Skip to main content
Glama
Peanuts1605

mcp-apps-workers-starter

by Peanuts1605

mcp-apps-workers-starter

A small, tested starting point for an MCP server with an MCP Apps view on Cloudflare Workers, with one Durable Object per session. It also includes a plain web page that acts as an MCP Apps host, so you can see the view working in a browser without a chat client.

When I built Open Tomorrow for Alexa+, I could not find one example that put these pieces together. This repo is that missing example, in about 230 lines of source:

Piece

File

What it shows

Stateless MCP over Streamable HTTP

src/mcp.mjs

WebStandardStreamableHTTPServerTransport with sessionIdGenerator: undefined and enableJsonResponse: true: one Request in, one JSON Response out. No SSE stream, so it fits a Worker. Protocol 2025-11-25.

MCP Apps tools and view

src/mcp.mjs, src/view.*

registerAppTool and registerAppResource from @modelcontextprotocol/ext-apps. Both tools point to one ui:// view, and the view calls tools back through the host.

Per-session state

src/worker.mjs

?session=<id> maps to a Durable Object. State is saved only when a tool changed it, and an alarm deletes it after a day without use.

Safe concurrent writes

src/checklist.mjs

Every write sends expectedRevision. If two writers race (an agent and the view, say), the second one gets STALE_REVISION and reads again.

Browser host

src/host.*

SDK Client + AppBridge + PostMessageTransport. The view runs in an allow-scripts iframe with no same-origin access.

Small bundles

build.mjs

esbuild inlines the view and host into ES modules. A small plugin keeps only zod's English locale, which roughly halves the view.

Run it

Needs Node 22+.

npm install
npm test          # 10 tests: the state rules, MCP over real Requests with the SDK client, and a check that generated files are current
npm run dev       # wrangler dev on http://localhost:8787, then open it in a browser
npm run smoke     # with dev running: persistence, session isolation, and 405/400/403 guards

Deploy with npx wrangler deploy. Durable Objects with SQLite storage are available on the Workers free plan.

To connect an MCP client, use https://<your-worker>/mcp?session=<8-64 letters, digits or dashes>.

Related MCP server: Durable Thinking

Make it yours

Replace Checklist with your own state. Keep read() and apply() pure and revision-checked. Then change the two tool definitions in src/mcp.mjs and the rendering in src/view.mjs, and run npm run build. The generated files are committed so Node tests can import them without a build step; npm test fails if they are stale.

Notes and limits

  • The server sends JSON only, so the SDK client's optional GET /mcp (for an SSE stream) gets 405, which the spec allows. The browser host answers that probe itself (fetchNoProbe in src/host.mjs) so the console stays clean.

  • Cross-origin POST /mcp with an Origin header is rejected. Clients that send no Origin (server-side agents) are allowed. The session id is a capability, so anyone who knows it can use that session. Add authentication before you store anything private.

  • Pinned versions: @modelcontextprotocol/sdk 1.30.0 and @modelcontextprotocol/ext-apps 1.7.5. ext-apps 2.x expects SDK v2.

License

MIT

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    F
    maintenance
    Implements an MCP server using Cloudflare Durable Objects with SSE transport, enabling remote MCP client connections.
    1
    -
  • A
    license
    Not graded
    quality
    A
    maintenance
    Persistent sequential thinking for MCP clients, stored durably on Cloudflare Workers with support for branching, revision, and history retrieval.
    2
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    A remote MCP server for structured sequential thinking, enabling users to create, revise, and manage sequences of steps with persistent state via Cloudflare Workers and Durable Objects.
    Apache 2.0