Cover image
Try Now
2025-01-07

Talk to a Cloudflare Worker from Claude Desktop!

3 years

Works with Finder

2

Github Watches

7

Github Forks

64

Github Stars

Workers MCP Server

Talk to your Cloudflare Workers from Claude Desktop!

NOTE: This has now been superseded by the Workers MCP package. Go there instead.

This is a proof-of-concept of writing a Model Context Protocol (MCP) Server in a Cloudflare Worker. This gives you a way to extend Claude Desktop (among other MCP clients) by invoking functions using Cloudflare Worker's new RPC syntax, which gives you access to any Cloudflare or third-party binding.

You write worker code that looks like this:

export class ExampleWorkerMCP extends WorkerEntrypoint<Env> {
	/**
	 * Generates a random number. This is extra random because it had to travel all the way to
	 * your nearest Cloudflare PoP to be calculated which... something something lava lamps?
	 *
	 * @return {string} A message containing a super duper random number
	 * */
	async getRandomNumber() {
		return `Your random number is ${Math.random()}`
	}
}

And, using the provided MCP proxy, your Claude Desktop can see & invoke these messages:

image

Yes, I know that Math.random() works the same on a Worker as it does on your local machine, but don't tell Claude 🤫

Neat! How do I play?

  1. Download Claude Desktop https://claude.ai/download
  2. Clone this repo.
  3. pnpm install
  4. Check wrangler.json
    The current demo uses both the Email Routing API and [Browser Rendering](https://developers.cloudflare.com/browser-rendering/. If you don't have access to these, or they're not enabled, comment out the relevant sections in wrangler.json or your deploy will fail.
  5. pnpm deploy:worker
    This takes your src/index.ts file and generate dist/docs.json from it, then deploys it using Wrangler.
  6. npx workers-mcp secret generate && npx workers-mcp secret upload
    This generates a secret in .dev.vars and uploads it using wrangler secret put. You only need to this once.
  7. npx workers-mcp install <server-alias> <worker-url>
  8. Restart Claude Desktop You have to do this pretty often, but you definitely have to do it after running the install step above.

To iterate on your server, do the following:

  1. Make your change to src/index.ts
  2. pnpm deploy:worker
  3. (usually) Restart Claude Desktop.
    You have to do this whenever you add/remove/change your methods or any of the documentation (Claude doesn't detect changes while it's running). But if you're just updating the code within a method then pnpm deploy:worker is enough.

NOTE: Specifics below are now outdated

These are replaced with relevant sections in Workers MCP package.


How it works

Separately to your MCP code inside src/index.ts, there are three pieces required to make this work:

1. Docs generation: scripts/generate-docs.ts

The MCP Specification separates the tools/list and tools/call operations into separate steps, and most MCP servers have naturally followed suit and separated their schema definition from the implementation. However, combining them provides a much better DX for the author.

I'm using ts-blank-space and jsdoc-api to parse the TS and emit the schema, slightly tweaked. This gives you LLM-friendly documentation at build time:

/**
 * Send a text or HTML email to an arbitrary recipient.
 *
 * @param {string} recipient - The email address of the recipient.
 * @param {string} subject - The subject of the email.
 * @param {string} contentType - The content type of the email. Can be text/plain or text/html
 * @param {string} body - The body of the email. Must match the provided contentType parameter
 * @return {Promise<string>} A success message.
 * @throws {Error} If the email fails to send, or if that destination email address hasn't been verified.
 */
async sendEmail(recipient: string, subject: string, contentType: string, body: string) {
  // ...
}
{
  "ExampleWorkerMCP": {
    "exported_as": "ExampleWorkerMCP",
    "description": null,
    "methods": [
      {
        "name": "sendEmail",
        "description": "Send a text or HTML email to an arbitrary recipient.",
        "params": [
          {
            "description": "The email address of the recipient.",
            "name": "recipient",
            "type": "string"
          },
          {
            "description": "The subject of the email.",
            "name": "subject",
            "type": "string"
          },
          {
            "description": "The content type of the email. Can be text/plain or text/html",
            "name": "contentType",
            "type": "string"
          },
          {
            "description": "The body of the email. Must match the provided contentType parameter",
            "name": "body",
            "type": "string"
          }
        ],
        "returns": {
          "description": "A success message.",
          "type": "Promise.<string>"
        }
      }
    ]
  }
}

This list of methods is very similar to the required MCP format for tools/list, but also gives us a list of the WorkerEntrypoint exports names to look up our service bindings later.

To iterate on your docs, run pnpm generate:docs:watch and you'll see the output change as you tweak your JSDoc in your src/index.ts (you'll need watchexec installed).

2. Public HTTP handler: lib/WorkerMCP.ts

Since our WorkerEntrypoint is not directly accessible, we need something that defines a default export with a fetch() handler. This is what lib/WorkerMCP.ts does.

