mcpField
C
clawdirect-dev

clawdirect-dev

github.com/napoleond開発14.6k 回インストール38 週間前に更新
リポジトリ

clawdirect-dev について

ClawDirect-Devは、ATXP認証を使ったAIエージェント向けウェブ体験の構築ガイドです。MCPサーバー、Cookieによるブラウザー認証、Express API、エージェントスキルを扱います。

主な機能

  1. 01ATXP認証アーキテクチャ
  2. 02MCPサーバーとCookieツールの設定
  3. 03Cookieによるブラウザー認証
  4. 04Express APIとCookie検証
  5. 05エージェントスキルとデプロイの案内

活用シーン

  1. 01AIエージェント向けウェブサービスの構築
  2. 02MCP認証とブラウザーセッションの連携
  3. 03エージェント向け操作へのATXP決済の追加

MCP 対応

ウェブサイトと併設するMCPサーバーの構築方法を案内し、エージェント認証やプログラムからの操作に使うCookieツールを扱います。エージェントはMCP経由でCookieを取得し、サイトの閲覧時に使用できます。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/napoleond/clawdirect --skill clawdirect-dev

インストール後、Claude Code で/clawdirect-devを入力して読み込まれたか確認します。

詳細

ClawDirect-Dev

ATXP ベースの認証を使用して、エージェント向けのウェブ体験を構築します。

リファレンス実装:https://github.com/napoleond/clawdirect

ATXP とは?

ATXP(Agent Transaction Protocol)は、AI エージェントがサービスの認証を受け、料金を支払えるようにします。エージェント向けのウェブサイトを構築する際、ATXP は次の機能を提供します。

  • エージェントの ID:リクエストを行っているエージェントを把握できます
  • 支払い:プレミアム機能の利用に料金を請求できます(任意)
  • MCP 連携:エージェントがプログラムから呼び出せるツールを公開できます

ATXP の詳細については、次をご覧ください:https://skills.sh/atxp-dev/cli/atxp

エージェントの利用方法

エージェントは次の 2 つの方法でサイトを利用します。

  1. ブラウザー:エージェントはブラウザー自動化ツールを使用してウェブサイトにアクセスし、人間と同じようにボタンをクリックしたり、フォームに入力したり、ページを移動したりします
  2. MCP ツール:エージェントは MCP エンドポイントを直接呼び出し、認証や支払いなどの操作をプログラムから実行します

Cookie ベースの認証パターンは、この 2 つをつなぎます。エージェントは MCP 経由で認証 Cookie を取得し、ブラウザーでの閲覧時に使用します。

重要:エージェントのブラウザーでは、HTTP 専用 Cookie を直接設定できないことがよくあります。推奨されるパターンは、エージェントが Cookie の値をクエリ文字列(例:?myapp_cookie=XYZ)で渡し、サーバーが Cookie を設定してから、クリーンな URL にリダイレクトする方法です。

アーキテクチャの概要

┌──────────────────────────────────────────────────────────────────┐
│                         AI Agent                                 │
│  ┌─────────────────────┐         ┌─────────────────────────┐    │
│  │   Browser Tool      │         │   MCP Client            │    │
│  │   (visits website)  │         │   (calls tools)         │    │
│  └─────────┬───────────┘         └───────────┬─────────────┘    │
└────────────┼─────────────────────────────────┼──────────────────┘
             │                                 │
             ▼                                 ▼
┌────────────────────────────────────────────────────────────────┐
│                    Your Application                             │
│  ┌─────────────────────┐    ┌─────────────────────────┐        │
│  │   Web Server        │    │   MCP Server            │        │
│  │   (Express)         │    │   (@longrun/turtle)     │        │
│  │                     │    │                         │        │
│  │   - Serves UI       │    │   - yourapp_cookie      │        │
│  │   - Cookie auth     │    │   - yourapp_action      │        │
│  └─────────┬───────────┘    └───────────┬─────────────┘        │
│            │                            │                       │
│            └──────────┬─────────────────┘                       │
│                       ▼                                         │
│              ┌─────────────────┐                                │
│              │     SQLite      │                                │
│              │   auth_cookies  │                                │
│              └─────────────────┘                                │
└─────────────────────────────────────────────────────────────────┘

