novice1248

workers-mcp-starter

Community novice1248
Updated

Minimal remote MCP server starter on Cloudflare Workers — stateless Streamable HTTP, Bearer + OAuth 2.1 (claude.ai connector ready), D1-backed tools, integration-tested

workers-mcp-starter

Cloudflare Workers 上で動くリモート MCP サーバーの最小スターター。SDK に頼らず、Streamable HTTP の JSON-RPC を素の fetch ハンドラで直接処理する stateless 構成です。

サンプルとして D1 の notes テーブルに対する CRUD ツール 5 つを載せています。ツール定義とハンドラを差し替えれば、自分のデータを Claude に繋ぐサーバーになります。

特徴

  • 依存が薄い@modelcontextprotocol/sdk も Agents SDK(Durable Objects 前提)も使わない。プロトコル処理は src/mcp-server.ts の素の JSON-RPC ディスパッチのみ。セッション ID を発行しない stateless な Streamable HTTP JSON-RPC 実装(protocolVersion 2025-06-18 を返す。単一バージョンのみ対応で、複数版ネゴシエーションは未実装)
  • 2系統の認証
    • Bearer 共有シークレット(MCP_API_TOKEN)— Claude Code 等ヘッダを設定できるクライアント向け。SHA-256 ハッシュ化+定数時間比較でタイミング攻撃を避ける
    • OAuth 2.1(src/oauth.ts)— claude.ai のカスタムコネクタ向け。claude.ai は任意ヘッダを設定できず、MCP 仕様の Authorization フロー(RFC9728/RFC8414/RFC7591 DCR/RFC7636 PKCE)を話せるサーバーにしか繋がらない。必要なのは KV だけで、Durable Objects 不要
  • 統合テスト — 実 D1(miniflare)相手に SELF.fetch で認証・プロトコル・ツール実行を一気通貫で検証(src/mcp-server.workers.test.ts)

セットアップ

npm install
npx wrangler d1 create workers-mcp-starter   # 出力されたdatabase_idをwrangler.jsoncに反映
npm run db:migrate:remote                     # notesテーブル作成
npx wrangler secret put MCP_API_TOKEN         # 十分に長いランダム値(例: openssl rand -hex 32)
npm run deploy

Claude Code から接続する(.mcp.json):

{
  "mcpServers": {
    "my-notes": {
      "type": "http",
      "url": "https://<your-worker>.workers.dev/mcp",
      "headers": { "Authorization": "Bearer <MCP_API_TOKEN>" }
    }
  }
}

claude.ai カスタムコネクタから接続する(OAuth)

  1. npx wrangler kv namespace create MCP_OAUTH_KV → 出力された id を wrangler.jsonc に反映して再デプロイ
  2. claude.ai の設定 → コネクタ → カスタムコネクタ追加で https://<your-worker>.workers.dev/mcp を指定
  3. 同意画面が開くので MCP_API_TOKEN を入力して許可する

OAuth を使わないなら KV バインディングごと削除してよい(関連エンドポイントは静かに 404 になる)。

設計メモ(なぜこの形か)

  • クエリパラメータでのトークン受け渡しはしない。 URL はシェル履歴・アクセスログ・Referer に残る。Bearer ヘッダのみ
  • トークンは平文で保存しない。 OAuth のアクセス/リフレッシュトークンは SHA-256 ハッシュを KV キーにして保存し、KV の内容が漏れても原文を復元できない
  • DCR は開放、認可はシークレットで防衛。 クライアント登録(RFC7591)は未認証で誰でもできるが、登録しただけでは何のデータにも触れない。実際の認可は同意画面での MCP_API_TOKEN 入力が必要。登録レコードには TTL を付け、bot の大量登録で KV が膨らみ続けるのを防ぐ
  • redirect_uri は登録値との完全一致のみ(オープンリダイレクト対策)。https 以外は http://localhost / http://127.0.0.1(ローカル開発用)を除き登録段階で拒否、フラグメント付き URI も拒否(OAuth 2.1)
  • PKCE(S256)必須、plain 不可。 code_verifier は RFC7636 の形式(43〜128 文字の unreserved)を検証。resource(RFC8707)は指定されるなら自サーバーの正準 URI と完全一致を要求し、認可時に束縛された値はトークン交換でも同じ値を必須にする(confused deputy 対策)
  • 認可コード・リフレッシュトークンはワンタイム。 既知の限界: Workers KV は get/delete がアトミックでないため、理論上ごく短い時間窓の同時リクエストが両方通過しうる。真の単一利用保証には Durable Objects が要るが、シングルユーザー用途では許容している(コード内コメント参照)
  • 同意画面はクリックジャッキング禁止X-Frame-Options: DENY / CSP frame-ancestors 'none')。/mcp はトークン認証のみで Cookie を使わないため、ブラウザ系クライアント向けに CORS(*)と OPTIONS プリフライトを許可している
  • ドメインエラーは JSON-RPC エラーではなく isError 付き正常応答で返す。 MCP クライアント(LLM)がエラーメッセージを読んで次の手を選べるようにするため

自分のツールに差し替える

  1. schema.sql を自分のテーブル定義に変更
  2. src/mcp-server.ts の TOOLS(ツール定義)と callTool()(ディスパッチ)、各 tool*() ハンドラを差し替え
  3. テストを合わせて更新して npm test

開発

npm run dev        # ローカル起動(D1はローカルシミュレーション)
npm test           # 統合テスト(実D1/miniflare)
npm run typecheck

License

MIT

MCP Server · Populars

MCP Server · New

    laurentvv

    Web Crawler MCP

    Web crawling tool that integrates with AI assistants via the MCP

    Community laurentvv
    anypost

    emailmd

    Render markdown into email-safe HTML

    Community anypost
    dinglebear-ai

    Unraid MCP

    Query, monitor, and manage Unraid servers via GraphQL API through MCP tools. Supports system info, Docker, VMs, array/parity, notifications, plugins, rclone, and live telemetry.

    Community dinglebear-ai
    superbasedapp

    SuperBased Observer

    Local-first control plane for AI coding agents — launch browser terminals, run and remotely control sessions, and track files, tokens & cost across Claude Code, Codex, Cursor, Gemini CLI and 20+ more. 100% local, no telemetry.

    Community superbasedapp
    OpenMarkdown-dev

    OpenMarkdown

    Feather-light. Light-speed.

    Community OpenMarkdown-dev