Skip to content

feat!: unify mcp client payment wrapping into a single McpClient.wrap#526

Open
parvahuja wants to merge 2 commits into
wevm:mainfrom
parvahuja:parv/mcp-client-inject
Open

feat!: unify mcp client payment wrapping into a single McpClient.wrap#526
parvahuja wants to merge 2 commits into
wevm:mainfrom
parvahuja:parv/mcp-client-inject

Conversation

@parvahuja

@parvahuja parvahuja commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Unify MCP client payment wrapping into a single McpClient.wrap (per review: one obvious API). wrap now adds payment handling in place — the client is mutated and the same reference is returned, so surfaces that keep using the original client become payment-aware (e.g. when another SDK owns the reference, like Cloudflare Agents). Re-wrapping replaces the payment configuration instead of stacking.
  • callTool keeps the exact MCP SDK (params, resultSchema?, options?) signature; context and a per-call onPaymentRequired (pass null to bypass the configured hook) ride in the third argument and are stripped before forwarding.
  • Payment challenges are handled whether they arrive as -32042 errors or as successful tool results carrying org.paymentauth/payment-required metadata; payment-required data is schema-validated. Config gains orderChallenges and paymentPreferences; methods accepts tuples.
  • Move MCP entrypoints to mppx/mcp/client and mppx/mcp/server; mppx/mcp-sdk/* remain as aliases.

Breaking (minor bump, per maintainer sign-off): the previous copy-semantics wrap and its (params, options) signature are replaced by the in-place SDK-shape API above, and the approval-hook-as-first-argument overload from #522 moves to the options argument.

Validation

  • pnpm check:ci, pnpm check:types, pnpm build; full vitest suite green in CI including localnet runtime shards.
  • Export map verified: mppx/mcp-sdk/client and mppx/mcp/client resolve to the identical module.
  • Exercised end-to-end by a deployed Cloudflare Worker paying per tool call on Tempo testnet.

Companion PRs: tempoxyz/mpp#677 (docs), #540 + tempoxyz/accounts#645 (wallet_authorizeChallenge).

@parvahuja

Copy link
Copy Markdown
Contributor Author

I can technically split this into two PRs if that makes it easier to review lmk...

One for the MCP SDK client helpers and another for Tempo Accounts Provider-backed clients

Comment thread src/mcp-sdk/client/McpClient.test-d.ts Outdated
Comment thread src/mcp/client/McpClient.ts
Comment thread src/mcp-sdk/client/McpClient.ts Outdated
Comment thread src/mcp-sdk/client/McpClient.ts Outdated
Comment thread src/mcp-sdk/client/McpClient.ts Outdated
Comment thread src/tempo/client/AccountsProvider.ts Outdated
@parvahuja parvahuja force-pushed the parv/mcp-client-inject branch from 322fec5 to 47c1128 Compare June 11, 2026 17:24
@parvahuja parvahuja changed the title feat: add mcp client injection feat: add wrapClient for in-place mcp client payment injection Jun 11, 2026
@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/mppx@526

commit: a6ea1ae

Comment thread .changeset/stripe-js-types-dependency.md Outdated
@parvahuja parvahuja force-pushed the parv/mcp-client-inject branch 3 times, most recently from dea95d0 to e6e1516 Compare June 11, 2026 18:25
@parvahuja parvahuja marked this pull request as ready for review June 11, 2026 18:50
@parvahuja parvahuja requested a review from brendanjryan June 11, 2026 18:50
@brendanjryan

Copy link
Copy Markdown
Collaborator

some comments -- can we just have a single .wrap interface which handles all of this automatically?

Parv Ahuja added 2 commits June 11, 2026 14:40
Renames src/mcp-sdk to src/mcp and adds the mppx/mcp/client and
mppx/mcp/server entrypoints. The published mppx/mcp-sdk/client and
mppx/mcp-sdk/server specifiers remain as aliases resolving to the same
dist files, so existing imports keep working.
Collapses McpClient.wrap and wrapClient: wrap now mutates the client in
place and returns the same reference, preserves the MCP SDK
callTool(params, resultSchema?, options?) signature (context and a
per-call onPaymentRequired ride in the options argument), handles
payment challenges from both payment-required errors and tool-result
metadata, accepts orderChallenges/paymentPreferences, and validates
challenge payloads with the Challenge schema.
@parvahuja parvahuja marked this pull request as draft June 11, 2026 22:26
@parvahuja parvahuja force-pushed the parv/mcp-client-inject branch from 1d464df to a6ea1ae Compare June 11, 2026 22:27
@parvahuja parvahuja changed the title feat: add wrapClient for in-place mcp client payment injection feat!: unify mcp client payment wrapping into a single McpClient.wrap Jun 11, 2026

@brendanjryan brendanjryan left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment thread .changeset/mcp-client-inject.md Outdated
'mppx': patch
---

Added `wrapClient` to the new `mppx/mcp/client` entrypoint for adding automatic payment handling to an SDK-owned MCP client in place: the client is mutated and the same reference is returned, the MCP SDK `callTool(params, resultSchema?, options?)` signature is preserved (method `context` is passed via the options argument), and payment challenges returned as tool results via `org.paymentauth/payment-required` metadata are handled alongside payment-required errors. The MCP entrypoints moved to `mppx/mcp/client` and `mppx/mcp/server`; the `mppx/mcp-sdk/client` and `mppx/mcp-sdk/server` specifiers remain as aliases.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we make this a bit shorter. we can just keep the first sentence before the :

Comment thread src/mcp/client/McpClient.test-d.ts Outdated
})
})

describe('McpClient.wrapClient', () => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just wrap? `it's somewhat stuttering to do xClient.wrapClient

type CallToolRequestOptions = Parameters<Client['callTool']>[2]
type PaymentRequiredData = NonNullable<core_Mcp.ErrorObject['data']>

const MPPX_MCP_CLIENT_WRAPPER = Symbol.for('mppx.mcp.client.wrapper')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

Comment thread src/server/Transport.ts
import { serviceWorker } from './internal/html/serviceWorker.gen.js'

export { type McpSdk, mcpSdk } from '../mcp-sdk/server/Transport.js'
export { type McpSdk, mcpSdk } from '../mcp/server/Transport.js'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@parvahuja parvahuja marked this pull request as ready for review June 11, 2026 23:26
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.

2 participants