Problem
X402PaymentProvider.decorateToolSchema advertises every paid tool's _meta.x402 in two shapes: the spec-shaped accepts[] array AND a flat copy of the preferred entry's fields (scheme, network, amount, ...). The flat shape is a back-compat shim for pre-#876 clients that don't iterate accepts[].
// src/payments/x402.ts
metaRecord.x402 = {
paymentRequired: true,
...(preferred ?? {}), // flat back-compat fields
...(accepts && { accepts }), // spec-shaped array
};
Two shapes for the same data invites drift (which scheme is "preferred"? both clients diverge over time) and forces every reader to handle both branches. The flat fields also can't express more than one scheme, so any new scheme support requires accepts[] anyway.
Fix
Drop the flat fields once every consumer reads accepts[]. Known consumers to confirm first:
apify/mcpc ≥ the release that lands PR #238 (uses accepts[] end-to-end).
apify/actor-agentic-payments-tester x402 canary ≥ PR #2 (uses accepts[]).
- Any third-party MCP client we know of that reads
_meta.x402 (none on file — please confirm before removal).
After the consumer matrix is green, this PR is a 5-line change: drop the flat spread + the selectPreferredAcceptEntry helper + the four flat-field assertions in the integration suite.
Out of scope
The accepts[] itself, the structuredContent in 402 tool results, and the upto scheme support all stay — only the duplicated flat fields go.
Problem
X402PaymentProvider.decorateToolSchemaadvertises every paid tool's_meta.x402in two shapes: the spec-shapedaccepts[]array AND a flat copy of the preferred entry's fields (scheme,network,amount, ...). The flat shape is a back-compat shim for pre-#876 clients that don't iterateaccepts[].Two shapes for the same data invites drift (which scheme is "preferred"? both clients diverge over time) and forces every reader to handle both branches. The flat fields also can't express more than one scheme, so any new scheme support requires
accepts[]anyway.Fix
Drop the flat fields once every consumer reads
accepts[]. Known consumers to confirm first:apify/mcpc≥ the release that lands PR #238 (usesaccepts[]end-to-end).apify/actor-agentic-payments-testerx402 canary ≥ PR #2 (usesaccepts[])._meta.x402(none on file — please confirm before removal).After the consumer matrix is green, this PR is a 5-line change: drop the flat spread + the
selectPreferredAcceptEntryhelper + the four flat-field assertions in the integration suite.Out of scope
The
accepts[]itself, the structuredContent in 402 tool results, and the upto scheme support all stay — only the duplicated flat fields go.