Skip to content

internal/mcp: implement 2026-07-28 error code allocation policy (sa-70) - #2513

Merged
topcheer merged 1 commit into
mainfrom
sa-70-mcp-error-codes
Sep 17, 2026
Merged

topcheer merged 1 commit into
mainfrom
sa-70-mcp-error-codes

Conversation

@topcheer

Copy link
Copy Markdown
Owner

sa-70 / MCP 2026-07-28: error code allocation policy

Implements the 2026-07-28 revision's error-code allocation policy in internal/mcp (changelog).

Spec background

  • The JSON-RPC server-error range is partitioned: -32000..-32019 stays implementation-defined (existing SDK usage grandfathered); -32020..-32099 is reserved for the MCP specification.
  • Draft codes renumbered: HeaderMismatch -32001 -> -32020, MissingRequiredClientCapability -32003 -> -32021, UnsupportedProtocolVersion -32004 -> -32022 (SEP-2575).
  • Resource not found changes from -32002 to -32602 (Invalid Params).

Gap closed

ggcode's MCP client previously had zero awareness of the reserved range or renumbering: servers answering -32020/-32021/-32022 surfaced as opaque JSON-RPC error -32020: ... with no spec context, the initialize path didn't recognize UnsupportedProtocolVersionError, and resources/read failures didn't normalize legacy/new not-found reporting.

Changes

  • New internal/mcp/errorcodes.go: reserved-range constants + grandfathered legacy aliases; classification helpers (isMCPReservedErrorCode, isUnsupportedProtocolVersionCode, isResourceNotFoundCode); decorateSpecError wraps known spec codes with name + actionable hint while keeping the original *Error reachable via errors.As (idempotent, so breaker semantics are untouched); annotateResourceReadError normalizes -32002 / -32602 not-found reporting for the agent.
  • client.go: sendRequest decorates spec-defined errors; Initialize renders an actionable version-rejection diagnostic listing supported versions (recognizes both -32022 and legacy -32004); ReadResource annotates not-found failures.

Verification

  • New unit tests for range boundaries / classification / decoration idempotence.
  • End-to-end httptest pins: decorated HeaderMismatch, version-rejection diagnostic, resource-not-found normalization.
  • Full internal/mcp suite passes (-tags goolm); builds on darwin/arm64, linux/amd64, linux/arm64.

Co-Authored-By: ggcode noreply@ggcode.dev

The MCP 2026-07-28 revision partitions the JSON-RPC server-error range:
-32000..-32019 stays implementation-defined (grandfathered), while
-32020..-32099 is reserved for the MCP specification. The draft codes
were renumbered (HeaderMismatch -32001 -> -32020,
MissingRequiredClientCapability -32003 -> -32021,
UnsupportedProtocolVersion -32004 -> -32022) and resource not found
changed from -32002 to -32602 (Invalid Params).

ggcode's MCP client previously had no awareness of the reserved range or
the renumbering: a server answering -32020/-32021/-32022 surfaced as an
opaque "JSON-RPC error -32020: ..." with no spec context, the initialize
path did not recognize UnsupportedProtocolVersionError, and resources/read
failures did not normalize the legacy/new not-found reporting.

- new internal/mcp/errorcodes.go: reserved-range constants (plus
  grandfathered legacy aliases), classification helpers
  (isMCPReservedErrorCode / isUnsupportedProtocolVersionCode /
  isResourceNotFoundCode), decorateSpecError wrapping known spec codes
  with name+hint while keeping *Error reachable via errors.As, and
  annotateResourceReadError normalizing -32002 / -32602 not-found
  reporting for the agent.
- client.go: sendRequest decorates spec-defined errors; Initialize
  renders an actionable UnsupportedProtocolVersion diagnostic listing
  supported versions (both -32022 and legacy -32004); ReadResource
  annotates not-found failures.

Tests: unit coverage of the range/classification helpers plus end-to-end
httptest pins for the decorated HeaderMismatch, the version-rejection
diagnostic, and resource-not-found normalization. Full internal/mcp
suite passes (goolm); darwin/arm64, linux/amd64, linux/arm64 build.

Co-Authored-By: ggcode <noreply@ggcode.dev>

@topcheer topcheer left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审通过 ✅(三重点核销)

① 区段边界:保留域 -32020..-32099(isMCPReservedErrorCode 严格界检查)+grandfathered 区 -32000..-32019(实现定义)+重编号映射(HeaderMismatch -32001→-32020/MissingRequiredClientCapability -32003→-32021/UnsupportedProtocolVersion -32004→-32022)——与 #2498(-32001 旧值识别)和 #2510(-32022 typed)的既有常量双号并认(legacy+新号同语义)零冲突。

② 透传 vs 拦截边界——hint-only 正确:未知码(保留域内未定义/实现域全部)原样透传+附 specErrorCodeHint 上下文注释——客户端不吞不改码(server 语义权威),只加可操作性解释;isResourceNotFoundCode 的 -32602 歧义显式声明(method 上下文消歧)。

③ 与 #2490 cancelled 码域:cancelled 是 notification 非 error 码(JSON-RPC notification 无 error 面)——无码域交集;#2498 的 HeaderMismatch 处理链升级为双号识别(旧 -32001 刷新重试语义保留)。

常量集中化后消除散落魔数。CI 9/9 绿。可合并。

@topcheer
topcheer merged commit f351d6d into main Sep 17, 2026
9 checks passed
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