使用 McpConnector 在 Code Mode 沙箱内暴露现有 Model Context Protocol (MCP) 客户端连接中的工具。连接器与持久运行时配合,含发现、审批与执行历史。
本页涵盖 Agent 消费 MCP 服务器。要将 Code Mode 发布为 MCP 服务器,请参阅 Code Mode MCP 服务器模式。
需要:
- 已配置 持久 Code Mode 运行时 的项目。该设置提供 Worker Loader 绑定与
CodemodeRuntime导出。 - 现有 Agents SDK MCP 连接。创建与授权连接请参阅 McpClient API。
-
安装 Code Mode
若项目尚未包含 Code Mode,安装
@cloudflare/codemode:npm i @cloudflare/codemodeyarn add @cloudflare/codemodepnpm add @cloudflare/codemodebun add @cloudflare/codemode -
创建 MCP connector
在独立文件中创建 connector。它是 plain class,无特殊文件名或 import 语法。
src/github-connector.jsjs import { McpConnector } from "@cloudflare/codemode"; export class GithubConnector extends McpConnector { connection; constructor(ctx, env, connection) { super(ctx, env); this.connection = connection; } name() { return "github"; } instructions() { return "Use for GitHub repositories, issues, and pull requests."; } createConnection() { return this.connection; } tool(name, tool) { if (name === "create_issue") { return { ...tool, requiresApproval: true }; } return tool; } }src/github-connector.tsts import { McpConnector, type ConnectorTool, type McpConnectionLike, } from "@cloudflare/codemode"; export class GithubConnector extends McpConnector<Env> { private connection: McpConnectionLike; constructor( ctx: DurableObjectState | ExecutionContext, env: Env, connection: McpConnectionLike, ) { super(ctx, env); this.connection = connection; } override name() { return "github"; } protected override instructions() { return "Use for GitHub repositories, issues, and pull requests."; } protected override createConnection() { return this.connection; } protected override tool( name: string, tool: ConnectorTool, ): ConnectorTool { if (name === "create_issue") { return { ...tool, requiresApproval: true }; } return tool; } }createConnection()返回现有 Agents SDK 连接。name()定义沙箱全局,因此此连接器在github下暴露方法。每个运行时内连接器名称须唯一。McpConnector为每个发现的 MCP 工具创建一个带类型的沙箱方法。从 MCP schema 推导方法类型。每个方法通过connection.client.callTool()调用原始工具。连接器将 MCP 工具名称清理为有效 JavaScript 标识符。例如
list-pull.requests变为list_pull_requests,3d-render变为_3d_render,delete变为delete_。若两个源名产生相同标识符,连接器抛出错误。重写toolName()以消歧。tool()装饰钩子按清理后的名称接收每个生成方法。此例中钩子将create_issue标记为需审批。持久运行时在执行该方法前暂停,审批后恢复运行。 -
将 connector 加入 runtime
在 Agent 中找到现有 MCP 连接并传给 connector。创建 Code Mode runtime 时包含 connector:
src/server.jsjs import { Agent } from "agents"; import { createCodemodeRuntime, DynamicWorkerExecutor, } from "@cloudflare/codemode"; import { GithubConnector } from "./github-connector"; export class Chat extends Agent { async codemodeRuntime() { await this.mcp.waitForConnections(); const server = this.mcp .listServers() .find((server) => server.name === "github"); if (!server) { throw new Error("GitHub MCP server is not registered."); } const connection = this.mcp.mcpConnections[server.id]; if (!connection) { throw new Error("GitHub MCP connection is not available."); } return createCodemodeRuntime({ ctx: this.ctx, executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }), connectors: [new GithubConnector(this.ctx, this.env, connection)], }); } }src/server.tsts import { Agent } from "agents"; import { createCodemodeRuntime, DynamicWorkerExecutor, } from "@cloudflare/codemode"; import { GithubConnector } from "./github-connector"; export class Chat extends Agent<Env> { private async codemodeRuntime() { await this.mcp.waitForConnections(); const server = this.mcp .listServers() .find((server) => server.name === "github"); if (!server) { throw new Error("GitHub MCP server is not registered."); } const connection = this.mcp.mcpConnections[server.id]; if (!connection) { throw new Error("GitHub MCP connection is not available."); } return createCodemodeRuntime({ ctx: this.ctx, executor: new DynamicWorkerExecutor({ loader: this.env.LOADER }), connectors: [ new GithubConnector(this.ctx, this.env, connection), ], }); } }先 await
codemodeRuntime(),然后将runtime.tool()作为codemode工具传给模型。调用审批、拒绝、回滚或代码片段方法前再次 await 该辅助方法。这确保 MCP 连接在休眠后完成恢复。若运行时属于
Thinkagent,将 MCP 工具排除在直接模型工具集外:import { Think } from "@cloudflare/think"; export class Chat extends Think { includeMcpTools = false; waitForMcpConnections = true; }import { Think } from "@cloudflare/think"; export class Chat extends Think<Env> { includeMcpTools = false; waitForMcpConnections = true; }includeMcpTools = false跳过 Think 的自动getAITools()调用。MCP 连接仍对McpConnector可用。 -
让模型发现并调用 tool
告诉模型在调用不熟悉的方法前使用
codemode.search()与codemode.describe()。模型生成的沙箱代码可发现并调用生成的方法:async () => { const matches = await codemode.search("open pull requests"); const docs = await codemode.describe(matches.results[0].path); const pullRequests = await github.list_pull_requests({ owner: "cloudflare", repo: "agents", state: "open", }); return { docs, pullRequests }; };codemode.search()返回 ranked connector 方法。codemode.describe()返回 connector 或方法的 TypeScript 文档。这使模型仅在需要时加载 tool 详情。
当模型调用 github.create_issue() 时,运行时返回已暂停的执行。通过运行时审批该执行以执行 MCP 工具并继续同一沙箱程序。
对无需持久审批或 codemode.search()/codemode.describe() 的较小集成,将 Agents SDK 工具集合直接传给 createCodeTool():
import { DynamicWorkerExecutor } from "@cloudflare/codemode";
import { createCodeTool } from "@cloudflare/codemode/ai";
await this.mcp.waitForConnections();
const executor = new DynamicWorkerExecutor({ loader: this.env.LOADER });
const codemode = createCodeTool({
tools: this.mcp.getAITools(),
executor,
});import { DynamicWorkerExecutor } from "@cloudflare/codemode";
import { createCodeTool } from "@cloudflare/codemode/ai";
await this.mcp.waitForConnections();
const executor = new DynamicWorkerExecutor({ loader: this.env.LOADER });
const codemode = createCodeTool({
tools: this.mcp.getAITools(),
executor,
});此方式在默认 codemode 命名空间下暴露 MCP 工具。不使用连接器运行时的持久暂停、审批与恢复流程。当工具可产生副作用或模型需要按需发现时使用 McpConnector。
getAITools() 转换 MCP 输入输出 schema 供 AI SDK 使用。Agents SDK 复用这些转换 schema,每个实时连接保持相同当前目录。仅需检查原始 MCP 目录时使用 this.mcp.listTools()。