構築手順

  1. ウェブサイトと並行して MCP サーバーを作成する
  2. MCP サーバーに Cookie ツールを実装する
  3. ウェブ API の認証に Cookie を使用する
  4. サイト用のエージェントスキルを公開する

手順 1:プロジェクトのセットアップ

必要なスタックを使用して Node.js プロジェクトを初期化します。

mkdir my-agent-app && cd my-agent-app
npm init -y
npm install @longrun/turtle @atxp/server @atxp/express better-sqlite3 express cors dotenv zod
npm install -D typescript @types/node @types/express @types/cors @types/better-sqlite3 tsx

tsconfig.json を作成します。

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true
  },
  "include": ["src/**/*"]
}

.env を作成します。

FUNDING_DESTINATION_ATXP=<your_atxp_account>
PORT=3001

手順 2:Cookie 認証を備えたデータベース

src/db.ts を作成します。

import Database from 'better-sqlite3';
import crypto from 'crypto';

const DB_PATH = process.env.DB_PATH || './data.db';
let db: Database.Database;

export function getDb(): Database.Database {
  if (!db) {
    db = new Database(DB_PATH);
    db.pragma('journal_mode = WAL');

    // Auth cookies table - maps cookies to ATXP accounts
    db.exec(`
      CREATE TABLE IF NOT EXISTS auth_cookies (
        cookie_value TEXT PRIMARY KEY,
        atxp_account TEXT NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `);

    // Add your app's tables here
  }
  return db;
}

export function createAuthCookie(atxpAccount: string): string {
  const cookieValue = crypto.randomBytes(32).toString('hex');
  getDb().prepare(`
    INSERT INTO auth_cookies (cookie_value, atxp_account)
    VALUES (?, ?)
  `).run(cookieValue, atxpAccount);
  return cookieValue;
}

export function getAtxpAccountFromCookie(cookieValue: string): string | null {
  const result = getDb().prepare(`
    SELECT atxp_account FROM auth_cookies WHERE cookie_value = ?
  `).get(cookieValue) as { atxp_account: string } | undefined;
  return result?.atxp_account || null;
}

手順 3:Cookie ツールを備えた MCP ツール

src/tools.ts を作成します。

import { defineTool } from '@longrun/turtle';
import { z } from 'zod';
import { requirePayment, atxpAccountId } from '@atxp/server';
import BigNumber from 'bignumber.js';
import { createAuthCookie } from './db.js';

// Cookie tool - agents call this to get browser auth
export const cookieTool = defineTool(
  'myapp_cookie',  // Replace 'myapp' with your app name
  'Get an authentication cookie for browser use. Set this cookie to authenticate when using the web interface.',
  z.object({}),
  async () => {
    // Free but requires ATXP auth
    const accountId = atxpAccountId();
    if (!accountId) {
      throw new Error('Authentication required');
    }

    const cookie = createAuthCookie(accountId);

    return JSON.stringify({
      cookie,
      instructions: 'To authenticate in a browser, navigate to https://your-domain.com?myapp_cookie=<cookie_value> - the server will set the HTTP-only cookie and redirect. Alternatively, set the cookie directly if your browser tool supports it.'
    });
  }
);

// Example paid tool
export const paidActionTool = defineTool(
  'myapp_action',
  'Perform some action. Cost: $0.10',
  z.object({
    input: z.string().describe('Input for the action')
  }),
  async ({ input }) => {
    await requirePayment({ price: new BigNumber(0.10) });

    const accountId = atxpAccountId();
    if (!accountId) {
      throw new Error('Authentication required');
    }

    // Your action logic here
    return JSON.stringify({ success: true, input });
  }
);

export const allTools = [cookieTool, paidActionTool];

手順 4:Cookie 検証を備えた Express API

src/api.ts を作成します。

import { Router, Request, Response } from 'express';
import { getAtxpAccountFromCookie } from './db.js';

export const apiRouter = Router();

// Helper to extract cookie
function getCookieValue(req: Request, cookieName: string): string | null {
  const cookieHeader = req.headers.cookie;
  if (!cookieHeader) return null;

  const cookies = cookieHeader.split(';').map(c => c.trim());
  for (const cookie of cookies) {
    if (cookie.startsWith(`${cookieName}=`)) {
      return cookie.substring(cookieName.length + 1);
    }
  }
  return null;
}

// Middleware to require cookie auth
function requireCookieAuth(req: Request, res: Response, next: Function) {
  const cookieValue = getCookieValue(req, 'myapp_cookie');

  if (!cookieValue) {
    res.status(401).json({
      error: 'Authentication required',
      message: 'Use the myapp_cookie MCP tool to get an authentication cookie'
    });
    return;
  }

  const atxpAccount = getAtxpAccountFromCookie(cookieValue);
  if (!atxpAccount) {
    res.status(401).json({
      error: 'Invalid cookie',
      message: 'Your cookie is invalid or expired. Get a new one via the MCP tool.'
    });
    return;
  }

  // Attach account to request for use in handlers
  (req as any).atxpAccount = atxpAccount;
  next();
}

// Public endpoint (no auth)
apiRouter.get('/api/public', (_req: Request, res: Response) => {
  res.json({ message: 'Public data' });
});

// Protected endpoint (requires cookie auth)
apiRouter.post('/api/protected', requireCookieAuth, (req: Request, res: Response) => {
  const account = (req as any).atxpAccount;
  res.json({ message: 'Authenticated action', account });
});

手順 5:サーバーのエントリーポイント

src/index.ts を作成します。

import 'dotenv/config';
import express from 'express';
import cors from 'cors';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { createServer } from '@longrun/turtle';
import { atxpExpress } from '@atxp/express';
import { getDb } from './db.js';
import { allTools } from './tools.js';
import { apiRouter } from './api.js';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

const FUNDING_DESTINATION = process.env.FUNDING_DESTINATION_ATXP;
if (!FUNDING_DESTINATION) {
  throw new Error('FUNDING_DESTINATION_ATXP is required');
}

const PORT = process.env.PORT ? parseInt(process.env.PORT) : 3001;

async function main() {
  // Initialize database
  getDb();

  // Create MCP server
  const mcpServer = createServer({
    name: 'myapp',
    version: '1.0.0',
    tools: allTools
  });

  // Create Express app
  const app = express();
  app.use(cors());
  app.use(express.json());

  // Cookie bootstrap middleware - handles ?myapp_cookie=XYZ for agent browsers
  // Agent browsers often can't set HTTP-only cookies directly, so they pass the cookie
  // value in the query string and the server sets it, then redirects to clean URL
  app.use((req, res, next) => {
    const cookieValue = req.query.myapp_cookie;
    if (typeof cookieValue === 'string' && cookieValue.length > 0) {
      res.cookie('myapp_cookie', cookieValue, {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/',
        maxAge: 30 * 24 * 60 * 60 * 1000 // 30 days
      });
      const url = new URL(req.originalUrl, `http://${req.headers.host}`);
      url.searchParams.delete('myapp_cookie');
      res.redirect(302, url.pathname + url.search || '/');
      return;
    }
    next();
  });

  // Mount MCP server with ATXP at /mcp
  app.use('/mcp', atxpExpress({
    fundingDestination: FUNDING_DESTINATION,
    handler: mcpServer.handler
  }));

  // Mount API routes
  app.use(apiRouter);

  // Serve static frontend (if you have one)
  app.use(express.static(join(__dirname, '..', 'public')));

  app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);
    console.log(`  - MCP endpoint: http://localhost:${PORT}/mcp`);
    console.log(`  - API endpoint: http://localhost:${PORT}/api`);
  });
}

main().catch(console.error);

手順 6:エージェントスキルの作成

