Skip to content

非公式本サイトは非公式の日本語ドキュメントであり、Cloudflare 公式サイトではありません。最新情報はdevelopers.cloudflare.comをご確認ください。

単一ツールの Code Mode MCP サーバーを構築する

最終更新 Markdown で表示Agent セットアップ

codeMcpServer() で、既存の Model Context Protocol (MCP) サーバーをラップします。MCP クライアントは、上流の全ツールではなく、1 つの code ツールを受け取ります。

code ツールには、上流ツール向けに生成された型定義が含まれます。モデルが書いた JavaScript は複数のツールを呼び、結果を処理し、1 つの焦点を絞った値を返せます。

前提条件

Cloudflare Workers プロジェクトと、既存の McpServer が必要です。

codeMcpServer() は現在、SDK v1 サーバーを返します。明示的なレガシー createLegacyMcpHandler API 経由で提供します。

サーバーをラップする

  1. Code Mode と MCP 依存関係をインストールします。

    npm i @cloudflare/codemode agents @modelcontextprotocol/sdk zod
  2. Worker Loader バインディングと nodejs_compat 互換フラグを追加します。

    {
      "$schema": "./node_modules/wrangler/config-schema.json",
      "name": "codemode-mcp-server",
      "main": "src/server.ts",
      // Set this to today's date
      "compatibility_date": "2026-09-20",
      "compatibility_flags": [
        "nodejs_compat"
      ],
      "worker_loaders": [
        {
          "binding": "LOADER"
        }
      ]
    }
    name = "codemode-mcp-server"
    main = "src/server.ts"
    # Set this to today's date
    compatibility_date = "2026-09-20"
    compatibility_flags = ["nodejs_compat"]
    
    [[worker_loaders]]
    binding = "LOADER"
  3. 上流サーバーを作り、codeMcpServer() に渡します。

    src/server.jsjs
    import { DynamicWorkerExecutor } from "@cloudflare/codemode";
    import { codeMcpServer } from "@cloudflare/codemode/mcp";
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { createLegacyMcpHandler } from "agents/mcp";
    import { z } from "zod";
    
    function createOrderServer() {
    	const server = new McpServer({
    		name: "orders",
    		version: "1.0.0",
    	});
    
    	server.registerTool(
    		"get_order",
    		{
    			description: "Get an order by ID",
    			inputSchema: {
    				orderId: z.string().describe("Order ID"),
    			},
    		},
    		async ({ orderId }) => ({
    			structuredContent: {
    				id: orderId,
    				status: "processing",
    			},
    			content: [
    				{
    					type: "text",
    					text: JSON.stringify({ id: orderId, status: "processing" }),
    				},
    			],
    		}),
    	);
    
    	return server;
    }
    
    export default {
    	async fetch(request, env, ctx) {
    		const upstream = createOrderServer();
    		const executor = new DynamicWorkerExecutor({ loader: env.LOADER });
    		const server = await codeMcpServer({
    			server: upstream,
    			executor,
    		});
    
    		return createLegacyMcpHandler(server, { route: "/mcp" })(request, env, ctx);
    	},
    };
    src/server.tsts
    import { DynamicWorkerExecutor } from "@cloudflare/codemode";
    import { codeMcpServer } from "@cloudflare/codemode/mcp";
    import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
    import { createLegacyMcpHandler } from "agents/mcp";
    import { z } from "zod";
    
    function createOrderServer() {
    	const server = new McpServer({
    		name: "orders",
    		version: "1.0.0",
    	});
    
    	server.registerTool(
    		"get_order",
    		{
    			description: "Get an order by ID",
    			inputSchema: {
    				orderId: z.string().describe("Order ID"),
    			},
    		},
    		async ({ orderId }) => ({
    			structuredContent: {
    				id: orderId,
    				status: "processing",
    			},
    			content: [
    				{
    					type: "text",
    					text: JSON.stringify({ id: orderId, status: "processing" }),
    				},
    			],
    		}),
    	);
    
    	return server;
    }
    
    export default {
    	async fetch(request, env, ctx): Promise<Response> {
    		const upstream = createOrderServer();
    		const executor = new DynamicWorkerExecutor({ loader: env.LOADER });
    		const server = await codeMcpServer({
    			server: upstream,
    			executor,
    		});
    
    		return createLegacyMcpHandler(server, { route: "/mcp" })(
    			request,
    			env,
    			ctx,
    		);
    	},
    } satisfies ExportedHandler<Env>;
  4. Worker をデプロイします。

    npx wrangler deploy
  5. MCP クライアントで https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/mcp に接続します。サーバーが code という名前のツールを 1 つ公開していることを確認します。

モデルは code ツール内で、生成された codemode 名前空間を使えます。

async () => {
	const order = await codemode.get_order({ orderId: "order-123" });
	return { id: order.id, status: order.status };
};

上流ツールが structuredContent を返すと、Code Mode はその値を直接公開します。テキストのみの内容は結合され、可能なら JSON として解析されます。上流の MCP エラーは、モデルが書いたコードが catch できる例外になります。テキストとバイナリが混在する内容は、MCP 結果構造のままです。

カスタム description を渡す場合、生成された TypeScript 宣言を置く位置に {{types}} を使います。SDK が最初の上流 MCP ツールに基づく呼び出し例を挿入する位置には {{example}} を使います。どちらも任意です。

上流操作を保護する

codeMcpServer() は、上流ツール呼び出しごとの耐久承認を提供しません。外側の code ツール内から上流ハンドラーを呼び出します。

副作用を適用する前に、各上流ハンドラーで認可と、必要な操作ごとの承認を強制します。ツール結果に認証情報を含めないでください。

DynamicWorkerExecutor は、デフォルトで外部の fetch()connect() をブロックします。生成コードが外部システムに届くのは、上流 MCP ツール経由だけです。

結果を制限する

モデルが書いたコードは、返す前に上流データを選択、マップ、集約、ページングできます。大きな中間結果がモデルコンテキストに入るのを防ぎます。

公開側は最終 MCP 応答を、推定トークン約 6,000 に制限します。それを超える応答は切り捨てられ、--- TRUNCATED --- マーカーが付きます。上流ツールがすでに行った作業は減りません。

OpenAPI サービスを別々の searchexecute ツールで公開するには、検索と実行の MCP サーバーを構築する を参照してください。

役に立ちましたか?