MCP Real-World Tasks Reference
A minimal, dependency-free MCP server demonstrating the 2026-07-28 protocol with a toy example of sending a person to check something in the physical world and returning structured evidence, ideal for learning the protocol layer.
README
MCP reference server for real-world tasks
A minimal, dependency-free MCP server written against protocol revision
2026-07-28 — the one that removed sessions and the initialize handshake.
It models a service that sends a person to check something in the physical
world and returns structured evidence.
The domain is a toy. The shape is not: it is extracted from a production server that answers agents today, with the business logic replaced by a readable example so the protocol layer is the thing you actually read.
npm start # http://localhost:8787
npm test # 20 tests, no dependencies
curl -s -X POST http://localhost:8787/ \
-H 'content-type: application/json' \
-H 'mcp-protocol-version: 2026-07-28' \
-H 'mcp-method: tools/list' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28"}}}'
What changed in 2026-07-28, and why it makes this simpler
If you last read the MCP spec before this revision, most of what you remember about transports is gone:
| Removed | Replaced by |
|---|---|
Protocol-level sessions, Mcp-Session-Id |
Nothing. Every request stands alone. |
The initialize / notifications/initialized handshake |
Version and capabilities in each request's _meta |
The standalone GET SSE stream |
subscriptions/listen, opt-in, not needed by most servers |
ping, logging/setLevel |
Removed outright |
Resumable streams (Last-Event-ID) |
Removed; a broken stream is re-issued as a new request |
The practical consequence is the whole point of this repo: a stateless
request handler is now the shape the spec expects. There is no session to
store, nothing to expire, and no reason to reach for a durable object, a Redis,
or a stateful process. src/protocol.js is a pure function from Request to
Response.
Two things were added that are easy to miss and that clients silently rely on:
- Every result carries
resultType: "complete". - List results (
tools/list,server/discover) carryttlMsandcacheScope. server/discoveris mandatory — clients may call it before anything else.
Layout
| File | What it is |
|---|---|
src/protocol.js |
The protocol layer. Knows nothing about the domain. This is the part worth copying. |
src/tools.js |
The example domain: a catalogue, a deterministic quote engine, and one write tool. |
src/server.js |
Wires the two together; exposes a fetch handler and a Node listener. |
test/protocol.test.mjs |
20 tests, each pinning one rule that is easy to get subtly wrong. |
src/server.js exports fetchHandler(request) — a plain Request →
Response function, so it drops unchanged into Cloudflare Workers, Deno
Deploy, Bun, or a Next.js route handler. The Node listener exists so npm start works without a platform account.
The five decisions worth stealing
Everything below is a choice that cost real debugging somewhere else.
1. The header/body mirror is a real requirement, not decoration.
Mcp-Method and Mcp-Name duplicate values from the body so intermediaries
can route without parsing. If they disagree, reject with -32020. Skipping
this creates a split-brain where a proxy routes on the header while your
handler executes the body — which is exactly the bug the rule exists to
prevent.
2. Unknown method is 404, not 200 with an error body.
The spec uses the HTTP status so a client can tell "this endpoint does not
implement that method" from "this URL is not an MCP endpoint at all". Return
200 and you break client fallback logic.
3. Read-only tools need no authentication. Quoting creates nothing, reserves nothing, costs nothing. There is nothing to gate. Gating it only teaches agents that exploring your service is expensive. Authenticate the tools that commit something.
4. Exactly one tool has a side effect, and its annotations say so.
readOnlyHint, destructiveHint, idempotentHint and openWorldHint are what
clients and directory reviewers branch on. An unannotated write tool will be
treated as dangerous or rejected.
5. One pricing function serves every surface.
In the production system this is extracted from, the same quote() answers the
web form, the REST endpoint and the MCP tool. A human and an agent therefore
cannot be shown different prices for identical work. If you take one idea from
this repository, take this one — it is a correctness property, not an
optimisation.
The safety shape
The example write tool (submit_request) is deliberately not a booking:
- It requires
consent: true, set only after a human has agreed. - It returns
status: "pending_human_review"anddispatch: "never_automatic". - Nothing in the response can be mistaken for a confirmation.
An agent should never be able to send a person into the physical world without someone reading the request first. In the system this comes from, that is a fixed product guardrail rather than a limitation to be lifted later — and the tool description says so, because the description is what the model reads when it decides whether to call it.
Compatibility with older clients
src/protocol.js answers initialize, notifications/initialized and ping
for the 2025-* revisions, because deployed clients lag published specs by
months. It is a shim, not a second protocol: both paths serve the same tools
from the same definitions. Header mirroring is enforced only on the modern
revisions, since requiring it on legacy clients would reject exactly the
clients the shim exists for.
Delete LEGACY_PROTOCOL_VERSIONS once nothing in the wild still opens with a
handshake.
Connecting it
Once deployed at a public HTTPS URL, add it as a custom connector in Claude (Settings → Connectors) or in ChatGPT (Settings → Apps → Advanced → Developer mode). Both accept a no-auth Streamable HTTP endpoint.
License
MIT. Built as a by-product of VorOrtAI, which runs the non-toy version of this.
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。