This exposes a single endpoint, /rpc, which takes a JSON payload of { method: string, args?: any[] }, then calls that method on your WorkerEntrypoint.

3. Local MCP proxy: scripts/local-proxy.ts

This file uses the @modelcontextprotocol/sdk library to build up a normal, local MCP server. This responds to tools/list by producing the data from docs.json for the specified entrypoint.

On tools/call, a .fetch call is made to the remote worker on the /rpc route, providing a Bearer token with the contents of generated/.shared-secret. The responses are then piped back to Claude.

Calling pnpm install:claude <server-alias> <worker-url> adds a sever definition that points to this file in your claude_desktop_config.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>"
      ]
    }
  }
}

In this way you can install as many of these as you like, as long as they each have a distinct <server-alias>.

Limitations

There are lots. This pizza is straight out of the oven. You may well burn your mouth.

  1. docs.json is only generated from src/index.ts. It doesn't currently crawl imports like a bundler, because no bundler I could find preserved comments in-place in order for me to run the docs generator afterwards.
  2. Documentation generation only works for class exports. It can, at least, parse class X {}; export { X as Y }, but in general most people do export default class X {} anyway so this is fine for now.
  3. The local proxy <-> remote proxy communication doesn't follow any particular RPC spec, but it probably should.
  4. Error handling, non-text return values, streaming responses, etc have not really been thought through but do sorta work.
  5. No wrangler dev support yet, but wrangler dev --remote should be possible so you don't have to deploy so often
  6. Following on from the above, the spec includes a notifications/tools/list_changed notification that should trigger Claude to refresh its list of the tools available, meaning fewer restarts of Claude Desktop. But I haven't implemented that yet.
  7. The docs parsing doesn't yet use TS types to either augment or replace the need for @param blocks in the JSDoc
  8. The doc generation might be completely superfluous if someone was using a validator like zod or a schema library like typebox. However, I wanted build-time docs generation (i.e. static extraction) and wanted to be as generic as possible, so JSDoc will do for now.

Future ideas

Obviously, having Claude Desktop talk directly to the Worker would be ideal. Also, wrangler dev --remote support would be great: you could iterate on your worker without redeploying, but still access your production bindings.

The docs generator needs to be extracted into a library so we can publish changes, as it needs to grow in scope to be really useful, and likely incorporate other sources of data (d.ts files, zod schemas, etc).

Feedback & Contributions

Give it a try! Then, raise an issue or send a PR . This is all very new, so it could really go in a lot of different directions. We'd love to hear from you!

相关推荐

  • https://maiplestudio.com
  • Find Exhibitors, Speakers and more

  • Yusuf Emre Yeşilyurt
  • I find academic articles and books for research and literature reviews.

  • https://suefel.com
  • Latest advice and best practices for custom GPT development.

  • Carlos Ferrin
  • Encuentra películas y series en plataformas de streaming.

  • Emmet Halm
  • Converts Figma frames into front-end code for various mobile frameworks.

  • Joshua Armstrong
  • Confidential guide on numerology and astrology, based of GG33 Public information

  • https://zenepic.net
  • Embark on a thrilling diplomatic quest across a galaxy on the brink of war. Navigate complex politics and alien cultures to forge peace and avert catastrophe in this immersive interstellar adventure.

  • Elijah Ng Shi Yi
  • Advanced software engineer GPT that excels through nailing the basics.

  • https://reddgr.com
  • Delivers concise Python code and interprets non-English comments

  • 林乔安妮
  • A fashion stylist GPT offering outfit suggestions for various scenarios.

  • 1Panel-dev
  • 💬 MaxKB is a ready-to-use AI chatbot that integrates Retrieval-Augmented Generation (RAG) pipelines, supports robust workflows, and provides advanced MCP tool-use capabilities.

  • ShrimpingIt
  • Micropython I2C-based manipulation of the MCP series GPIO expander, derived from Adafruit_MCP230xx

  • Dhravya
  • Collection of apple-native tools for the model context protocol.

  • GLips
  • MCP server to provide Figma layout information to AI coding agents like Cursor

  • open-webui
  • User-friendly AI Interface (Supports Ollama, OpenAI API, ...)

  • Mintplex-Labs
  • The all-in-one Desktop & Docker AI application with built-in RAG, AI agents, No-code agent builder, MCP compatibility, and more.

  • adafruit
  • Python code to use the MCP3008 analog to digital converter with a Raspberry Pi or BeagleBone black.

    Reviews

    5 (1)
    Avatar
    user_G4gS6Ep5
    2025-04-17

    The workers-mcp-server by geelen is an excellent tool for managing server workloads efficiently. I particularly appreciate its clean language and how seamlessly it integrates into existing projects. If you're looking for a robust server management solution, I highly recommend checking it out on GitHub!