Context Mode 的核心适配机制之一是动态平台工具命名系统。该系统通过 createToolNamer 工厂函数,为 Claude Code、Gemini CLI、Cursor 等 15 个平台生成符合各自规范的 ctx_* 工具名称(如 mcp__plugin_context-mode_context-mode__ctx_execute 或裸名 ctx_execute)。随后,createRoutingBlock 利用此命名函数生成定制的 XML 路由指导,确保 LLM 在不同客户端中都能正确识别并调用沙箱工具,从而保障上下文节省策略的统一执行。
Context Mode 的平台工具命名系统:跨 15 个平台的 ctx_* 工具名称映射与路由块生成
Context Mode 作为一个 MCP 服务器插件,需要适配多种 AI 编码平台。一个关键挑战是,不同平台对 MCP 工具名称的呈现格式有各自约定。例如,Claude Code 要求工具名带有一长串插件前缀,而 Cursor 或 Codex 则直接使用裸名。如果工具名称在 LLM 的上下文中不匹配,平台将无法识别或路由这些调用。Context Mode 的工具命名系统正是为了解决此问题而设计,它作为适配器系统的基础层,确保 ctx_execute、ctx_search 等核心工具在任何平台都能被正确调用。
工具命名映射:从平台 ID 到工具名前缀的转换
工具命名的核心是一个预定义的映射表 TOOL_PREFIXES。它存储了 15 个已知平台的命名函数,每个函数接收一个基础工具名(如 ctx_execute),并返回该平台下的完整名称。
const TOOL_PREFIXES = {
"claude-code": (tool) => `mcp__plugin_context-mode_context-mode__${tool}`,
"gemini-cli": (tool) => `mcp__context-mode__${tool}`,
"cursor": (tool) => tool, // 裸名
"kiro": (tool) => `@context-mode/${tool}`,
"zed": (tool) => `mcp:context-mode:${tool}`,
// ... 其他平台
};
从代码证据中可以清晰地看到几种主要模式:
- 长前缀模式:如
claude-code,采用mcp__plugin_context-mode_context-mode__<tool>格式。 - 中等前缀模式:如
gemini-cli和antigravity,使用mcp__context-mode__<tool>。 - 下划线分隔模式:如
opencode和vscode-copilot,使用context-mode_<tool>。 - 裸名模式:如
cursor、codex和pi,工具名不附加任何前缀。 - 特殊符号模式:如
kiro使用@context-mode/<tool>,zed使用mcp:context-mode:<tool>。
系统通过 getToolName(platform, bareTool) 函数进行转换。如果传入了未知的平台 ID,它会优雅地回退到 claude-code 的命名约定,确保功能不会完全失效。测试文件 tool-naming.test.ts 中的断言验证了这些映射的正确性,例如:
expect(getToolName("claude-code", "ctx_fetch_and_index")).toBe("mcp__plugin_context-mode_context-mode__ctx_fetch_and_index");
expect(getToolName("cursor", "ctx_fetch_and_index")).toBe("ctx_fetch_and_index");
expect(getToolName("kiro", "ctx_execute_file")).toBe("@context-mode/ctx_execute_file");
createToolNamer 工厂函数则封装了这个过程,它返回一个绑定到特定平台的命名函数 t。这个函数随后被注入到路由指导的生成逻辑中。
路由块生成:为不同平台定制 XML 指导
Context Mode 的钩子系统(如 SessionStart 和 PreToolUse)会向 LLM 注入结构化的指导信息,引导其优先使用 ctx_* 沙箱工具,从而节省上下文窗口。createRoutingBlock(t) 函数负责生成这段 XML 核心指导,其中 t 就是上文由 createToolNamer 创建的平台特定命名函数。
指导内容是一个模板,其中工具名称的位置都由 t("tool_name") 动态替换。以工具选择层次为例:
`1. GATHER: ${t("ctx_batch_execute")}(commands, queries)`
`2. FOLLOW-UP: ${t("ctx_search")}(queries: ["q1", "q2", ...])`
`3. PROCESSING: ${t("ctx_execute")}(language, code) | ${t("ctx_execute_file")}(path, language, code)`
当平台为 Gemini CLI 时,t 函数会将 ctx_batch_execute 转换为 mcp__context-mode__ctx_batch_execute;当平台为 Cursor 时,则直接使用 ctx_batch_execute。测试用例证实了这种动态生成:
it("produces block with platform-specific tool names for gemini-cli", () => {
const t = createToolNamer("gemini-cli");
const block = createRoutingBlock(t);
expect(block).toContain("mcp__context-mode__ctx_batch_execute");
expect(block).not.toContain("mcp__plugin_context-mode_context-mode__");
});
同样,其他指导块如 createReadGuidance、createBashGuidance 也采用相同的模式,确保针对 Read、Bash 等原生工具的拦截提示也能使用正确的 ctx_* 工具名。
向后兼容与扩展性
为了保持向后兼容,模块同时导出了基于默认 claude-code 命名的静态常量,如 ROUTING_BLOCK 和 EXTERNAL_MCP_GUIDANCE。这些常量用于未提供平台上下文的旧场景。测试代码中的“漂移守护”断言确保了静态导出与使用默认命名器的工厂函数输出完全一致。
当需要支持新平台时,开发者只需在 TOOL_PREFIXES 映射表中增加一个新的条目,并定义其命名函数。createToolNamer 和相关的路由生成函数无需任何修改,即可为新平台提供完整的支持。这体现了系统良好的开放封闭原则。
从测试中还可以看到,系统不仅能为 ctx_* 工具生成名称,还能处理外部 MCP 工具返回大数据的场景指导。createExternalMcpGuidance 生成的提示会引用平台正确的 ctx_execute 和 ctx_fetch_and_index 名称,引导 LLM 将数据先导入沙箱处理,避免污染上下文窗口。
总结
Context Mode 的平台工具命名系统,通过一个清晰的映射层和一套工厂函数,巧妙地解决了跨 15 个平台的 MCP 工具名称适配问题。它不仅是一个简单的字符串替换,更是连接底层沙箱工具与上层 LLM 路由指导的桥梁。该系统确保了无论用户使用 Claude Code、Gemini CLI 还是 Cursor,ctx_execute 等工具都能以其平台“母语”的形式被 LLM 识别和调用,从而将上下文节省的核心价值无缝且一致地交付给所有平台用户。对于希望深入理解其跨平台架构的开发者,可以进一步研究平台检测机制和安全防线。
FAQ
Q: 如果遇到一个不在预定义列表中的新平台,工具名会如何处理?
A: getToolName 函数会回退到 claude-code 的命名约定(即 mcp__plugin_context-mode_context-mode__ 前缀),确保基础功能可用,但可能需要针对新平台调整前缀格式以获得最佳兼容性。
Q: 路由块(Routing Block)是如何确保 LLM 遵循工具使用指导的?
A: 路由块以结构化的 XML 格式注入到 LLM 的会话中,明确列出了工具选择的优先级层次(如先使用 ctx_batch_execute 进行研究)、不同场景下的最佳工具选择(如分析文件用 ctx_execute_file 而非 Read),以及输出约束。这些指令结合了平台正确的工具名,直接引导 LLM 的决策路径,使其倾向于使用高效的沙箱工具,从而减少上下文消耗。