Skip to content

MCP 2026-07-28 (1/11): protocol foundations — versions, typed errors, resultType - #224

Open
simonx1 wants to merge 4 commits into
mainfrom
mcp-2026/protocol-foundations
Open

MCP 2026-07-28 (1/11): protocol foundations — versions, typed errors, resultType#224
simonx1 wants to merge 4 commits into
mainfrom
mcp-2026/protocol-foundations

Conversation

@simonx1

@simonx1 simonx1 commented Sep 1, 2026

Copy link
Copy Markdown
Owner

Summary

First of a stacked series implementing the MCP 2026-07-28 revision. This PR lays the base-protocol groundwork the later feature PRs build on; nothing changes on the wire yet.

  • Version constantsLATEST_PROTOCOL_VERSION (2026-07-28), MODERN_PROTOCOL_VERSIONS, LEGACY_PROTOCOL_VERSIONS; SUPPORTED_PROTOCOL_VERSIONS is their union. PROTOCOL_VERSION stays 2025-11-25 (the legacy initialize request version), and initialize now only accepts a legacy negotiated version.
  • Error-code allocation policy (basic/index "Error Codes") — Errors::Codes constants; ServerError gains code/data (backward-compatible ctor); ServerError.from_jsonrpc builds the typed HeaderMismatchError (-32020), MissingRequiredClientCapabilityError (-32021, #required_capabilities) and UnsupportedProtocolVersionError (-32022, #supported/#requested). All four transports raise them; stdio now routes every response through process_jsonrpc_response so codes are never dropped.
  • resultType — absent ⇒ "complete" (earlier-protocol servers), "input_required" passes through (handled by the MRTR PR), anything unrecognized raises InvalidResultError (a non-retried ServerError). Transports can widen the accepted set via accepted_result_types (used by the tasks extension PR).
  • Resource not foundresources/read errors with -32602 (or legacy -32002) raise ResourceNotFound on every transport.

Spec references

  • basic/index: Result responses / ResultType, Error Codes
  • basic/versioning: terminology (modern vs legacy)
  • server/resources: Error Handling (-32602, accept -32002)

Test plan

  • bundle exec rspec — 1701 examples, 0 failures (44 new)
  • bundle exec rubocop — clean

🤖 Generated with Claude Code

https://claude.ai/code/session_01MoErzDypnq7hhuFBtueML7

…ltType

Lay the groundwork for the stateless 2026-07-28 revision:

- LATEST/MODERN/LEGACY protocol version constants; SUPPORTED is their union
  and initialize only accepts a legacy negotiated version.
- ServerError carries the JSON-RPC code and data; ServerError.from_jsonrpc
  builds HeaderMismatchError (-32020), MissingRequiredClientCapabilityError
  (-32021) and UnsupportedProtocolVersionError (-32022). Errors::Codes holds
  the allocation-policy constants.
- process_jsonrpc_response validates resultType: absent means complete,
  unrecognized values raise InvalidResultError (a non-retried ServerError).
  Stdio now routes every response through it so codes are preserved.
- resources/read errors with -32602 (or legacy -32002) raise
  ResourceNotFound on every transport.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoErzDypnq7hhuFBtueML7
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

Codex review: only callers of process_jsonrpc_response checked resultType.
ServerSSE#check_for_result returned the stored result directly and the
stdio initialize handshake read res['result'] itself, so an unrecognized
resultType passed through on those paths. Both now run the same
validation; a stdio initialize error still surfaces as ConnectionError.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoErzDypnq7hhuFBtueML7
simonx1 and others added 2 commits September 1, 2026 20:38
…ot-found

Review findings (grok):
- HTTP, Streamable HTTP and SSE discarded the JSON-RPC body of a 4xx, so
  the 2026-07-28 protocol errors (-32020/-32021/-32022, which the spec
  requires servers to send with HTTP 400) never became typed errors and a
  dual-era client could not recognize a modern server. The body is now
  parsed (gzip-aware) and the typed error raised with the HTTP status in
  the message; 5xx stays TransientServerError.
- resources/read -32602 only means not-found on a modern session; on a
  legacy (2025-11-25) session it remains generic Invalid params. Added
  protocol_version/modern? readers to JsonRpcCommon for the gate.
- A stdio initialize rejected with UnsupportedProtocolVersionError now
  names the versions the server supports; initialize answering with a
  modern version is covered by a test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoErzDypnq7hhuFBtueML7
…and raise_error

Second review round (codex + grok):
- Only a JSON-RPC 2.0 error body carrying the data its schema mandates
  (data.supported for -32022, data.requiredCapabilities for -32021) counts
  as a recognized modern error, so a bare -3202x from a legacy endpoint or
  intermediary cannot suppress the fallback. ServerError#http_status
  records the HTTP status the error arrived with.
- Faraday raise_error middleware no longer bypasses body inspection: a
  4xx raised as Faraday::ClientError is parsed like the response path and
  never becomes a retryable TransportError.
- HTTP error bodies are inspected only up to 64 KiB (gzip expansion
  included); larger bodies yield a plain ServerError without parsing.
- Protocol-level errors (the typed -3202x errors and InvalidResultError,
  ServerError#protocol_error?) propagate through call_tool, get_prompt,
  read_resource and every stdio public method instead of being wrapped
  into ToolCallError and friends, so requiredCapabilities and supported
  versions reach the host.
- A modern result must be an object; an explicit null resultType is
  invalid in either era. Legacy bare-array results stay tolerated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MoErzDypnq7hhuFBtueML7
@simonx1
simonx1 force-pushed the mcp-2026/protocol-foundations branch from b211916 to 8ca799c Compare September 1, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant