Add structured error envelope and server codes for MCP errors (#1581) - #2230
Merged
Conversation
Every JSON-RPC error and tool-result error from the MCP server now carries a canonical `data` envelope (`category`, `suggestion`, `retry_safe`) so MCP clients can branch on a stable machine-readable category instead of parsing the human `message` string. Server-defined codes are allocated in the JSON-RPC reserved range `-32000..-32099`: - `-32000 rate_limited` (#1560 legacy fields preserved) - `-32001 permission_denied` - `-32010 index_missing` - `-32011 index_stale` (SqliteException: no such table or column) - `-32012 index_corrupted` (SqliteException: malformed, not a db, encrypted) - `-32015 request_cancelled` Standard codes (`-32700`, `-32600..-32603`) keep their semantics with new categories layered on top: `parse_error`, `invalid_request`, `message_too_large`, `method_not_found`, `tool_unknown`, `tool_disabled`, `missing_parameter`, `invalid_argument`, `internal_error`. The classifier maps unhandled exceptions to `index_stale`, `index_corrupted`, `request_cancelled`, or `internal_error` from the exception type plus selected SQLite message substrings. The raw exception message is never leaked on the wire (per #1530). Documentation: full code and category map in DEVELOPER_GUIDE.md (English and Japanese). Fixes #1581
- Add the canonical data envelope to the unsupported-protocol handshake error (#1554 helper) so the version-negotiation path now also carries `category=invalid_argument`, `suggestion`, and `retry_safe=false` alongside the pre-existing `supportedVersions` / `requestedVersion` fields. - Fix DEVELOPER_GUIDE.md code/category tables (EN + JA) to match the emitted wire values: `message_too_large` rides `-32700` (frame reader, pre-parse), `tool_unknown` rides `-32602` (invalid params), `tool_disabled` keeps `-32601`. Split the previous row groupings so each (code, category) pair has its own line. - Flip `index_missing.retry_safe` documentation from `false` to `true` to match the emitted value and the regression test: the implementation drops cached DB context so a subsequent retry can reopen after the operator runs an index build. - Extend the existing `Initialize_UnsupportedProtocolVersion_*` test to assert the envelope is present. Refs #1581
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
data.category,data.suggestion,data.retry_safe) to every MCP JSON-RPC error and tool-result error so clients can branch on a stable category instead of parsingmessagestrings (MCP error model uses bare -32603 for everything; no data envelope or server codes #1581).-32000..-32099range —-32000 rate_limited,-32001 permission_denied,-32010 index_missing,-32011 index_stale,-32012 index_corrupted,-32015 request_cancelled— and keeps the standard-32700..-32603codes for envelope-level errors.McpErrorEnvelope.ClassifyExceptionsoSqliteExceptionpatterns map toindex_stale(retry after--rebuild) vsindex_corrupted(delete and rebuild) without leaking the raw message (MCP error path leaks raw ex.Message; DbDebug env-flag risks content leak #1530 stays intact).error_category,tool,caller,retry_after_ms) sit alongside the new canonical envelope, andtool_disabledkeeps its existing-32601wire code.Validation
dotnet build CodeIndex.sln -c Release --no-restore -m:1— succeeded (0 errors, 0 warnings).dotnet test CodeIndex.sln -c Release --no-restore --no-build -m:1— 5066 passed, 3 performance tests skipped (expected), 0 failed.--filter FullyQualifiedName~Mcp) — 355 passed, 0 failed.index_missing.retry_safedoc/code mismatch, message_too_large/tool_unknown row collisions in the doc table); all addressed in 5f52c67. Round 2 found no further actionable issues.Docs / changelog
DEVELOPER_GUIDE.md— added bilingual "Structured error envelope and server codes (MCP error model uses bare -32603 for everything; no data envelope or server codes #1581)" section under the MCP protocol notes, including the full code/category/retry_safe table.changelog.d/unreleased/1581.added.md— bilingual fragment with frontmatter (category: added,issues: [1581]).Follow-ups
None identified during this change. All categories listed in the issue (
index_stale,index_corrupted,resource_limit,unsupported_language,missing_parameter,permission_denied) are covered either by a dedicated server code or by mapping onto an existing JSON-RPC envelope-level code with the newdata.categoryfield.Fixes #1581