Skip to content

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

ツール

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

MCP ツールは、MCP サーバー がクライアントから呼べるよう公開する関数です。LLM はツールを呼び出してデータの検索、計算、API の呼び出しができます。MCP サーバーがツールを実行し、結果を返します。

ステートレスな createMcpHandler サーバーには @modelcontextprotocol/server を使います。McpAgent は非推奨で、機能は凍結されています。既存の McpAgent ルートは、移行中に限り @modelcontextprotocol/sdk だけを使い続けてください。

WebMCP の例

Cloudflare の McpAgent から MCP ツールを、Chrome の実験的な WebMCP API へ橋渡しします。

ツールの定義

server.registerTool() で、ステートレスな McpServer インスタンスにツールを登録します。各ツールには名前、説明、ZodValibot などのスキーマライブラリで定義した入力スキーマ、ハンドラー関数があります。

import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";

function createServer() {
	const server = new McpServer({ name: "Math", version: "1.0.0" });

	server.registerTool(
		"add",
		{
			description: "Add two numbers together",
			inputSchema: { a: z.number(), b: z.number() },
		},
		async ({ a, b }) => ({
			content: [{ type: "text", text: String(a + b) }],
		}),
	);

	return server;
}
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";

function createServer() {
	const server = new McpServer({ name: "Math", version: "1.0.0" });

	server.registerTool(
		"add",
		{
			description: "Add two numbers together",
			inputSchema: { a: z.number(), b: z.number() },
		},
		async ({ a, b }) => ({
			content: [{ type: "text", text: String(a + b) }],
		}),
	);

	return server;
}

ツールハンドラーは検証済みの入力を受け取り、content 配列を持つオブジェクトを返す必要があります。各コンテンツ項目には type(通常は "text")と対応するデータがあります。

ツールの結果

ツールの結果は、コンテンツパーツの配列として返ります。いちばん多い型は text ですが、画像や埋め込みリソースも返せます。

server.registerTool(
	"lookup",
	{
		description: "Look up a user by ID",
		inputSchema: { userId: z.string() },
	},
	async ({ userId }) => {
		const user = await db.getUser(userId);

		if (!user) {
			return {
				isError: true,
				content: [{ type: "text", text: `User ${userId} not found` }],
			};
		}

		return {
			content: [{ type: "text", text: JSON.stringify(user, null, 2) }],
		};
	},
);
server.registerTool(
	"lookup",
	{
		description: "Look up a user by ID",
		inputSchema: { userId: z.string() },
	},
	async ({ userId }) => {
		const user = await db.getUser(userId);

		if (!user) {
			return {
				isError: true,
				content: [{ type: "text", text: `User ${userId} not found` }],
			};
		}

		return {
			content: [{ type: "text", text: JSON.stringify(user, null, 2) }],
		};
	},
);

ツール呼び出しが失敗したことを示すには、isError: true を設定します。LLM はエラーメッセージを受け取り、次の対応を判断できます。

ツールの説明

description パラメーターは重要です。LLM はこれを読んで、ツールを呼ぶかどうか、いつ呼ぶかを決めます。説明は次のように書いてください。

  • 具体的に何をするかを書く: 「Weather tool」より「都市の現在の天気を取得する」
  • 入力を明確にする: 「都市名を文字列で指定する」と書くと、LLM が呼び出しを正しく整形しやすくなります
  • 制限を正直に書く: 「米国の都市のみ対応」と書けば、未対応の入力で呼ばれにくくなります

Zod による入力検証

ツール入力は Zod スキーマとして定義され、ハンドラー実行前に自動検証されます。各パラメーターの文脈を LLM に伝えるには、Zod の .describe() メソッドを使います。

server.registerTool(
	"search",
	{
		description: "Search for documents by query",
		inputSchema: {
			query: z.string().describe("The search query"),
			limit: z
				.number()
				.min(1)
				.max(100)
				.default(10)
				.describe("Maximum number of results to return"),
			category: z
				.enum(["docs", "blog", "api"])
				.optional()
				.describe("Filter by content category"),
		},
	},
	async ({ query, limit, category }) => {
		const results = await searchIndex(query, { limit, category });
		return {
			content: [{ type: "text", text: JSON.stringify(results) }],
		};
	},
);
server.registerTool(
	"search",
	{
		description: "Search for documents by query",
		inputSchema: {
			query: z.string().describe("The search query"),
			limit: z
				.number()
				.min(1)
				.max(100)
				.default(10)
				.describe("Maximum number of results to return"),
			category: z
				.enum(["docs", "blog", "api"])
				.optional()
				.describe("Filter by content category"),
		},
	},
	async ({ query, limit, category }) => {
		const results = await searchIndex(query, { limit, category });
		return {
			content: [{ type: "text", text: JSON.stringify(results) }],
		};
	},
);

createMcpHandler でツールを使う

ステートレスな MCP サーバーでは、ファクトリ関数内でツールを定義し、サーバーを createMcpHandler に渡します。

import { createMcpHandler } from "agents/mcp/server";
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";

function createServer() {
	const server = new McpServer({ name: "My Tools", version: "1.0.0" });

	server.registerTool(
		"ping",
		{ description: "Check if the server is alive", inputSchema: {} },
		async () => ({
			content: [{ type: "text", text: "pong" }],
		}),
	);

	return server;
}

export default {
	fetch(request, env, ctx) {
		return createMcpHandler(createServer)(request, env, ctx);
	},
};
import { createMcpHandler } from "agents/mcp/server";
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";

function createServer() {
	const server = new McpServer({ name: "My Tools", version: "1.0.0" });

	server.registerTool(
		"ping",
		{ description: "Check if the server is alive", inputSchema: {} },
		async () => ({
			content: [{ type: "text", text: "pong" }],
		}),
	);

	return server;
}

export default {
	fetch(request, env, ctx) {
		return createMcpHandler(createServer)(request, env, ctx);
	},
} satisfies ExportedHandler;

McpAgent でツールを使う

このセクションは、移行中の既存レガシールートにだけ当てはまります。ツールは McpAgentinit() メソッドで定義します。ツールは this 経由でエージェントインスタンスにアクセスできるので、状態の読み書きができます。

import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export class MyMCP extends McpAgent {
	server = new McpServer({ name: "Stateful Tools", version: "1.0.0" });

	async init() {
		this.server.tool(
			"incrementCounter",
			"Increment and return a counter",
			{},
			async () => {
				const count = (this.state?.count ?? 0) + 1;
				this.setState({ count });
				return {
					content: [{ type: "text", text: `Counter: ${count}` }],
				};
			},
		);
	}
}
import { McpAgent } from "agents/mcp";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";

export class MyMCP extends McpAgent {
	server = new McpServer({ name: "Stateful Tools", version: "1.0.0" });

	async init() {
		this.server.tool(
			"incrementCounter",
			"Increment and return a counter",
			{},
			async () => {
				const count = (this.state?.count ?? 0) + 1;
				this.setState({ count });
				return {
					content: [{ type: "text", text: `Counter: ${count}` }],
				};
			},
		);
	}
}

次のステップ

McpAgent API

ステートフル MCP サーバーのリファレンスです。

MCP 認可

MCP サーバーへ OAuth 認証を追加します。

役に立ちましたか?