MCP needs a standard payment layer — x402 onboarding friction is losing users to MPP/Tempo #2436
Replies: 33 comments 8 replies
|
The payment fragmentation problem is real and it has a security dimension worth calling out. We have been testing agent payment protocols (x402, L402, Stripe Connect) as part of a broader agent security harness. The finding: payment is where agent security failures become irreversible. A prompt injection that exfiltrates data is bad. A prompt injection that triggers an unauthorized payment is worse because you cannot undo a blockchain transaction. Three specific risks with the current fragmented approach: 1. No payment authorization chain. When Agent A calls your MCP server and triggers a 402, who authorized the spend? The agent? The human behind the agent? A delegation chain three hops deep? x402 authenticates the wallet, not the intent. Your proposed error response format needs an authorization field that ties the payment to an explicit human approval. 2. Amount manipulation via tool description injection. If the payment amount lives in the error response data, an attacker who can modify tool descriptions (MCP tool description poisoning, which we test for) can change the amount field before the client sees it. The amount needs to be signed by the server, not just returned as a plain JSON field. 3. No refund or dispute path. Your proposal covers the happy path (server requests payment, client fulfills). What happens when the tool call fails after payment? With 263 tools across 74 providers, some will fail. On-chain payments have no chargeback. The spec needs a dispute resolution mechanism or escrow pattern. We published 20 x402-specific security tests covering these patterns: wallet authorization bypass, amount manipulation, replay attacks on payment proofs, and cross-session payment token reuse. Open source: agent-security-harness The broader point: any MCP payment transport spec should be designed with adversarial testing from day one, not bolted on after adoption. |
|
The escrow pattern is the right architecture — Two things worth testing against that model:
On the harness — our x402 module has 20 tests specifically for agent payment protocols: recipient manipulation, session theft, facilitator trust abuse, cross-chain confusion, and amount validation. Would be a good fit for your escrow model. Zero cost, no dependencies, runs in ~60 seconds: pip install agent-security-harness
agent-security test x402 --url https://your-endpoint.comThe HMAC-signed challenge approach you mentioned aligning with MPP is interesting. If there's appetite for it, we could propose a joint contribution to the MCP spec discussion on payment transport — your production escrow data + our adversarial testing results would be a strong foundation. |
|
This is exactly the kind of feedback that makes the harness better. The 5/20 result is a targeting issue, not a security issue, and the fact that the 5 that passed are the ones that actually matter (no data leaks, no session hijacking, rate limiting) is a clean result. On the endpoint targeting: you're right, the harness assumes root URL returns 402, which is the simplest x402 flow but not how production implementations work. Adding agent-security test x402 --url https://apibase.com --paid-path /api/v1/tools/weather.current/callThe harness would hit On the escrow timing: the hard 10s timeout with AbortSignal + atomic PG transaction (REFUNDED or rollback) is clean. The partial-body-at-timeout-boundary case is worth testing explicitly — it's the kind of edge case where implementations silently diverge from the spec. On the delegation token pattern: agreed that a scoped permission token (A signs for B, B presents alongside its own key) is the right direction for multi-hop workflows. That's also testable — our identity harness (18 tests) could validate that delegation tokens are properly scoped and can't be replayed or escalated. Opening the |
|
Quick update @whiteknightonhorse — shipped the agent-security test x402 --url https://apibase.com --paid-path /api/v1/tools/weather.current/callWhen set, payment-specific tests (challenge validation, facilitator trust, recipient manipulation) hit the paid path. General security tests still probe the base URL. Backward compatible — omitting the flag gives the same behavior as before. Once merged, would appreciate a re-run against your production endpoint. The 5 tests that already passed (stateless sessions, no data leaks, rate limiting, clean error messages) should still pass, and the payment flow tests should now get proper 402 responses to validate against. |
This comment was marked as spam.
This comment was marked as spam.
|
pip install --upgrade agent-security-harness
agent-security test x402 --url https://apibase.pro --paid-path /api/v1/tools/geo.geocode/callNote: PyPI still has v3.5.0 — the pip install git+https://github.com/msaleme/red-team-blue-team-agent-fabric.gitTesting against paid (402), cached (200), and free tier endpoints is a great spread. The harness should handle all three gracefully — 402 triggers the payment flow tests, 200 validates the general security properties. On the joint spec contribution — your escrow section outline (atomic PG transactions, cache-hit billing, idempotency, orphaned escrow reconciliation) plus our test methodology and delegation chain validation is a solid structure. Agreed on targeting it as an MCP spec extension rather than standalone. I'll draft the test methodology section covering:
Looking forward to the re-run results. |
|
PR #54 is merged but the PyPI release is behind (3.2.0 on PyPI vs v3.6.0 on git). That is why the In the meantime, installing from git main should work: pip install git+https://github.com/msaleme/red-team-blue-team-agent-fabric.git@mainIf that still shows the error, the issue is the CLI entrypoint not picking up the new argparse flag from the merged code. I will verify and tag you when the release is live. On the joint spec contribution: your four-point structure (escrow flow, cache-hit billing, idempotency, reconciliation) paired with our test methodology section is the right framing. Agree that targeting it as an MCP spec extension rather than standalone gives it more traction. Happy to co-author the test methodology section once you have the escrow draft started. |
|
Update: v3.6.0 is now live on PyPI with the pip install agent-security-harness==3.6.0
agent-security test x402 --url https://apibase.pro --paid-path /api/v1/tools/geo.geocode/callAlso expanded the x402 harness from 20 to 43 tests in this release, adding 18 health check validations (payment challenge completeness, currency validation, recipient verification, address format checks) and the identity verification tests that @FransDevelopment is contributing fixtures for. Looking forward to your re-run results against the APIbase endpoints. |
This comment was marked as spam.
This comment was marked as spam.
|
Lightning-first architectures like this are exactly why I pushed for the x402 harness to focus on semantics rather than a specific rail. If the platform enforces "agent calls tool → gets invoice → pays atomically" and the controls live in code, the payment surface area shrinks dramatically. The two attack classes we keep seeing (regardless of whether it’s Lightning, x402, or L402) are: (1) spend bypasses — agents replaying or underpaying challenges, and (2) facilitator trust — someone swapping out the payee or session context mid-flight. That’s why I added the Curious if you’ve found any gaps Lightning doesn’t solve, especially around facilitator trust or replay. Happy to compare notes if you’re willing to share details (even privately). |
This comment was marked as spam.
This comment was marked as spam.
|
@whiteknightonhorse — this is the kind of feedback that makes the harness better. Running against a production endpoint with 1,700+ calls is exactly the validation we need. Let me address the 7 failures directly: X4-001/004 (POST-only endpoints): Real gap in the harness. Shipping a X4-013 (budget exhaustion returns 401): This is actually a better result than 402. Your AUTH-before-PAYMENT pipeline means unauthenticated burst attacks never reach the payment layer at all. That is the correct defense-in-depth pattern. I will update the test to recognize 401 as a valid mitigation response — the test should pass if the payment endpoint is unreachable to unauthenticated callers. X4-017 (x-request-id header): Agreed — correlation IDs are operational, not vulnerabilities. Will add an allowlist for standard debugging headers (x-request-id, x-trace-id, x-correlation-id) so they do not trigger the info leak detector. X4-021/022/023 (OATR attestation): These are v3.7.0 tests against an emerging standard. Expected to fail on endpoints that have not adopted OATR yet. The fact that all your security-critical tests pass without OATR means your existing auth pipeline is solid — OATR would add defense-in-depth for multi-provider scenarios. Net assessment: 18/25 with zero real vulnerabilities on a production endpoint processing 1,700+ calls with atomic escrow. That is a clean bill of health. The 7 failures are all either harness limitations (X4-001/004/013/017) or emerging standards (X4-021-023). Will ship the @giskard09 — the BOLT11 architecture is interesting. The two attack classes whiteknightonhorse identified (spend bypasses + facilitator trust) apply to Lightning rails too. If you have a test endpoint for Giskard MCP, happy to run the L402 harness against it — we have 14 tests specifically for macaroon/invoice/caveat security. |
This comment was marked as spam.
This comment was marked as spam.
|
@giskard09 — perfect. This is exactly the kind of architectural data we need to make the L402 harness useful beyond the macaroon-native pattern. Your BOLT11 + custom verification flow is actually a cleaner test target for the payment-layer tests than traditional L402. Here is what will be meaningful vs. noise: Tests that should work as-is (7 of 14):
Tests that will fail by design (7 of 14):
We do not have a What the harness needs: Just a URL. Format: pip install agent-security-harness==3.7.0
agent-security test l402 --url https://your-endpoint.com/paid-pathIf your paid path requires POST + JSON body (like whiteknightonhorse's endpoint), add that context and we will include it in the The 1,700+ calls with zero orphaned payments is a strong operational claim. If the harness confirms the anti-replay and session binding hold under adversarial conditions, that is publishable validation data. |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
|
@msaleme @giskard09 — Frans from OATR here. Seeing OATR identity verification included in the security harness (X4-021/022/023) is exactly the right call for this use case. Before an MCP server processes an x402 payment, it should know which agent runtime is on the other side. The core specs are ratified and the SDK is live. Here's everything you need to flip those 3 tests to native passing: Install: npm install @open-agent-trust/registryVerify an agent attestation before processing payment: import { OpenAgentTrustRegistry } from '@open-agent-trust/registry';
const registry = await OpenAgentTrustRegistry.load('https://registry.openagenttrust.com');
const agentJwt = request.headers['x-agent-attestation'];
const result = await registry.verifyToken(agentJwt, 'https://your-api.com');
if (result.isValid) {
// Identity verified — proceed to x402 payment flow
console.log(`Verified agent from issuer: ${result.issuerId}`);
} else {
return res.status(401).json({ error: 'Untrusted agent identity' });
}CLI for manual testing: npx @open-agent-trust/cli verify <JWT_STRING> --audience https://your-api.comThis slots in before the payment layer in the same defense-in-depth pattern @msaleme identified — AUTH before PAYMENT. The registry lookup confirms the agent's runtime is a trusted issuer, then x402 handles the economics. Back to @whiteknightonhorse's original point — MCP needs a standard payment layer, agreed. But a payment spec without an identity layer means any anonymous caller can trigger payment flows. OATR solves the identity half: the MCP server knows who is paying before it decides whether to accept payment. If a payment transport spec lands in MCP, identity verification should be a recommended prerequisite, not an afterthought. Happy to help with integration or provide test fixtures for the harness. |
|
@FransDevelopment — alignment confirmed. The minute we added OATR verification tests (X4-021 through X4-027) the false positives vanished: we can now distinguish between endpoints that simply require auth (X4-013 returning 401 before payment) and endpoints that truly have missing attestation coverage. Appreciate you building the @giskard09 The Haiku agent case study is a perfect test for the payment layer. Once we wrap the |
|
Frans — thank you for the OATR fixtures and the reference server drop. I have X4-021/022/023 queued to run against it as soon as v3.8.0 lands with the new @whiteknightonhorse the dual-rail launch is exactly the data point we needed. I am carving out a dedicated Tempo/Stripe profile for the harness next:
Goal: first nightly with MPP coverage the week of March 31 right after the 3.8.0 release drops. I will ping this thread with a build link so APIbase can be the first external validation run. Appreciate both of you pushing the ecosystem forward. |
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
This comment was marked as spam.
|
added similar request at the newly launched a2a protocol: a2aproject/A2A#1815 , which @msaleme already commented on |
|
Real bug from running an x402 server in production, relevant to the spend-bypass and facilitator-trust points raised above. Our server logged the settle result from the facilitator but never actually checked it before serving the paid data. Both the primary facilitator call and the on-chain fallback could fail and the server would still return 200 with the real data, because success or failure of settlement was never gated on. Separately, two of our endpoints treated any header that was not a recognizable payment format as though payment had succeeded, so a garbage string in the payment header was enough to get free access. Neither of these was caught by us. A reader asked a technical question in a blog comment about whether verification was bound to the wallet or only the amount, and that question is what led to actually re-reading the code and finding both gaps. Fixed now: data is only built after a confirmed settle, and an unrecognized payment format returns an explicit 400 or 402 instead of falling through. The reason I am bringing this up here is that both bugs are the kind a spec would catch by construction. Right now every implementer has to remember on their own that settle failure means reject, and that an invalid payment proof is not the same as no proof and both must be rejected. If a payment transport spec defines these as mandatory rejection states rather than something each server author has to think of independently, this exact class of bug stops being possible to ship by accident. |
|
“x402 authenticates the wallet, not the intent” is the core issue. CAPI2 checks authority, policy, delivery and settlement as one portable receipt. Would a free endpoint preview help test that model? https://capi2-claim-verify.onrender.com/buy |
|
Adding a merchant/operator note on the onboarding friction vs. “payment rail works” split. We’ve seen the same pattern from the seller side of x402: the protocol settles fine once a payload is facilitator-clean, but cold agents (and cold human operators wiring agents) bounce on opaque failure modes that look like wallet/funding problems:
For an MCP payment transport
Happy to compare failure-shape matrices with folks running dual-rail sellers; the agent-side “hours of docs vs 2 minutes hosted wallet” complaint is real, and a lot of that hour is illegible 402s rather than USDC mechanics. |
|
Thanks for connecting this, @slowe89, that's an accurate read of what I found and fixed in August: a custom x402-payment-gated API server that logged the facilitator's settle result but never actually checked it before serving the paid response, so a failed or fake payment still got the real data back. Root cause was the same in two places: no branch on settle.success, and a second spot where an unrecognized payment-header format silently fell through to "payment OK" instead of rejecting. The fix that held up under testing: gate the response build behind a confirmed settle result everywhere data leaves the server, and make any unparseable payment payload an explicit 400/402 rather than a silent pass. Verified live with a junk header (now 400) and a structurally valid but cryptographically fake signed payload (settle fails, now 402 instead of real data). If a conformance vector for settle-before-serve is useful for the spec work, happy to share the exact test cases that caught this on my end. |
|
@holistis thanks — that matches what we were pointing at, and the fix shape (gate on confirmed settle + explicit 400/402 for unparseable headers) is the right conformance bar. Yes, please share the exact vectors if you can paste them here: junk-header → expected status, and structurally valid but crypto-fake-signed → expected status (and which settle field failed). Happy to treat those as settle-before-serve conformance cases. One adjacent seller-side cell from our side, same class: facilitator eventually returns Still comparing failure-shape matrices across sellers if useful; no other ask. |
|
@slowe89 here are the exact vectors. Junk-header, endpoints /api/vuln-search and /api/screen-finding: send an unrecognized string as the PAYMENT-SIGNATURE header (not a valid tx hash, not valid base64 JSON). Expected: 400. Before the fix: 200 with the real data. Structurally valid but crypto-fake-signed, endpoint /api/pt: an EIP-3009 transferWithAuthorization payload that is well-formed but has a forged signature. Which settle field fails: the facilitator call itself rejects with 400, and the on-chain fallback fails specifically on signature recovery, "non-canonical s", not on amount or counterparty. Expected: 402. Before the fix: 200 with the real data. Unrelated free routes and the normal 402 flow without a header are unaffected, no regression there. |
|
For an MCP payment layer, a useful split is create versus approve. send21 prepares payment drafts and pay links. Agents create drafts with scoped keys that cannot spend. Humans sign in their own wallet. send21 never holds keys, never signs, never broadcasts. That keeps fiscal safety on the human (or buyer control plane) while the agent still gets payment capability. Supported: BTC, USDC, USDT, EURC on Bitcoin, Solana, Ethereum, Base. (Never USDT or BTC on Base.) Testnet demo: https://send21.io/demo |
Uh oh!
There was an error while loading. Please reload this page.
Problem
We operate APIbase.pro — an MCP server with 263 tools and 74 providers. We use x402 (HTTP 402 + USDC on Base) for tool-call payments.
The payment protocol works well technically. But we're receiving feedback that the agent-side setup is too hard. A recent user gave up on x402 and switched to Tempo/MPP because their hosted wallet made payments work in 2 minutes vs. hours of reading x402 docs.
Why MCP Should Care
MCP currently has no payment standard. When an MCP tool costs money, each server implements its own payment mechanism. This fragments the ecosystem:
WWW-Authenticate: Payment)Proposal: MCP Payment Transport Spec
MCP should define a standard way for servers to request payment and for clients to fulfill it. The MCP protocol already has a natural extension point —
_metain JSON-RPC responses.A minimal spec could look like:
All reactions