Skip to content

[mcp-2026] Align 2026 wire: drop ping, add -32021, discover _meta, MUST headers #24

Description

@manish-wekan

Context

PR #21 merged 2026-07-28-shaped code that still speaks 2025 on the wire:

Spec Code today
ping removed build_ping_response, pipeline fast path, MODERN_METHOD_CONTRACTS includes ping with requires_method_header=False
-32021 Missing Required Client Capability JsonRpcErrorCode has -32020 and -32022 only (nitrostack/protocol/errors.py)
serverInfo / version / caps on result _meta build_discover_result puts serverInfo on the body; _meta is only a cache hint
resultType on 2026 results Set on discover, task create helper, MRTR — not on normal tools/call / list / read results
SEP-2243 MUST MCP-Protocol-Version + Mcp-Method (and Mcp-Name on name-scoped methods) tools/call has requires_method_header=False; comments say header is not required on modern in the sidecar; validate_header_body_method no-ops if header absent
Retired methods Table still lists tasks/result, tasks/list, logging/setLevel, resources/subscribe as modern contracts; rejected only when era is modern, so auto still serves them

Sidecar handle_post currently intercepts discover/initialize/ping. WP0 must remove that. This issue is the handler-side wire: core/app.py _setup_handlers, protocol/discovery.py, protocol/errors.py, protocol/method_contract.py.

Handoff: #21 (comment)

Spec references (judge wire, not official SDK DX):

NitroStack may keep modules/DI/@tool. Do not copy official SDK internals.

Goal

After WP0, mcp 2.x owns /mcp. NitroStack handlers stamp 2026 fields. No ping. Modern POST fails closed on missing MUST headers. Discover _meta includes serverInfo.

Probe

rg -n "ping|build_ping_response|-32021|32021|serverInfo|resultType|requires_method_header" nitrostack/protocol nitrostack/core/app.py nitrostack/transports/dispatch.py

Read:

  • nitrostack/protocol/errors.py
  • nitrostack/protocol/method_contract.py — entire MODERN_METHOD_CONTRACTS and DEPRECATED_MODERN_METHODS
  • nitrostack/protocol/discovery.pybuild_discover_result, build_sessionless_initialize_result
  • nitrostack/protocol/jsonrpc.py — header validators; parse_jsonrpc_request treats missing id as a request
  • nitrostack/core/app.pyhandle_server_discover, _setup_handlers, _to_call_tool_result
  • nitrostack/runtime/stateless.py — comment that protocol version header is not required on modern

Confirm era auto still allows 2025 handshake via mcp 2.x, not via a NitroStack JSON-RPC middleware. Delete build_sessionless_initialize_result from any sidecar path. If mcp needs a NitroStack initialize payload, use NitroStackMcpServer.initialize_handler on the Server object only.

Implementation

  1. Errors. Add -32021 to JsonRpcErrorCode + default message. Prefer mcp 2.x owning -32020/-32022 if it already emits them. If you keep a thin header check, it must not become a second method router.
  2. Ping. Remove from contracts, production helpers, and public exports. ping-32601.
  3. Discover. One builder used by handle_server_discover and server.add_request_handler("server/discover", ...). Put serverInfo (name, version) on result _meta. Set resultType on discover. If era auto also exposes top-level serverInfo for old clients, modern must still satisfy 2026 _meta rules. Advertise io.modelcontextprotocol/tasks only if the tasks issue implements 2026 tasks (default: do not advertise).
  4. Headers (modern). POST /mcp JSON-RPC MUST send MCP-Protocol-Version: 2026-07-28 and Mcp-Method matching body. tools/call, resources/read, prompts/get MUST send Mcp-Name matching name/uri. One validator: missing/mismatch → -32020. Delete the dual optional-vs-required helpers. Era auto: do not require 2026 headers on 2025 handshake; do require them on 2026 methods if mcp does.
  5. resultType. Stamp in NitroStack handlers that already build mcp types: list tools/resources/prompts, tools/call, resources/read, prompts/get — not only discover/MRTR/task.
  6. Retired methods on modern. Do not register (or register not-found): tasks/result, tasks/list, resources/subscribe, logging/setLevel, ping, initialize. Do not rely on a sidecar that return None so mcp still runs them. auto handshake is mcp’s job (WP0).
  7. Method table. If it exists only for tests, delete it and test via HTTP. It must not list ping / tasks/result / tasks/list as live modern methods.

Do not implement tasks/update here (tasks issue). Do not add era aliases.

Test / verify

Prefer Starlette TestClient on McpApplication.get_combined_app() (same fixture style as tests/test_transport_http.py / lifecycle HTTP tests). Era via NITRO_MCP_PROTOCOL_VERSION / ServerConfig.protocol_era.

Case Era Expect
POST /mcp method: ping modern, auto -32601
POST /mcp server/discover without MUST headers modern -32020 or mcp equivalent, not 200
POST /mcp discover with headers modern, auto 200; serverInfo on result _meta; no Mcp-Session-Id
POST /mcp initialize modern -32601
POST /mcp tools/call without Mcp-Method modern -32020
-32021 is defined and used or re-exported enum exists; at least one test references it (task capability or document “unused until tasks issue”)

Do not restore header-only ping tests.

pytest on the new tests + tests/test_transport_http.py tests/test_lifecycle_http.py. Expect tests/test_mcp20_stateless_http.py to fail until the test-rewrite issue; do not expand that file.

Review

  • Wire changes live in handlers / mcp registration, not a new ASGI JSON-RPC server.
  • Discover _meta.serverInfo present on modern.
  • rg ping nitrostack/ has no live RPC.

Success

  • No production ping success path
  • -32021 exists on JsonRpcErrorCode
  • Discover result _meta contains serverInfo
  • Modern POST without version/method headers fails closed
  • resultType not limited to discover/MRTR
  • Modern does not register retired 2025 methods

Related

Depends on WP0. Align subscribe flag with WP1. Tasks advertising is WP3.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions