Claude Code Router ToolHub 深度指南:用一个 MCP 入口懒加载全部低频工具,替 Agent 省 Context
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
ToolHub 是 Claude Code Router(CCR)内置的“工具聚合 + 懒加载”机制:它把多个后端 MCP 服务器的全部工具折叠成一个名为ccr-toolhub的 MCP 入口,只暴露tool_hub.resolve与tool_hub.invoke两个元工具。当 Agent 面对外部服务、业务 API 或低频能力时,先由解析模型在完整工具目录中筛选任务真正需要的工具,再通过 invoke 按需调用,从而把庞大的低频工具目录挡在 Agent 的 eager tool list 之外,显著节省上下文并降低误选工具的概率。读完本文,你将掌握 ToolHub 的启用方式、Resolved 模型与超时等全部选项语义、stdio / streamable-http / sse 后端服务器接入方法、内置浏览器自动化与 Chrome 登录态导入的完整流程,以及它和 Fusion MCP 的能力边界。
ToolHub 解决什么问题:该在什么时候用它
随着 MCP 服务器越接越多,如果把这些服务器的每个工具都直接暴露给 Agent,会出现两个问题:
- eager tool list 变得很大:Agent 每次请求都要携带全部工具描述,Context 消耗直线上升。
- 更容易误用:可选项太多,模型更容易在不该用某个工具的任务里选中它。
ToolHub 的解法是只向 Agent 暴露一个ccr-toolhubMCP 服务器,其中只有两个元工具(定义见 toolhub-mcp.ts 的metaTools()与常量resolveToolName/invokeToolName):
tool_hub.resolve:针对当前任务,在可用的 MCP 工具目录中检索并选出该任务所需的工具;tool_hub.invoke:调用某个经过 resolve 选出的真实 MCP 工具。
因此它的适用场景非常明确:工具偶尔有用、但不需要每个任务都常驻加载。真正的收益是“节省上下文”:低频大目录不进 Agent 的 eager 工具列表,Context 占用更低,选错工具的概率也更低。而纯本地代码、文件、会话类任务通常不需要 ToolHub——它们用不到外部能力,引入反而多一次 resolve 开销。
值得说明的是,Agent 端只看到两个元工具,不代表 CCR 真的只认识两个工具。ToolHub 运行时在进程内维护一个完整工具目录(Catalog),并对每个后端服务器做工具发现(discovery)。相关实现可见 toolhub-mcp.ts 中的ToolHubRegistry与ToolHubRuntime两个核心类。
工作原理:从配置到一次完整的 resolve/invoke 调用
按官方文档描述,ToolHub 从零到可用的完整链路如下:
- 在Settings → ToolHub中启用 ToolHub。
- 在已配置的模型中选择一个Resolver model(解析模型)。它负责读取 MCP 工具目录,为当前任务挑选所需工具。官方建议优先选择
deepseek-v4-flash,或其他处于同类 flash 价位、工具描述理解能力稳定的轻量模型。 - 添加或导入后端 MCP 服务器。ToolHub 支持
stdio、streamable-http、sse三种传输。 - 从 CCR 打开 Claude Code 或 Codex。CCR 会把
ccr-toolhub这个 MCP 服务器写进对应 Agent 的配置。 - 当 Agent 收到涉及外部服务、已安装 MCP 能力、或业务 API 的请求时,它先调用
tool_hub.resolve,再用tool_hub.invoke运行被选中的工具。
工具目录从哪里来
文档明确说明:ToolHub 会合并“ToolHub 页面配置的 MCP 服务器”与“旧配置里兼容的全局 Agent MCP 服务器”,并且排除ccr-toolhub自身,以避免递归调用。这在源码中可以直接验证:toolhub-config.ts 的toolHubBackendServers()把四类来源拼接到一起并统一过滤:
return [ ...(options.includeBuiltIns === false ? [] : toolHubBuiltInBackendServers(config, options)), ...(Array.isArray(config?.agent?.mcpServers) ? config.agent.mcpServers : []), ...(Array.isArray(config?.toolHub?.mcpServers) ? config.toolHub.mcpServers : []), ...extraServers ].filter(isToolHubBackendServer);而isToolHubBackendServer()的判定是name小写化后不等于ccr-toolhub。当启用了内置浏览器自动化时,toolHubBuiltInBackendServers()还会自动追加一个名为ccr-browser-automation、走streamable-http的内置后端(URL 形如{gateway}/__ccr/browser-automation/mcp)。也就是说,你不需要在 ToolHub 页面为浏览器自动化单独添加任何后端或 API Key。
CCR 如何把ccr-toolhub注入 Agent
CCR 在启动 Claude Code / Codex 时通过 Profile 写入机制完成注入:
- 对 Claude Code,service.ts 的
writeClaudeCodeToolHubMcpConfig()会在 Profile 管理的claude目录下生成toolhub-mcp.json,把ccr-toolhub的运行时配置写成mcpServers.ccr-toolhub; - 对 Codex,
writeCodexToolHubMcpRuntimeConfig()生成运行时配置并合并进 Codex 的 config.toml。
值得注意的是,Profile 写入时 resolver 的baseUrl会被指向本地网关的/v1端点,model取自 ToolHub 配置,API Key 则复用 CCR 的令牌——这意味着 Resolver 请求也走 CCR 的本地网关鉴权与路由路径。
运行时如何约束 Agent 行为
只注入工具还不够,CCR 还在网关层往 Claude Code 请求的系统提示里注入一段指令,见 claude-code-router-plugin.ts 的injectClaudeCodeToolHubInstructions()。它告诉模型:
- 凡是涉及外部服务、已安装 MCP 能力、业务 API、订单、优惠券、商店、账户、可用工具等“eager 工具中不明显”的请求,必须先调用解析工具,即使对话里没提到 ToolHub 也要调;
- 仅当请求明显是本地代码/文件/shell 工作或简单会话时才允许跳过;
- 拿到 resolve 结果后应调用 invoke 执行,而不是告诉用户“没有这种能力”。
这套“系统指令 + MCP 元工具”的组合,是 ToolHub 能真正约束 Agent 行为的关键设计。集成测试 toolhub-mcp-runtime.test.mjs 也断言了元工具名称、以及tool_hub.resolve描述中包含 “MUST be called before answering / external services / business APIs / orders / coupons / stores / accounts” 等强制性语义。
resolve 之后:会话状态与调用约束
tool_hub.invoke并不是无条件的:运行时要求被调用的工具必须先在本会话中被 resolve 加载,否则返回TOOL_NOT_RESOLVED错误并提示“先针对该任务调用tool_hub.resolve”。这是为了防止 Agent 绕过检索随意调远程工具。另外:
- 同一 scope(默认按会话)下,5 分钟窗口内重复出现的相同任务会命中“最近已解析”缓存,resolve 直接返回
alreadyResolved结果,不必重复检索(见常量repeatedResolveWindowMs = 5 * 60_000); - 工具目录的发现结果带约 10 秒的新鲜度控制(
discoveryCacheMaxAgeMs = 10_000),避免每次都重新连接后端; - 当 Resolver LLM 不可用或超时时,运行时存在一个本地打分回退(
resolveCatalogLocally()):对任务文本做分词与关键词匹配,为浏览器自动化、登录导入、定位、用户交互等高频意图预置了可解释的得分(例如出现 order/booking/checkout 相关词时优先返回browser_session_open、browser_navigate等),保证基础能力不掉线。
Options:ToolHub 页面全部选项与语义
以下表格来自官方文档,并与源码(default-config.ts 的默认值、config.ts 的normalizeToolHubConfig()归一化逻辑)逐项对应:
| 选项 | 说明 | 默认值 / 范围 |
|---|---|---|
| Enable ToolHub | 向 Agent 暴露ccr-toolhub。如果没有任何可用后端 MCP 服务器,CCR 不会生成 ToolHub MCP 配置。 | 默认关闭 |
| Built-in browser automation | 仅在 ToolHub 启用后才显示。允许 Agent 使用 CCR Desktop 内置浏览器完成网页任务。 | 默认关闭 |
| Resolver model | 从已配置的 provider 模型中选择。建议deepseek-v4-flash,或同类 flash 价位、工具描述理解能力稳定的轻量模型。 | 无默认模型(需选择) |
| Max tools | 单次 resolve 最多返回的工具数。 | 范围1–20,默认10 |
| Timeout ms | ToolHub resolve 与 invoke 的基础超时。若某个后端 MCP 服务器需要更长的请求超时,CCR 会把实际 invoke 超时抬升到与后端一致。 | 范围8000–300000,默认60000 |
| MCP servers | 后端工具来源。每个服务器需要唯一名称,以及传输方式、命令或 URL、环境变量、请求头和超时。 | 空列表 |
| Import JSON | 导入常见 MCP JSON 结构,支持根对象、数组、mcpServers、mcp_servers等形态。 | — |
其中“Enable ToolHub 打开但没有任何后端时不出配置”与“超时自动抬升”都有源码依据:
- toolhub-config.ts 的
toolHubMcpRuntimeConfig()在normalizedBackendServers.length === 0时返回undefined;toolHubClaudeCodeMcpConfig()也在没有后端时直接返回undefined; toolHubRequestTimeoutMs()取“配置的requestTimeoutMs”与“所有后端的requestTimeoutMs”两者最大值,也就是文档里说的“实际超时跟随最慢的后端”。
代码中还为每个后端做了配置哈希(configHash),配置变更时才会重建 MCP 客户端连接。
添加后端 MCP 服务器
stdio(本地命令行服务器)
stdio适合本地命令行 MCP 服务器,需要配置:
- Command:启动命令,如
npx、node、python; - Arguments:命令参数;
- Working directory:可选的工作目录;
- Stdio message mode:默认保持
content-length;对以换行分隔 JSON 的服务器选newline-json; - Environment variables:仅该 MCP 服务器需要的环境变量。
注意并非所有 npx 服务器都能立即就绪:如果服务器冷启动很慢,请调整该服务器的Startup timeout(启动超时)。
streamable-http / sse(远程服务器)
远程 MCP 服务器需要提供 URL,鉴权方式三选一:
- API key:直接把 Key 存进配置;
- API key env:从环境变量读取 Key;
- Headers:自定义请求头。
如果远程服务器启动慢或单次调用耗时长,请单独调整该服务器的Startup timeout与Request timeout。在运行时实现中,HttpMcpClient、SseMcpClient会先发initialize握手(协议版本默认2024-11-05),再执行tools/list与tools/call;连接、握手、调用都遵守各自超时设置(参见 toolhub-mcp.ts)。
名称与工具命名空间
每个后端服务器的name必须唯一。发现出来的工具在目录中以mcp.<serverNamespace>.<remoteToolName>命名(命名空间由服务器名规范化而来,ToolHubRegistry.listCatalogEntriesSync()负责),resolve 返回的selectedTools会携带这类规范化名称、描述与输入输出 Schema,供 invoke 精确引用。
JSON 配置示例(备份 / 迁移 / 排障用)
桌面应用的 SQLite 配置才是生效来源,所以常规操作应优先在 UI 里编辑。下面这些字段主要用于备份、迁移或排障:
{ "toolHub": { "enabled": true, "browserAutomation": true, "llm": { "apiKey": "sk-...", "baseUrl": "https://api.openai.com/v1", "model": "gpt-5-mini" }, "maxTools": 10, "requestTimeoutMs": 60000, "mcpServers": [ { "name": "filesystem", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"], "env": {}, "stdioMessageMode": "content-length", "requestTimeoutMs": 30000, "startupTimeoutMs": 600000 } ] } }其中browserAutomation: true需要 ToolHub 处于enabled: true且具备桌面内置浏览器环境才会生效(底层判定见browserAutomationMcpEnabled():enabled && browserAutomation)。
导入对话框也接受常见的 MCP JSON 结构,例如标准的mcpServers形态:
{ "mcpServers": { "filesystem": { "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"] } } }导入时请避免服务器重名,stdio条目必须有command,远程条目必须有url。与配置结构对应的 TypeScript 类型定义位于 app.ts(ToolHubConfig/ToolHubLlmConfig/GatewayMcpServerConfig等)。
内置浏览器自动化:让 Agent 操作真实浏览器
在 CCR Desktop 中启用 ToolHub 并打开Built-in browser automation后,Agent 就能使用桌面内置浏览器完成需要真实浏览器状态的网页任务(打开站点、读页面、填表、点按钮、滚动、以及下单、订票、查询、结账等没有专用能力时的网页流程),而且无需添加浏览器后端、无需单独的 API Key——CCR 通过本地网关鉴权路径与之相连。
启用步骤:
- 打开Settings → ToolHub,开启Enable ToolHub;
- 在同一个页面打开Built-in browser automation(此开关只有在 ToolHub 启用后才显示);
- 保存设置后,从 CCR 重新打开 Claude Code 或 Codex,让新的 Agent 实例加载最新配置。
已经运行的 Agent 实例通常不会立即感知这个开关。请重启 Agent 实例,或使用 Agent 自身的控制来重启 ToolHub。
启用后 Agent 具备的能力:
- 打开或挂接内置浏览器标签页,导航到 URL 或执行搜索;
- 读取页面内容,查找按钮、链接、表单字段等页面元素;
- 对元素执行点击、输入、下拉选择、按键、滚动等操作;
- 在继续之前等待页面加载、导航、对话框或人工交接结果;
- 在遇到登录、验证码、CAPTCHA、真人校验或人工确认时,向人类请求帮助。
当网页流程需要登录 / 验证码 / CAPTCHA / 人工校验 / 人工确认时,CCR 会弹出内置浏览器窗口,并在顶部工具栏展示待执行的动作;用户点击Done或Hide后,Agent 收到结果并继续。人工交接等待最长支持10 分钟(源码中的BROWSER_AUTOMATION_HANDOFF_TIMEOUT_MS = 600000)。这些工具(如browser_session_open、browser_navigate、browser_handoff_request、browser_handoff_wait等)由 browser-automation-mcp.ts 提供,网关侧路径/__ccr/browser-automation/mcp仅在桌面环境就绪时才返回可用(见 request-handler.ts 对BROWSER_AUTOMATION_MCP_PATH的处理)。
注意:内置浏览器自动化依赖 CCR Desktop 的内置浏览器,仅桌面应用可用。CLI、服务端部署和纯 Web 环境不包含此内置能力;这些环境请改用外部浏览器自动化 MCP 服务器。
Chrome 登录态导入扩展
内置浏览器自动化还可以把系统 Chrome 中指定域名的登录态导入 CCR 应用内浏览器,让 Agent 复用你在 Chrome 中已经登录的站点。它依赖本仓库的未打包 Chrome 扩展 extension/chrome。
安装扩展:
- 在 Chrome 打开
chrome://extensions; - 开启Developer mode(开发者模式);
- 点击Load unpacked(加载已解压的扩展程序);
- 选择仓库的
extension/chrome目录。
该扩展(Manifest V3,见 manifest.json)声明了cookies、scripting、storage权限,并只按 CCR 导入任务列出的域名读取 Cookie;修改扩展文件后需在chrome://extensions里点Reload。
导入流程:
- 当任务需要现有 Chrome 登录态时,Agent 可以请求导入;用户也可以点击 CCR 应用内浏览器工具栏的钥匙按钮主动发起;
- CCR 创建一次性导入任务并打开一个确认页;在装有扩展的 Chrome 中打开该确认 URL;
- 如果确认页没有在 Chrome 中打开:从 CCR 对话框复制Extension import URL,打开 Chrome 中的 CCR Login Import 扩展弹窗,粘贴该 URL,点击Import Selected Domains;
- 在确认页检查请求的域名列表,点击Confirm and Import,或在扩展弹窗中确认导入;
- Chrome 扩展读取这些域名的 cookies 与 localStorage 并提交给 CCR;完成后,Agent 即可在内置浏览器中继续任务。
安全边界与注意事项:
- 扩展只读取 CCR 导入任务中列出的域名,不会枚举 Chrome 的全部 Cookie;
- 对 localStorage,扩展会为所选 origin 临时打开非活动标签页、读取
localStorage后关闭这些标签页; - 如果确认页提示扩展没有站点访问权限,请在 Chrome 扩展设置中允许扩展访问目标域名、重新加载未打包扩展,然后再试一次。
此外,当任务文本命中登录导入意图(如 chrome/login/cookie/登录态/导入等关键词)时,toolhub-mcp.ts 的taskWantsChromeLoginImport()会确定性地把browser_chrome_login_import、browser_chrome_login_import_status纳入 resolve 结果,即使 Resolver LLM 没选到它们,也会自动补充。
ToolHub vs Fusion MCP:两条路线怎么选
两者都能让 Agent 用到 MCP 能力,但机制完全不同。官方对比表如下:
| 能力 | ToolHub | Fusion Custom MCP Tool |
|---|---|---|
| 入口 | Agent 侧的ccr-toolhubMCP 服务器 | 某个 Fusion 模型内部的能力 |
| 工具选择 | 每个任务动态解析出一个工具包 | 在模型配置中固定选择工具 |
| 适用场景 | 大量 MCP 服务器、工具目录经常变化、由 Agent 自主发现能力 | 给某个模型固定追加一组已知工具 |
| 可见范围 | 通过 CCR 打开的 Claude Code / Codex 配置 | 选中该 Fusion 模型的路由或 Agent |
简单概括:ToolHub 是“动态、跨 Agent、任务驱动”的聚合入口,适合工具集大且演进的场景;Fusion Custom MCP Tool 是“静态、按模型绑定”的固化能力,适合把一个确定的工具集合挂到特定模型上。Fusion 侧的自定义 MCP 同样支持 stdio 与 streamable-http / sse,且与内置的图像、视频生成工具处于同一体系,相关细节参见 fusion-mcp-tool.md。
故障排查速查表
按官方文档整理如下:
- Agent 看不到 ToolHub:确认 ToolHub 已启用,且至少配置了一个后端 MCP 服务器,或Built-in browser automation已打开;然后从 CCR 重新打开 Claude Code 或 Codex。
- 缺少 Resolver 模型或 API Key:在设置中选择一个已配置的 Resolver 模型,并确认对应 provider 凭据可用。
- Agent 无法使用内置浏览器自动化:确认你使用的是 CCR Desktop,并在Settings → ToolHub打开了Built-in browser automation,随后从 CCR 重新打开 Claude Code / Codex。CLI、服务端部署与纯 Web 环境没有该能力。
- Chrome 登录导入确认一直等待扩展:确认未打包的 extension/chrome 已在 Chrome 中加载,并拥有目标域名的站点访问权限;尝试在 Chrome 中手动打开确认 URL。
- resolve 不到任何工具:确认后端 MCP 服务器能正常列出工具;改善工具名称与描述,或调大Max tools。
- 调用超时:检查 ToolHubTimeout ms,以及后端服务器的 request / startup 超时。
- 导入失败:校验 JSON 合法性,避免服务器名称重复,确认
stdio条目带command、远程条目带url。
小结:ToolHub 的定位与使用建议
ToolHub 的价值定位是“低频能力收纳层”:让 Agent 的 eager tool list 始终精简,同时保留按任务发现并调用任意 MCP 工具的能力。使用时的关键判断依据是任务属性——外部服务、业务 API、低频 MCP 能力交给 resolve → invoke 两段式调用;纯本地代码与文件操作直接走常驻工具即可。无论选择 stdio 还是远程传输、是否开启内置浏览器自动化,理解ccr-toolhub的注入时机(重新从 CCR 打开 Agent)和两层超时(ToolHub 基础超时与各后端单独超时)是稳定使用它的两个关键点。如需进一步深入实现,可阅读 toolhub-config.ts(配置如何变成运行时环境变量)、toolhub-mcp.ts(目录、会话与本地回退逻辑)及 toolhub-mcp-runtime.test.mjs(端到端行为契约)。
【免费下载链接】claude-code-routerOne local control plane for every AI agent: route across models, fuse new capabilities, orchestrate tools, and stay fully in control.项目地址: https://gitcode.com/GitHub_Trending/cl/claude-code-router
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考