MCP HubMCP Hub
geelen

workers-mcp-server

by: geelen

Talk to a Cloudflare Worker from Claude Desktop!

64created 03/12/2024
Visit
Cloudflare
Claude

📌Overview

Purpose: The framework serves as a proof-of-concept Model Context Protocol (MCP) Server for Cloudflare Workers, extending the functionality of Claude Desktop by enabling RPC communication with server-side functions.

Overview: This MCP Server allows for seamless interaction between Claude Desktop and Cloudflare Workers, utilizing the new RPC syntax to provide responsive and dynamic capabilities. By writing worker code, developers can create functions that Claude Desktop can easily invoke, facilitating various operations via HTTP requests.

Key Features:

  • Easy Function Invocation: The framework allows developers to define functions within a Cloudflare Worker, which can then be invoked from clients like Claude Desktop using the RPC endpoint. This extends the capabilities of MCP clients with server-side functionality.

  • Automated Documentation Generation: The MCP Server includes scripts that automatically generate documentation for the exposed methods, providing a better developer experience by simplifying integration and clear understanding of available functionalities.


Workers MCP Server

Talk to your Cloudflare Workers from Claude Desktop!

Important Note

This project has been superseded by the Workers MCP package. Please use that instead.


Overview

This is a proof-of-concept to write a Model Context Protocol (MCP) Server as a Cloudflare Worker. It allows you to extend Claude Desktop (and other MCP clients) by invoking functions using Cloudflare Worker's new RPC syntax, providing access to any Cloudflare or third-party binding.

You write worker code 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.
	 *
	 * @return {string} A message containing a super duper random number
	 * */
	async getRandomNumber() {
		return `Your random number is ${Math.random()}`
	}
}

Using the provided MCP proxy, Claude Desktop can see and invoke these messages.

Note: Math.random() works the same on a Worker as it does locally, but this is a playful detail.


How to Get Started

  1. Download Claude Desktop from https://claude.ai/download
  2. Clone this repository.
  3. Install dependencies:
    pnpm install
    
  4. Check wrangler.json:
    The demo uses the Email Routing API and Browser Rendering. If you don't have access or these are disabled, comment out relevant sections in wrangler.json to avoid deployment failure.
  5. Deploy the worker:
    pnpm deploy:worker
    
    This generates dist/docs.json from src/index.ts and deploys using Wrangler.
  6. Generate and upload secret:
    npx workers-mcp secret generate && npx workers-mcp secret upload
    
    This creates a secret in .dev.vars and uploads it with wrangler secret put. Run this once.
  7. Install the MCP server for Claude Desktop:
    npx workers-mcp install <server-alias> <worker-url>
    
  8. Restart Claude Desktop:
    Restarting is required, particularly after installation or changing methods/documentation.

Iterating on Your Server

  • Modify src/index.ts
  • Run:
    pnpm deploy:worker
    
  • Usually restart Claude Desktop if you add/remove/change methods or documentation. For code changes within a method, deploying alone is sufficient.

How It Works

This project involves three main components beyond your worker code (src/index.ts):

1. Docs Generation (scripts/generate-docs.ts)

The MCP specification separates tools/list and tools/call operations. Typically, MCP servers separate schema from implementation, but this combines them for improved developer experience.

We use ts-blank-space and jsdoc-api to parse TypeScript and generate LLM-friendly documentation at build time through JSDoc comments:

Example method with JSDoc:

/**
 * 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 (text/plain or text/html).
 * @param {string} body - The body of the email matching the contentType.
 * @return {Promise<string>} A success message.
 * @throws {Error} If email sending fails or recipient is unverified.
 */
async sendEmail(recipient: string, subject: string, contentType: string, body: string) {
  // ...
}

This generates a tools/list-compatible JSON schema.

To watch and update docs during development, run:

pnpm generate:docs:watch

(Ensure watchexec is installed to use this.)


2. Public HTTP Handler (lib/WorkerMCP.ts)

Because your worker entrypoint class isn't directly accessible, this file exports a fetch() handler that exposes a /rpc endpoint.

The /rpc endpoint accepts JSON payloads like:

{ "method": "methodName", "args": [ ... ] }

and calls the corresponding method on your WorkerEntrypoint instance.


3. Local MCP Proxy (scripts/local-proxy.ts)

This script uses the @modelcontextprotocol/sdk library to set up a local MCP server that communicates with the remote Cloudflare Worker.

  • On tools/list, it responds with docs.json content.
  • On tools/call, it proxies calls to the remote worker /rpc, including authentication by sending a Bearer token from a shared secret file.

Installing this proxy for Claude Desktop involves running:

pnpm install:claude <server-alias> <worker-url>

This adds an entry in your claude_desktop_config.json to launch the local proxy command, enabling multiple server aliases.


Limitations

This project is experimental and has several known limitations:

  1. Documentation generation only covers src/index.ts and does not crawl imports.
  2. Only class exports are supported for docs generation.
  3. The proxy communication does not follow a formal RPC specification.
  4. Limited error handling, non-text return values, and streaming responses support.
  5. No support yet for wrangler dev; wrangler dev --remote may work in future.
  6. Missing implementation of notifications/tools/list_changed spec to allow refreshing without restarting Claude Desktop.
  7. Doc parsing does not yet integrate TypeScript type information (only JSDoc).
  8. Doc generation may be redundant if using schema validators like zod or typebox but currently provides static extraction.

Future Directions

  • Enable Claude Desktop to communicate directly with the Worker without the proxy.
  • Add support for wrangler dev --remote for faster development cycles.
  • Extract and improve the docs generator into a standalone library, potentially incorporating type info and schema validation.

Feedback & Contributions

Try the project and provide feedback! Issues and pull requests are welcome to improve this evolving project.