内容
# Workers MCP Server
> **从 Claude Desktop 与您的 Cloudflare Workers 进行交互!**
## 注意:此项目现已被 [Workers MCP](https://github.com/cloudflare/workers-mcp) 包取代。请前往该链接。
这是一个在 Cloudflare Worker 中编写 [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) 服务器的概念验证。这为您提供了一种通过使用 Cloudflare Worker 的 [新 RPC 语法](https://blog.cloudflare.com/javascript-native-rpc/) 来扩展 Claude Desktop(以及其他 MCP 客户端)的方法,从而访问任何 Cloudflare 或第三方绑定。
您编写的 Worker 代码如下所示:
```ts
export class ExampleWorkerMCP extends WorkerEntrypoint<Env> {
/**
* 生成一个随机数。这个随机数特别随机,因为它必须经过您最近的 Cloudflare PoP 进行计算,这... 有点像熔岩灯?
*
* @return {string} 包含超级随机数的消息
* */
async getRandomNumber() {
return `Your random number is ${Math.random()}`
}
}
```
使用提供的 MCP 代理,您的 Claude Desktop 可以查看并调用这些消息:

> <sub>是的,我知道 `Math.random()` 在 Worker 上的工作方式与在您的本地机器上相同,但别告诉 Claude</sub> 🤫
## 太棒了!我该如何开始?
1. **下载 Claude Desktop** https://claude.ai/download
2. **克隆此仓库。**
3. **`pnpm install`**
4. **检查 `wrangler.json`**<br/>当前演示使用了 [Email Routing](https://developers.cloudflare.com/email-routing/) API 和 [Browser Rendering](https://developers.cloudflare.com/browser-rendering/)。如果您没有访问权限或未启用这些功能,请注释掉 `wrangler.json` 中的相关部分,否则您的部署将失败。
5. **`pnpm deploy:worker`**<br/>这将从您的 `src/index.ts` 文件生成 `dist/docs.json`,然后使用 Wrangler 部署它。
6. **`npx workers-mcp secret generate && npx workers-mcp secret upload`**<br/>这将在 `.dev.vars` 中生成一个密钥,并使用 `wrangler secret put` 上传。您只需执行一次。
7. **`npx workers-mcp install <server-alias> <worker-url>`**
8. **重启 Claude Desktop** 您需要经常执行此操作,但在运行上述安装步骤后,您 _绝对_ 需要这样做。
要对您的服务器进行迭代,请执行以下操作:
1. 对 `src/index.ts` 进行更改
2. **`pnpm deploy:worker`**
3. (通常)**重启 Claude Desktop**。<br/>每当您添加/删除/更改方法或任何文档时,都需要执行此操作(Claude 在运行时无法检测到更改)。但如果您只是更新方法中的代码,那么 `pnpm deploy:worker` 就足够了。
---
## 注意:以下具体内容现已过时
这些内容已被 [Workers MCP](https://github.com/geelen/workers-mcp) 包中的相关部分取代。
---
## 工作原理
除了 `src/index.ts` 中的 MCP 代码外,还需要三个部分来使其工作:
### 1. 文档生成:`scripts/generate-docs.ts`
[MCP 规范](https://spec.modelcontextprotocol.io/specification/server/tools/#listing-tools) 将 `tools/list` 和 `tools/call` 操作分为不同的步骤,大多数 MCP 服务器自然遵循这一点,并将其模式定义与实现分开。然而,将它们结合起来为作者提供了更好的开发体验(DX)。
我使用 [ts-blank-space](https://github.com/bloomberg/ts-blank-space) 和 [jsdoc-api](https://www.npmjs.com/package/jsdoc-api) 来解析 TS 并发出稍作调整的模式。这为您提供了在构建时友好的 LLM 文档:
```ts
/**
* 向任意收件人发送文本或 HTML 邮件。
*
* @param {string} recipient - 收件人的电子邮件地址。
* @param {string} subject - 邮件的主题。
* @param {string} contentType - 邮件的内容类型。可以是 text/plain 或 text/html
* @param {string} body - 邮件的正文。必须与提供的 contentType 参数匹配
* @return {Promise<string>} 成功消息。
* @throws {Error} 如果邮件发送失败,或者该目标电子邮件地址尚未验证。
*/
async sendEmail(recipient: string, subject: string, contentType: string, body: string) {
// ...
}
```
```json
{
"ExampleWorkerMCP": {
"exported_as": "ExampleWorkerMCP",
"description": null,
"methods": [
{
"name": "sendEmail",
"description": "向任意收件人发送文本或 HTML 邮件。",
"params": [
{
"description": "收件人的电子邮件地址。",
"name": "recipient",
"type": "string"
},
{
"description": "邮件的主题。",
"name": "subject",
"type": "string"
},
{
"description": "邮件的内容类型。可以是 text/plain 或 text/html",
"name": "contentType",
"type": "string"
},
{
"description": "邮件的正文。必须与提供的 contentType 参数匹配",
"name": "body",
"type": "string"
}
],
"returns": {
"description": "成功消息。",
"type": "Promise.<string>"
}
}
]
}
}
```
这个方法列表与 `tools/list` 所需的 MCP 格式非常相似,但也为我们提供了 `WorkerEntrypoint` 导出名称的列表,以便稍后查找我们的服务绑定。
要对您的文档进行迭代,请运行 `pnpm generate:docs:watch`,您将看到输出随着您在 `src/index.ts` 中调整 JSDoc 而变化(您需要安装 [watchexec](https://github.com/watchexec/watchexec))。
### 2. 公共 HTTP 处理程序:`lib/WorkerMCP.ts`
由于我们的 `WorkerEntrypoint` 不能直接访问,我们需要定义一个带有 `fetch()` 处理程序的默认导出。这就是 `lib/WorkerMCP.ts` 的作用。
它公开了一个单一的端点 `/rpc`,该端点接受一个 JSON 有效负载 `{ method: string, args?: any[] }`,然后在您的 `WorkerEntrypoint` 上调用该方法。
### 3. 本地 MCP 代理:`scripts/local-proxy.ts`
此文件使用 `@modelcontextprotocol/sdk` 库构建一个正常的本地 MCP 服务器。它通过生成指定入口点的 `docs.json` 数据来响应 `tools/list`。
在 `tools/call` 上,会对远程 Worker 的 `/rpc` 路由进行 `.fetch` 调用,并提供一个包含 `generated/.shared-secret` 内容的 `Bearer` 令牌。然后将响应传回 Claude。
调用 `pnpm install:claude <server-alias> <worker-url>` 会添加一个服务器定义,指向您 `claude_desktop_config.json` 中的此文件:
```json
{
"mcpServers": {
"<server-alias>": {
"command": "<absolute-path-to>/node",
"args": [
"<project-dir>/node_modules/tsx/dist/cli.mjs",
"<project-dir>/scripts/local-proxy.ts",
"<server-alias>",
"<worker-url>",
"<entrypoint-name>"
]
}
}
}
```
通过这种方式,您可以安装任意数量的这些,只要它们每个都有一个独特的 `<server-alias>`。
## 限制
有很多限制。这块披萨刚出炉。您可能会烫到嘴。
1. `docs.json` 仅从 `src/index.ts` 生成。它目前不会像打包工具那样爬取导入,因为我找不到任何一个打包工具能够保留注释,以便我在之后运行文档生成器。
2. 文档生成仅适用于类导出。至少,它可以解析 `class X {}; export { X as Y }`,但一般来说,大多数人还是会使用 `export default class X {}`,所以目前这样就可以了。
3. 本地代理与远程代理之间的通信并不遵循任何特定的 RPC 规范,但可能应该遵循。
4. 错误处理、非文本返回值、流式响应等尚未经过深思熟虑,但确实可以工作。
5. 目前尚不支持 `wrangler dev`,但 `wrangler dev --remote` 应该是可行的,这样您就不必频繁部署。
6. 根据上述内容,规范中包含一个 [`notifications/tools/list_changed` 通知](https://spec.modelcontextprotocol.io/specification/server/tools/#list-changed-notification),应该触发 Claude 刷新可用工具的列表,从而减少 Claude Desktop 的重启次数。但我尚未实现这一点。
7. 文档解析尚未使用 TS 类型来增强或替代 JSDoc 中 `@param` 块的需求。
8. 如果有人使用像 zod 这样的验证器或像 typebox 这样的模式库,文档生成可能完全多余。然而,我希望在构建时生成文档(即静态提取),并希望尽可能通用,因此 JSDoc 目前可以满足需求。
## 未来想法
显然,让 Claude Desktop 直接与 Worker 进行交互是理想的。此外,支持 `wrangler dev --remote` 将是很好的:您可以在不重新部署的情况下对 Worker 进行迭代,但仍然可以访问生产绑定。
文档生成器需要提取到一个库中,以便我们可以发布更改,因为它需要扩大范围以真正有用,并可能结合其他数据源(`d.ts` 文件、zod 模式等)。
## 反馈与贡献
试试看!然后,提出问题或发送 PR。这一切都是非常新的,因此可能会朝着许多不同的方向发展。我们期待您的反馈!