cloudflare/mcp-server-cloudflare

十五个生产级 MCP 服务共用一套工厂与书面规范,服务只写差异部分;请求级无状态、能力接口封装与 LLM 评估层都能直接搬。

4,301 stars · TypeScript · Apache-2.0

数据截至 2026-09-26 · commit 1d7a16b

这个仓库表面上是一堆 MCP server,实际是一套多服务量产框架。十五个域服务跑在同一个工厂上,传输、鉴权、指标、错误上报全部共享,每个服务只剩三件事要写:工具、校验器、给模型的说明书。单个工具写得好不好是小事,值得搬走的是这套分层。

它解决什么问题

单个 MCP server 手搓并不难,难的是第二个。协议接入、OAuth、CORS、账号解析、指标上报,每个服务重复实现一遍,质量随人而 drift;工具怎么命名、参数怎么校验、错误怎么报,全靠各服务作者自觉。Cloudflare 一年里开出十几个域服务(观测、构建、浏览器渲染、DNS 分析……README 的服务表 数下来是十五个),这件事必须变成工厂加规范,否则维护成本随服务数线性上涨。

他们的答案分两层。代码层:packages/mcp-common 收敛所有基建,服务只声明差异。文字层:implementation-guides/ 三份内部规范(工具、校验器、评估)把工具质量从口口相传变成可查的守则。

怎么解的

monorepo 三层。apps/ 每个服务一个目录,内部固定三件套:入口 <name>.app.ts 只有二十来行,声明 scopes 与主机名;<name>.context.ts 放环境绑定与服务器指令;tools/*.tools.ts 是纯注册函数。packages/ 放共享库。implementation-guides/ 放规范。最小服务 demo-day 全部代码 53 行,含 Worker 导出——它同时是新服务的抄写起点。

运行时模型是请求级无状态:每个请求经 createCloudflareMcpHandler 用 SDK 工厂新建一个服务器实例,无协议会话,天然水平扩展。旧 /sse 端点不悄悄兼容,回 410 加迁移指引。配套纪律写进工具规范原文:每个工具显式收参,不依赖前一次调用或会话状态。

设计亮点

注册上下文封死旁路。 应用代码拿不到裸的 SDK server,只能用 context.registerTool() / context.accountTool()(registration-context.ts)。工厂给每个回调包上指标计时与错误上报,共享可观测性在类型上就绕不过去。注释写得很直白:这是防止有人”accidentally bypass”。

inputSchema 按凭据形态收窄。 多账号场景的三级解析(account-tool.ts):token 只绑一个账号时,schema 里根本不出现 account_id 参数;多账号凭据才动态 extend 出这个参数让模型自己选。模型少填一个参数,就少一次填错的机会。

校验器锚定上游类型。 规范要求每个字段一个命名 Zod schema,并用 z.ZodType<SDKType> 链到 SDK 的参数类型——上游改了类型签名,编译期就炸,不留到运行期。字段 schema 跨工具复用,每个都 .describe()。

错误分内外两层。 McpError 把 message(给模型)和 internalMessage(内部日志,含上游响应体前 500 字符)拆开;上游 4xx 保留状态码不上报 Sentry,5xx 映射 502 才上报。该吵的吵,不该吵的静默。

给模型的输出按 token 优化。 fmt.asTSV 把表格数据转 TSV 返回,注释直言比 JSON 省 token。截图走 image content block,PDF 走 resource blob,网页正文带一段引导文本告诉模型拿它干什么。

单元测试之上还有一层 LLM 评估。 vitest-evals 让真实模型连上工具跑任务,断言调了哪个工具、参数对不对,再对最终回答做事实性评分,多模型矩阵跑(evals.md)。测的是”模型能不能用对这套工具”——这层大多数团队没有。

借鉴清单

能搬的:

什么怎么搬
工具不依赖会话、参数全显式纯设计纪律,任何 MCP 服务立刻适用
字段级命名 schema + 锚定上游类型有 SDK 的服务照抄 z.ZodType<SDKType> 写法
错误分内外两层、4xx 不上报两个小函数的事,信噪比立竿见影
表格数据 TSV 化一个 @fast-csv/format 依赖
LLM 评估层vitest-evals 断言 toolCalls,工具多于五个就值得建

不适用的:

  • monorepo 全家桶(pnpm + Turbo + changesets)。服务只有一个时,这是纯开销。
  • Workers 绑定、Durable Object、Analytics Engine 指标。平台特权,不在 Cloudflare 上跑就搬不动。
  • OAuth provider 与授权对话框。自建一套只为对标 Cloudflare 账号体系,不值。

局限

三处要警惕。规范是书面约定,没有 lint 强制——implementation-guides 里的守则新贡献者可以不读,代码也不会拦。工具 handler 里 try/catch 加 content 包装的样板每个工具重复一遍,二十个工具的文件读起来很闷。最重的一点:mcp-common 里 Cloudflare 平台耦合(绑定、OAuth、账号体系)与通用机制(错误分层、注册封装)混在同一层,想只搬通用那半,得自己剥。

还有个方向性事实:Cloudflare 自己在收摊。仓库里 radar 服务已标记废弃,README 把推荐位让给了统一的 Code Mode 服务(mcp.cloudflare.com,两个通用工具加代码执行覆盖全 API)。策划型工具与广覆盖通用工具的取舍他们两边都试了,值得在做同类决策时引用。

相关