todos

A live deployment of the MCP TypeScript SDK's reference server, examples/todos-server — a small todo board where every server-side MCP feature has a real job: tools, resources, prompts, sampling, elicitation, progress, logging, and subscriptions.

Connect

https://todos-demo-ts.fweinberger-test.workers.dev/mcp (Streamable HTTP) serves both protocol revisions at once — 2026-07-28 and 2025-11-25, negotiated per connection. Boards there are anonymous: keyed by your network address, or by an X-Todos-Board header you choose. For a private board, connect to https://todos-demo-ts.fweinberger-test.workers.dev/oauth/mcp instead: your client discovers the OAuth endpoints (RFC 9728), registers itself (dynamic registration or a URL-format client id), and walks the PKCE authorization-code flow. Consent mints a fresh board bound to that grant — the token is the board. No accounts.

{ "mcpServers": { "todos": { "url": "https://todos-demo-ts.fweinberger-test.workers.dev/mcp" }, "todos-private": { "url": "https://todos-demo-ts.fweinberger-test.workers.dev/oauth/mcp" } } }

Version-forced endpoints

For client BC testing, every endpoint also exists in version-forced flavors — same boards, one protocol era each:

https://todos-demo-ts.fweinberger-test.workers.dev/2026-07-28/mcp
https://todos-demo-ts.fweinberger-test.workers.dev/2026-07-28/oauth/mcp
Modern only — 2025-era requests get the authentic strict rejection.
https://todos-demo-ts.fweinberger-test.workers.dev/2025-11-25/mcp
https://todos-demo-ts.fweinberger-test.workers.dev/2025-11-25/oauth/mcp
A real 2025-11-25 deployment: pinned sessions, 2026 clients negotiated down, authentic old-server rejections.
https://todos-demo-ts.fweinberger-test.workers.dev/auto/mcp
https://todos-demo-ts.fweinberger-test.workers.dev/auto/oauth/mcp
Both eras negotiated — identical to the bare paths.

One grant works across all OAuth flavors. A leaner sibling, mcp-checker.val.run, serves the same version-forced matrix as a fully stateless test target — probe tools only, no OAuth, no board.

Watch it live

https://todos-demo-ts.fweinberger-test.workers.dev/board is a read-only live view: tasks appear and complete in real time. Anonymous boards: open https://todos-demo-ts.fweinberger-test.workers.dev/board?b=<name> and connect with X-Todos-Board: <name>. OAuth boards: open it in the browser that approved consent — no token or board id in any URL. Or raw, in the 2026-07-28 wire format (there is no initialize — try server/discover):

curl -X POST https://todos-demo-ts.fweinberger-test.workers.dev/mcp \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -H 'mcp-protocol-version: 2026-07-28' \
  -H 'mcp-method: server/discover' \
  -d '{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{
    "io.modelcontextprotocol/protocolVersion":"2026-07-28",
    "io.modelcontextprotocol/clientInfo":{"name":"my-client","version":"1.0"},
    "io.modelcontextprotocol/clientCapabilities":{}}}}'

What to try

Everything works on both revisions: 2026-07-28 clients run the interactive tools as stateless input_required round trips; 2025-era clients get a real session at initialize with push-style elicitation/sampling. Sessions are in-memory (a conformant client just re-initializes after a recycle); boards are durable either way.

Boards

Every visitor gets their own board, keyed by connecting address — or send X-Todos-Board: any-name to pick your own (recommended if your egress rotates IPs). Boards cap at 200 tasks and expire ~2 hours after the last change. Treat board content as untrusted: it was written by whoever shares your visitor key — don't give an agent connected here unattended write authority elsewhere, and don't store anything sensitive.

No availability promises — this exists so you can kick the tires of a real 2026-07-28 server without running one. Source: typescript-sdk · SDK docs · MCP spec