fix: MCP notifications must not receive JSON-RPC responses (#7) - #17
Merged
Conversation
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
WalkthroughThe MCP server now writes responses through an injectable ChangesMCP notification handling
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
detour1999
added a commit
that referenced
this pull request
Aug 3, 2026
Rebasing this branch onto current main brought two integration touchpoints into focus: 1. PR #17 (issue #7 fix) added dispatch-layer tests that used a helper named newTestServer with an io.Writer buffer signature. Harper's later commit added its own newTestServer with a real *db.DB signature. The dispatch tests are still valuable regression guards, so they come back here renamed to newBufferedServer to coexist with the db-backed helper. 2. PR #12 (issue #11 fix) added four scenarios to scenarios.jsonl that the new coverage-drift guard (0575986) legitimately flags as unmapped. Three are covered by existing parser tests, mapped in scenarioCoverage. The fourth — base64-payload-does-not-pollute-fts — asserts extractUserContent behavior on image-block tool_result content, which had no dedicated test before now. TestExtractUserContent_IgnoresImageBlocks pins the "returns empty string → nothing enters FTS" behavior. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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
Closes #7.
ccvault's MCP server was sending JSON-RPC error responses to notifications (messages without an
id), violating JSON-RPC 2.0 §4.1 ("A Notification is a Request object without anidmember … The Server MUST NOT reply to a Notification"). Claude Code's Zod validator rejects theid:nullerror line and drops the stdio transport, so MCP tools were completely unavailable.Verification
Reporter's exact repro before this PR:
Two lines. Second one breaks Claude Code.
After this PR:
One line. Notification is silent.
Also verified
notifications/cancelledandnotifications/roots/list_changed(same class of bug, hit during audit) now produce zero output.What changed
internal/mcp/server.go— three-part fix:case "initialized":tocase "notifications/initialized":(the actual MCP spec name — the bare form was never reached because Claude Code sends the prefixed version)notifications/cancelledandnotifications/roots/list_changedso debug logs are informativedefaultbranch:if req.ID == nil { return }beforesendError, so any unknown notification produces no responseinternal/mcp/server_test.go(new) — six tests via an injectedio.Writer:notifications/some/future/thing) asserts zero output — guards the default-branch fix-32601response — regression guard so we don't over-swallowinitializeasserts the expected result shape — regression guard for the working pathRefactor for testability
Servernow has anout io.Writerfield defaulting toos.StdoutinNewServer. Tests supply abytes.Bufferto inspect emitted bytes without spawning a subprocess.NewServer's signature is unchanged; the field is unexported.Not doing (out of scope)
jsonrpcversion field validation — missing/wrongjsonrpcfield is currently accepted. Permissive here is arguably a feature (robust to slightly non-compliant clients); no compelling reason to tighten.Test plan
-race -count=1notifications/cancelledandnotifications/roots/list_changed— both silent, exit 0Design doc
Full audit + plan: `docs/plans/2026-08-03-mcp-notifications-fix.md`.
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by CodeRabbit
Bug Fixes
Tests
Documentation