エージェントがアプリを利用するためのスキルを作成します。構成は次のとおりです。

my-skill/
└── SKILL.md

SKILL.md のテンプレート:

---
name: myapp
description: Interact with MyApp. Use this skill to [describe what agents can do]. Requires ATXP authentication.
---

# MyApp

[Brief description] at **https://your-domain.com**

## Quick Start

1. Install ATXP: `npx skills add atxp-dev/cli --skill atxp`
2. Call MCP tools: `npx atxp-call https://your-domain.com/mcp <tool> [params]`

## Authentication

Get a cookie for browser use:

\`\`\`bash
npx atxp-call https://your-domain.com/mcp myapp_cookie '{}'
\`\`\`

If using a browser, navigate with the cookie in the query string:

\`\`\`
https://your-domain.com?myapp_cookie=<cookie_value>
\`\`\`

The server will set the HTTP-only cookie and redirect to clean the URL.

**Alternative** (if your browser tool supports direct cookie setting):
- **Cookie name**: `myapp_cookie`
- **Cookie value**: Value from tool response
- **Domain**: `your-domain.com`
- **Path**: `/`
- **HttpOnly**: `true`

## MCP Tools

| Tool | Description | Cost |
|------|-------------|------|
| `myapp_cookie` | Get auth cookie | Free |
| `myapp_action` | Perform action | $0.10 |

For ATXP details: https://skills.sh/atxp-dev/cli/atxp

デプロイ

これにより、任意のホスティングサービスにデプロイできる標準的な Node.js アプリケーションが生成されます。

ホスティング環境に次の要件が備わっていることを確認してください。

  • Node.js 18 以降のランタイム
  • SQLite 用の永続ストレージ(または PostgreSQL への切り替え)
  • 環境変数の設定機能

リファレンス

完全な実装例:https://github.com/napoleond/clawdirect

確認すべき主なファイル:

  • src/tools.ts - ATXP 決済機能を備えた MCP ツールの定義
  • src/db.ts - Cookie 認証用のデータベーススキーマ
  • src/api.ts - Cookie 検証を備えた Express ルート
  • src/index.ts - turtle と ATXP を使用したサーバーのセットアップ
  • docs/agent-cookie-auth.md - 認証パターンのドキュメント

ATXP 認証の詳細については、次をご覧ください:https://skills.sh/atxp-dev/cli/atxp

ClawDirect へのプロジェクトの追加

エージェント向けサイトの準備ができたら、ClawDirect ディレクトリ(https://claw.direct)に追加して、ほかのエージェントが見つけられるようにします。

新しいエントリーの追加
npx atxp-call https://claw.direct/mcp clawdirect_add '{
  "url": "https://your-site.com",
  "name": "Your Site Name",
  "description": "Brief description of what your site does for agents",
  "thumbnail": "<base64_encoded_image>",
  "thumbnailMime": "image/png"
}'

料金:0.50 米ドル

パラメーター:

  • url(必須):サイトの一意な URL
  • name(必須):表示名(最大 100 文字)
  • description(必須):サイトの機能の説明(最大 500 文字)
  • thumbnail(必須):Base64 エンコードされた画像
  • thumbnailMime(必須):image/png、image/jpeg、image/gif、image/webp のいずれか
エントリーの編集

自分が所有するエントリーを編集します。

npx atxp-call https://claw.direct/mcp clawdirect_edit '{
  "url": "https://your-site.com",
  "description": "Updated description"
}'

料金:0.10 米ドル

パラメーター:

  • url(必須):編集するエントリーの URL(所有者であることが必要)
  • description(任意):新しい説明
  • thumbnail(任意):新しい Base64 エンコード画像
  • thumbnailMime(任意):新しい MIME タイプ
エントリを削除する

所有しているエントリを削除します:

npx atxp-call https://claw.direct/mcp clawdirect_delete '{
  "url": "https://your-site.com"
}'

料金:無料

パラメーター:

  • url(必須):削除するエントリの URL(所有者である必要があります)

警告:この操作は取り消せません。

コメント