← Создание агентов на Cloudflare / agents / model-context-protocol / guides
Создайте MCP-сервер Code Mode с одним инструментом
Используйте codeMcpServer() чтобы обернуть существующий сервер Model Context Protocol (MCP). MCP-клиенты получают один code инструмент вместо каждого вышестоящего инструмента.
code инструмент содержит сгенерированные определения типов для вышестоящих инструментов. Написанный моделью JavaScript может вызывать несколько инструментов, обрабатывать их результаты и возвращать одно целевое значение.
Предварительные требования
Вам понадобится проект Cloudflare Workers и существующий McpServer.
codeMcpServer() в настоящее время возвращает сервер SDK v1. Обслуживайте его через явный устаревший createLegacyMcpHandler API.
Оберните сервер
-
Установите Code Mode и зависимости MCP:
npm i @cloudflare/codemode agents @modelcontextprotocol/sdk zod -
Добавьте привязку 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-08-28", "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-08-28" compatibility_flags = ["nodejs_compat"] [[worker_loaders]] binding = "LOADER" -
Создайте вышестоящий сервер и передайте его в
codeMcpServer():src/server.jsimport { 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.tsimport { 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>; -
Разверните Worker:
npx wrangler deploy -
В клиенте MCP подключитесь к
https://<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.dev/mcp. Убедитесь, что сервер предоставляет один инструмент с именемcode.
Модель может использовать сгенерированный codemode пространство имён внутри code инструмент:
async () => {
const order = await codemode.get_order({ orderId: "order-123" });
return { id: order.id, status: order.status };
};Когда upstream-инструмент возвращает structuredContent, Code Mode передаёт это значение напрямую. Контент, состоящий только из текста, объединяется и по возможности разбирается как JSON. Ошибки вышестоящего MCP становятся исключениями, которые может перехватить код, написанный моделью. Смешанный текстовый и бинарный контент остаётся в исходной структуре результата MCP.
Если вы укажете собственный description, используйте {{types}} где должны появиться сгенерированные объявления TypeScript. Используйте {{example}} где SDK должен подставить пример вызова на основе первого вышестоящего инструмента MCP. Оба плейсхолдера необязательны.
Защита операций с upstream
codeMcpServer() не обеспечивает устойчивое подтверждение для каждого вышестоящего вызова инструмента. Он вызывает вышестоящие обработчики изнутри внешнего code инструмент.
Обеспечивайте авторизацию и любое необходимое подтверждение для отдельных операций в каждом вышестоящем обработчике перед применением побочных эффектов. Не включайте учётные данные в результаты инструментов.
DynamicWorkerExecutor блокирует внешние fetch() и connect() вызовы по умолчанию. Сгенерированный код может обращаться к внешним системам только через вышестоящие инструменты MCP.
Ограничение результатов
Код, написанный моделью, может выбирать нужные данные, преобразовывать и агрегировать их или разбивать на страницы перед возвратом результата. Это не позволяет большим промежуточным результатам попадать в контекст модели.
Publisher ограничивает итоговый ответ MCP примерно 6,000 оценочными токенами. Более крупный ответ обрезается и включает --- TRUNCATED --- маркер. Это не уменьшает объём работы, уже выполненной вышестоящими инструментами.
Чтобы опубликовать службу OpenAPI с отдельными search и execute инструменты, см. Создайте MCP-сервер типа найди и выполни.