Skip to content

fix(vmcp): allow JSON-RPC client responses through authz middleware#5654

Open
syf2211 wants to merge 3 commits into
stacklok:mainfrom
syf2211:fix/5009-client-response-authz-bypass
Open

fix(vmcp): allow JSON-RPC client responses through authz middleware#5654
syf2211 wants to merge 3 commits into
stacklok:mainfrom
syf2211:fix/5009-client-response-authz-bypass

Conversation

@syf2211

@syf2211 syf2211 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

When MCP clients POST JSON-RPC responses to server-initiated requests on the streamable HTTP backchannel (e.g. replying to server pings), vMCP returned 400 Invalid or malformed MCP request instead of 202 Accepted. This caused clients like VS Code and Cursor to tear down sessions every ~30s.

Motivation

Per the MCP streamable HTTP spec, the server must return 202 Accepted for accepted JSON-RPC responses/notifications. The authz middleware rejected these messages because the MCP parser only recognized JSON-RPC requests, leaving GetParsedMCPRequest() nil for valid client responses.

Fixes #5009

Changes

  • pkg/mcp/parser.go: parse JSON-RPC responses into context with IsRequest: false
  • pkg/authz/middleware.go: bypass method authorization for non-request messages
  • Add regression tests in pkg/mcp/parser_test.go and pkg/authz/middleware_test.go

Tests

go test ./pkg/mcp/... ./pkg/authz/... -run 'TestParseMCPRequest|TestMiddleware_AllowsJSONRPC|TestMiddleware_RejectsMalformed'

All targeted tests pass.

Notes

  • Connection authentication is unchanged; only method-level authorization is skipped for responses (which carry no MCP method).
  • Webhook validating/mutating middleware may need a follow-up guard (Method == "") if webhook-enabled streamable-http deployments observe ping-reply regressions; left out of this PR to keep the diff focused on the reported 400 path.

When MCP clients POST replies to server-initiated requests (e.g. ping
responses on the streamable HTTP backchannel), the authz middleware
rejected them with 400 because the MCP parser only recognized JSON-RPC
requests. Parse responses into context with IsRequest=false and bypass
authorization so downstream transport handlers can return 202 per spec.

Fixes stacklok#5009
@github-actions github-actions Bot added the size/XS Extra small PR: < 100 lines changed label Jun 26, 2026
@codecov

codecov Bot commented Jun 26, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.40%. Comparing base (7c574e2) to head (34032c7).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #5654      +/-   ##
==========================================
+ Coverage   70.37%   70.40%   +0.02%     
==========================================
  Files         649      649              
  Lines       66170    66180      +10     
==========================================
+ Hits        46568    46591      +23     
+ Misses      16231    16221      -10     
+ Partials     3371     3368       -3     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Jun 26, 2026
@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Jun 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS Extra small PR: < 100 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

vMCP streamable-http returns 400 on valid client responses to server-initiated requests

2 participants