fix: accept text/event-stream and unwrap SSE on /mcp (GV-401)#6
Conversation
The Streamable HTTP transport rejects requests whose Accept header omits
text/event-stream with HTTP 406 ("Client must accept both application/json and
text/event-stream"), so every real tools/list call failed even though login
succeeded. httptest-based tests never caught it because the fake handler did not
enforce the header.
- Send Accept: application/json, text/event-stream.
- Unwrap SSE-framed responses (extract the data: payload) before JSON-RPC decode;
plain application/json still passes through.
- Capture Mcp-Session-Id from responses and echo it on subsequent requests, so
the stateful transport mode works (harmless no-op when stateless).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review 📝 WalkthroughWalkthroughThe PR adds streamable HTTP session semantics to the MCP client by introducing mutex-protected session ID tracking, SSE payload extraction logic, updated request headers that advertise both JSON and event-stream support, refactored retry handling that persists session IDs, and comprehensive tests validating both low-level SSE unwrapping and end-to-end client behavior with a mock server. ChangesMCP Streamable HTTP Session Support
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
📊 Code Quality Score: 28/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
📊 Code Quality Score: 26/100
Was this score accurate? 👍 Yes · 👎 No Scored by GitVelocity · How are scores calculated? |
Problem (found in live testing)
After
gv auth loginsucceeded, every MCP call failed:GitVelocity's MCP server uses the Streamable HTTP transport, which (per the MCP spec) rejects any request whose
Acceptheader doesn't include bothapplication/jsonandtext/event-stream. Our client (like searchlight-cli's) sent onlyapplication/json→ HTTP 406 on the very firstinitialize, sotools/list,whoami, and the post-login cache all failed. The httptest-based tests never caught it because the fake handler didn't enforce the header — exactly the kind of gap only a live run surfaces.Fix
Accept: application/json, text/event-stream.Content-Type: text/event-stream, framing the JSON-RPC message asdata: {...}. The response path now extracts thedata:payload before decoding; a plainapplication/jsonresponse still passes through untouched.Mcp-Session-Id: capture it from any response and echo it on subsequent requests, so the stateful transport mode works (no-op when the server is stateless).Tests
TestExtractRPCPayload— table-driven SSE unwrapping (json passthrough, single event, CRLF, multi-linedata:, charset suffix, no-data fallback).TestStreamableHTTP_AcceptAndSSE— regression: an httptest handler that 406s without the dual Accept, replies via SSE, and hands out a session id; asserts initialize+tools/list succeed, every request advertises both media types, and the session id rides along on the second call.Verify
go test -race ./...✅ · coverage 81.1% · golangci-lint ✅ · gosec ✅Note
Once merged, this rides release-please → v0.1.1 → GoReleaser → updated Homebrew formula. The v0.1.0 already on the tap has the broken transport, so a patch release is needed for
brew-installed users to get a working CLI.🤖 Generated with Claude Code
Summary by CodeRabbit
Release Notes
Bug Fixes & Improvements
Tests