Skip to content

fix: unwrap JSON-RPC error envelope for MCP payment challenges#160

Merged
badjer merged 3 commits intomainfrom
fix/mcp-challenge-envelope-unwrap
Apr 13, 2026
Merged

fix: unwrap JSON-RPC error envelope for MCP payment challenges#160
badjer merged 3 commits intomainfrom
fix/mcp-challenge-envelope-unwrap

Conversation

@badjer
Copy link
Copy Markdown
Contributor

@badjer badjer commented Apr 13, 2026

Summary

  • Fix ATXPAccountHandler to unwrap the JSON-RPC error envelope when extracting payment challenge data from MCP server 402 responses
  • MCP servers wrap challenge fields (chargeAmount, x402, mpp) inside { error: { code: -30402, data: { ... } } } — the handler was looking at the top level and finding nothing

Context

Plain Express servers (dev:resource) return challenge fields at the top level, so they worked. MCP servers (search) wrap the 402 in a JSON-RPC error envelope, so buildAuthorizeParams received {}, produced no MPP challenges, and /authorize/auto rejected with 400.

Test plan

  • 208 client tests pass
  • Manual: search MCP server handles MPP payment challenge correctly

🤖 Generated with Claude Code

badjer and others added 3 commits April 13, 2026 12:54
When an MCP server returns a 402 payment challenge, the challenge data
(chargeAmount, x402, mpp) is nested inside a JSON-RPC error envelope
at error.data, not at the top level. The ATXPAccountHandler was parsing
the top level, finding no challenge fields, and calling /authorize/auto
without MPP challenges — causing a 400 from accounts.

Plain Express servers return challenge fields at the top level (no
envelope), so dev:resource worked while MCP servers like search failed.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The response rewriter only hooked res.end(), but MCP Streamable HTTP
sends JSON-RPC responses as SSE "data: {...}" events via res.write().
The rewriter never saw the payment challenge data, so x402/mpp fields
were lost — causing /authorize/auto to fail with "At least one MPP
challenge is required" for MCP servers using SSE transport.

Now hooks both res.write and res.end, and tryRewritePaymentResponse
handles both SSE data lines and plain JSON bodies.

Also unwraps JSON-RPC error envelope in ATXPAccountHandler for cases
where the challenge data arrives as { error: { data: {...} } }.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@badjer badjer merged commit 9f24b5f into main Apr 13, 2026
1 check passed
@badjer badjer deleted the fix/mcp-challenge-envelope-unwrap branch April 13, 2026 21:08
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