Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .changeset/mcp-client-inject.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'mppx': minor
---

**Breaking:** Collapsed `McpClient.wrap` and the in-place `wrapClient` variant into a single `McpClient.wrap` API on the `mppx/mcp/client` entrypoint.

`McpClient.wrap` now adds payment handling to an MCP SDK client 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 client reference, like Cloudflare Agents). The MCP SDK `callTool(params, resultSchema?, options?)` signature is preserved, payment challenges are handled whether they arrive as payment-required errors or as tool results carrying `org.paymentauth/payment-required` metadata, and the config accepts `orderChallenges` and `paymentPreferences` alongside `methods` and `onPaymentRequired`. Calling `wrap` on the same client again replaces its payment configuration.

Migration: move per-call options from the second argument to the third — `mcp.callTool(params, undefined, { context, timeout })` — and replace the approval-first overload `mcp.callTool(onPaymentRequired, params, options)` with the `onPaymentRequired` option: `mcp.callTool(params, undefined, { onPaymentRequired })` (pass `null` to bypass a configured hook). The MCP entrypoints moved to `mppx/mcp/client` and `mppx/mcp/server`; the `mppx/mcp-sdk/*` specifiers remain as aliases.
22 changes: 16 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -115,15 +115,25 @@
"types": "./dist/evm/server/index.d.ts",
"default": "./dist/evm/server/index.js"
},
"./mcp/client": {
"src": "./src/mcp/client/index.ts",
"types": "./dist/mcp/client/index.d.ts",
"default": "./dist/mcp/client/index.js"
},
"./mcp/server": {
"src": "./src/mcp/server/index.ts",
"types": "./dist/mcp/server/index.d.ts",
"default": "./dist/mcp/server/index.js"
},
"./mcp-sdk/client": {
"src": "./src/mcp-sdk/client/index.ts",
"types": "./dist/mcp-sdk/client/index.d.ts",
"default": "./dist/mcp-sdk/client/index.js"
"src": "./src/mcp/client/index.ts",
"types": "./dist/mcp/client/index.d.ts",
"default": "./dist/mcp/client/index.js"
},
"./mcp-sdk/server": {
"src": "./src/mcp-sdk/server/index.ts",
"types": "./dist/mcp-sdk/server/index.d.ts",
"default": "./dist/mcp-sdk/server/index.js"
"src": "./src/mcp/server/index.ts",
"types": "./dist/mcp/server/index.d.ts",
"default": "./dist/mcp/server/index.js"
},
"./proxy": {
"src": "./src/proxy/index.ts",
Expand Down
4 changes: 4 additions & 0 deletions src/Mcp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ export const paymentVerificationFailedCode = -32043
/** MCP metadata key for credentials. */
export const credentialMetaKey = 'org.paymentauth/credential'

/** MCP metadata key for payment-required tool results. */
export const paymentRequiredMetaKey = 'org.paymentauth/payment-required'

/** MCP metadata key for receipts. */
export const receiptMetaKey = 'org.paymentauth/receipt'

Expand Down Expand Up @@ -45,6 +48,7 @@ export type JsonRpcRequest = Request & {
*/
export type Result = {
_meta?: {
[paymentRequiredMetaKey]?: ErrorObject['data']
[receiptMetaKey]?: Receipt
[key: string]: unknown
}
Expand Down
228 changes: 0 additions & 228 deletions src/mcp-sdk/client/McpClient.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,7 @@ describe.runIf(isLocalnet)('McpClient.wrap integration', () => {
type WrappedClient = {
callTool: (
params: { name: string; arguments?: Record<string, unknown>; _meta?: Record<string, unknown> },
resultSchema?: undefined,
options?: { context?: unknown; timeout?: number },
) => Promise<McpClient.CallToolResult>
}
Expand Down Expand Up @@ -545,9 +546,14 @@ async function createHarness(options?: {
const clientTransport = new StreamableHTTPClientTransport(new URL(`${httpServer.url}/mcp`))
await sdkClient.connect(clientTransport as never)

const mcp = McpClient.wrap(sdkClient, {
methods: [chargeMethod, sessionMethod],
})
// Wrap a facade over the same session so `sdkClient` keeps raw (challenge-
// throwing) behavior for the credential-level scenarios below.
const mcp = McpClient.wrap(
{ callTool: sdkClient.callTool.bind(sdkClient) as Client['callTool'] },
{
methods: [chargeMethod, sessionMethod],
},
)

return {
async close() {
Expand Down
Loading
Loading