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.
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" } } }
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/mcphttps://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/mcphttps://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/mcphttps://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.
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":{}}}}'
add_task, list_tasks, complete_task — CRUD with structured output.brainstorm_tasks — multi-round input_required: a form, then sampling with your model.
clear_done — elicitation: a schema-driven confirm form.work_through_tasks — paced progress; cancel mid-run and watch it stop.simulate_failure — deliberate errors for client QA: tool error, progress-then-error, hang.todos://board — a subscribable resource; every mutation announces itself.plan-my-day — a prompt with completable arguments.
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.
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