From 647d6e4c9d08fba66bb5e10acc77dd943d3b22ba Mon Sep 17 00:00:00 2001 From: bdj Date: Tue, 14 Apr 2026 15:22:22 -0700 Subject: [PATCH 1/4] fix: only advertise protocols with actual challenge data in authorize MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ATXPAccountHandler was hardcoding protocols: ['atxp', 'x402', 'mpp'] regardless of what the MCP server's challenge actually contained. When the server only sent a paymentRequestUrl (no x402 accepts or mpp challenges), /authorize/auto would select x402 via feature flag and fabricate paymentRequirements from the generic receiver field — an ATXP account ID — causing 403 "Destination not allowed for IOU conversion". Now the protocols list is built from what's actually available: - Always 'atxp' (needs only amount + destination) - 'x402' only if paymentRequirements were extracted from the challenge - 'mpp' only if challenges were extracted from the challenge This lets resolveProtocol() fall back to a protocol the client actually has data for, instead of selecting one it can't fulfill. Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/atxp-client/src/atxpAccountHandler.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/packages/atxp-client/src/atxpAccountHandler.ts b/packages/atxp-client/src/atxpAccountHandler.ts index 2494d26..021adb3 100644 --- a/packages/atxp-client/src/atxpAccountHandler.ts +++ b/packages/atxp-client/src/atxpAccountHandler.ts @@ -58,11 +58,19 @@ export class ATXPAccountHandler implements ProtocolHandler { } // Delegate to account.authorize() → accounts /authorize/auto - logger.info('ATXPAccountHandler: delegating to account.authorize()'); + // Only advertise protocols the server actually provided data for. + // Always include 'atxp' (needs only amount + destination). + // Include 'x402' only if the challenge contained x402 accepts. + // Include 'mpp' only if the challenge contained mpp challenges. + const protocols: Array<'atxp' | 'x402' | 'mpp'> = ['atxp']; + if (authorizeParams.paymentRequirements) protocols.push('x402'); + if (authorizeParams.challenges) protocols.push('mpp'); + + logger.info(`ATXPAccountHandler: delegating to account.authorize() with protocols=[${protocols.join(',')}]`); let result; try { result = await account.authorize({ - protocols: ['atxp', 'x402', 'mpp'], + protocols, amount: authorizeParams.amount ? new BigNumber(String(authorizeParams.amount)) : undefined, destination: authorizeParams.destination as string | undefined, paymentRequirements: authorizeParams.paymentRequirements, From 7679dce676390592e2b767392421c0301d1ecaa4 Mon Sep 17 00:00:00 2001 From: bdj Date: Tue, 14 Apr 2026 15:37:22 -0700 Subject: [PATCH 2/4] chore: remove unused eslint-disable directive in x402Wrapper Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/atxp-x402/src/x402Wrapper.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/atxp-x402/src/x402Wrapper.ts b/packages/atxp-x402/src/x402Wrapper.ts index 78edfe5..108d6ff 100644 --- a/packages/atxp-x402/src/x402Wrapper.ts +++ b/packages/atxp-x402/src/x402Wrapper.ts @@ -211,7 +211,6 @@ export const wrapWithX402: FetchWrapper = (config: ClientArgs): FetchLike => { x402ClientInstance.register(network as `${string}:${string}`, scheme); const httpClient = new x402HTTPClient(x402ClientInstance); - // eslint-disable-next-line @typescript-eslint/no-explicit-any const paymentRequired = { x402Version: paymentChallenge.x402Version, accepts: [selectedPaymentRequirements], From e24b1d403358b7627a67ad72949a3fc23910c332 Mon Sep 17 00:00:00 2001 From: bdj Date: Tue, 14 Apr 2026 15:44:50 -0700 Subject: [PATCH 3/4] chore: fix pre-existing lint errors across packages - atxp-server: prefix unused logger param with underscore - atxp-base: remove unused eslint-disable directive Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/atxp-base/src/baseAccount.ts | 1 - packages/atxp-server/src/node/http.ts | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/atxp-base/src/baseAccount.ts b/packages/atxp-base/src/baseAccount.ts index caae4cf..0c7b159 100644 --- a/packages/atxp-base/src/baseAccount.ts +++ b/packages/atxp-base/src/baseAccount.ts @@ -103,7 +103,6 @@ export class BaseAccount implements Account { const httpClient = new x402HTTPClient(client); // Build PaymentRequired envelope from the enriched requirements - // eslint-disable-next-line @typescript-eslint/no-explicit-any const paymentRequired = { x402Version, accepts: [reqs], diff --git a/packages/atxp-server/src/node/http.ts b/packages/atxp-server/src/node/http.ts index fc3184e..81d348a 100644 --- a/packages/atxp-server/src/node/http.ts +++ b/packages/atxp-server/src/node/http.ts @@ -37,7 +37,7 @@ export async function parseMcpRequests(config: ATXPConfig, requestUrl: URL, req: return requests; } -export async function parseBody(req: IncomingMessage, logger: Logger): Promise { +export async function parseBody(req: IncomingMessage, _logger: Logger): Promise { try { const ct = req.headers["content-type"]; From cf97f8c65ad95622e5bbca888d403c7ad4efe026 Mon Sep 17 00:00:00 2001 From: bdj Date: Tue, 14 Apr 2026 15:59:55 -0700 Subject: [PATCH 4/4] fix: update test and fix pre-existing lint errors - Update atxpAccountHandler test to expect protocols=['atxp'] when challenge data has no x402/mpp data - atxp-server: prefix unused logger param with underscore - atxp-base: remove unused eslint-disable directive Co-Authored-By: Claude Opus 4.6 (1M context) --- packages/atxp-client/src/atxpAccountHandler.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/atxp-client/src/atxpAccountHandler.test.ts b/packages/atxp-client/src/atxpAccountHandler.test.ts index 9bcad61..d47c6d9 100644 --- a/packages/atxp-client/src/atxpAccountHandler.test.ts +++ b/packages/atxp-client/src/atxpAccountHandler.test.ts @@ -72,7 +72,7 @@ describe('ATXPAccountHandler', () => { expect(authorize).toHaveBeenCalledTimes(1); expect(authorize).toHaveBeenCalledWith( expect.objectContaining({ - protocols: ['atxp', 'x402', 'mpp'], + protocols: ['atxp'], amount: expect.anything(), }), );