@devlab.group/agent-commerce 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -128
- package/dist/ap2.d.ts +5 -5
- package/dist/ap2.js +19 -11
- package/dist/ap2.js.map +1 -1
- package/dist/{authorization-CPDcpJVa.d.ts → authorization-DA7mjy_O.d.ts} +4 -4
- package/dist/{chunk-ZEGFLRGV.js → chunk-5GEWKNIH.js} +5 -4
- package/dist/chunk-5GEWKNIH.js.map +1 -0
- package/dist/chunk-6D2EZ5ME.js +27 -0
- package/dist/chunk-6D2EZ5ME.js.map +1 -0
- package/dist/chunk-NKNXVDHN.js +701 -0
- package/dist/chunk-NKNXVDHN.js.map +1 -0
- package/dist/{chunk-NWIQLJNU.js → chunk-PBYN7EK2.js} +33 -31
- package/dist/chunk-PBYN7EK2.js.map +1 -0
- package/dist/{chunk-GF6KHHKL.js → chunk-US622BKF.js} +3 -3
- package/dist/{chunk-GF6KHHKL.js.map → chunk-US622BKF.js.map} +1 -1
- package/dist/cli/index.js +339 -107
- package/dist/cli/index.js.map +1 -1
- package/dist/constants-6mypC60h.d.ts +50 -0
- package/dist/index.d.ts +26 -11
- package/dist/index.js +189 -36
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +3 -3
- package/dist/mcp.js +4 -1
- package/dist/mcp.js.map +1 -1
- package/dist/mpp.d.ts +50 -0
- package/dist/mpp.js +351 -0
- package/dist/mpp.js.map +1 -0
- package/dist/{protocol-adapter-Bebmggf_.d.ts → protocol-adapter-APRjs1E2.d.ts} +2 -2
- package/dist/{runtime-CKq3d_3K.d.ts → runtime-DC5XQ9Cc.d.ts} +24 -13
- package/dist/x402.d.ts +1 -1
- package/dist/x402.js +7 -688
- package/dist/x402.js.map +1 -1
- package/package.json +13 -2
- package/dist/chunk-NWIQLJNU.js.map +0 -1
- package/dist/chunk-ZEGFLRGV.js.map +0 -1
package/dist/mcp.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { H as HttpProtocolAdapter } from './protocol-adapter-
|
|
1
|
+
import { H as HttpProtocolAdapter } from './protocol-adapter-APRjs1E2.js';
|
|
2
2
|
import 'node:http';
|
|
3
|
-
import './runtime-
|
|
4
|
-
import './authorization-
|
|
3
|
+
import './runtime-DC5XQ9Cc.js';
|
|
4
|
+
import './authorization-DA7mjy_O.js';
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* MCP protocol adapter.
|
package/dist/mcp.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PACKAGE_VERSION, toCommerceError, CommerceError, extractReservedInputFields, PAYMENT_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-
|
|
1
|
+
import { PACKAGE_VERSION, toCommerceError, CommerceError, extractReservedInputFields, PAYMENT_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-5GEWKNIH.js';
|
|
2
2
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
3
|
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
4
4
|
import { ListToolsRequestSchema, CallToolRequestSchema, LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
|
|
@@ -86,6 +86,9 @@ function paymentInputFieldDescription(resource) {
|
|
|
86
86
|
if (method === "x402") {
|
|
87
87
|
return "x402 payment proof (base64 PAYMENT-SIGNATURE value) returned from a previous payment-required response.";
|
|
88
88
|
}
|
|
89
|
+
if (method === "mpp") {
|
|
90
|
+
return 'MPP credential (the full "Authorization: Payment ..." value) for the challenge in a previous payment-required response.';
|
|
91
|
+
}
|
|
89
92
|
if (method !== void 0) {
|
|
90
93
|
return `${method} payment proof (base64-encoded) returned from a previous payment-required response.`;
|
|
91
94
|
}
|
package/dist/mcp.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocols/mcp/descriptor.ts","../src/protocols/mcp/result-mapping.ts","../src/protocols/mcp/tool-mapping.ts","../src/protocols/mcp/adapter.ts"],"names":[],"mappings":"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","file":"mcp.js","sourcesContent":["/**\n * Adapter self-description.\n *\n * `supportedSpec` reports the MCP protocol revision this adapter targets, as\n * negotiated by the installed @modelcontextprotocol/sdk@1.30.0 build.\n *\n * Verified against the shipped SDK (not guessed):\n * `dist/esm/types.js` exports `LATEST_PROTOCOL_VERSION = '2025-11-25'` and\n * `SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, '2025-06-18',\n * '2025-03-26', '2024-11-05', '2024-10-07']`. `dist/esm/server/index.js`\n * (`_oninitialize`) negotiates by echoing the client-requested version when\n * it is in `SUPPORTED_PROTOCOL_VERSIONS`, and falling back to\n * `LATEST_PROTOCOL_VERSION` otherwise — so `LATEST_PROTOCOL_VERSION` is the\n * single most accurate value to report as \"the\" supported spec revision.\n */\nimport { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';\nimport type { AdapterDescriptor } from '../../core/index.js';\n\n/** This package's own version — independent of the negotiated MCP spec revision. */\nexport { PACKAGE_VERSION } from '../../version.js';\n\n/** The MCP protocol revision this adapter targets (see module doc above). */\nexport const MCP_SUPPORTED_SPEC = LATEST_PROTOCOL_VERSION;\n\n/** Tool-oriented capabilities this adapter actually implements. */\nexport const MCP_CAPABILITIES: readonly string[] = ['tools/list', 'tools/call'];\n\n/**\n * MCP surfaces this adapter does not implement in this release. Kept explicit\n * so `doctor` / the support matrix never imply blanket protocol compatibility.\n *\n * `dns-rebinding-protection` is not a missing *feature* so much as a\n * delegated one: this transport does not validate `Origin`/`Host` itself\n * (see adapter.ts's module doc for why) — the gateway's `onRequest` hook\n * does, for `/mcp` and the HTTP routes together. Listed here so alpha\n * honesty holds even for a security property, not just a protocol surface:\n * an operator reading this adapter's own descriptor should not conclude it\n * provides Origin validation on its own.\n */\nexport const MCP_UNSUPPORTED: readonly string[] = [\n 'resources',\n 'prompts',\n 'sampling',\n 'completions',\n 'elicitation',\n 'roots',\n 'logging',\n 'notifications/tools/list_changed',\n 'tasks',\n 'dns-rebinding-protection',\n];\n\nexport function buildDescriptor(implementationVersion: string): AdapterDescriptor {\n return {\n name: 'mcp',\n kind: 'protocol',\n implementationVersion,\n supportedSpec: MCP_SUPPORTED_SPEC,\n capabilities: MCP_CAPABILITIES,\n status: 'stable',\n unsupported: MCP_UNSUPPORTED,\n };\n}\n","/**\n * Maps execution-pipeline results and payment-proof input to their MCP wire\n * representation. Uses only the frozen wire helpers from core\n * (`toErrorEnvelope`, `toPaymentRequiredEnvelope`) so the MCP adapter, the\n * HTTP route and the demo buyer agent can never drift apart.\n */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n type CommerceError,\n DELIVERY_SUMMARY_META_KEY,\n type DeliveredOutcome,\n type ExecutionOutcome,\n PAYMENT_INPUT_FIELD,\n type PaymentRequiredOutcome,\n toDeliverySummary,\n toErrorEnvelope,\n toPaymentRequiredEnvelope,\n} from '../../core/index.js';\n\nfunction toRecord(value: object): Record<string, unknown> {\n return value as Record<string, unknown>;\n}\n\nexport function deliveredResult(outcome: DeliveredOutcome): CallToolResult {\n const body = outcome.body;\n const text = typeof body === 'string' ? body : JSON.stringify(body ?? null);\n const isStructured = typeof body === 'object' && body !== null && !Array.isArray(body);\n return {\n content: [{ type: 'text', text }],\n ...(isStructured ? { structuredContent: toRecord(body) } : {}),\n _meta: { [DELIVERY_SUMMARY_META_KEY]: toRecord(toDeliverySummary(outcome)) },\n };\n}\n\nexport function paymentRequiredResult(outcome: PaymentRequiredOutcome): CallToolResult {\n const envelope = toPaymentRequiredEnvelope(outcome);\n const p = envelope.payment;\n const text = `Payment required: ${p.amount} ${p.currency} to ${p.destination} for resource \"${outcome.resourceId}\". Retry the call with a ${p.provider} payment proof in the \"${PAYMENT_INPUT_FIELD}\" input field.`;\n return {\n isError: true,\n content: [{ type: 'text', text }],\n structuredContent: toRecord(envelope),\n };\n}\n\nexport function errorResult(error: CommerceError): CallToolResult {\n const envelope = toErrorEnvelope(error);\n return {\n isError: true,\n content: [{ type: 'text', text: `${envelope.code}: ${envelope.message}` }],\n structuredContent: toRecord(envelope),\n };\n}\n\nexport function mapOutcome(outcome: ExecutionOutcome): CallToolResult {\n return outcome.kind === 'delivered' ? deliveredResult(outcome) : paymentRequiredResult(outcome);\n}\n","/**\n * Maps a canonical `CommerceResource` to an MCP `Tool`.\n *\n * One tool per resource: tool name = resource id, description carries a\n * clear price notice for paid resources, and input schema is the canonical\n * JSON Schema (preserved as-is, including per-property descriptions) with the\n * reserved `_payment` property added for paid resources.\n */\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n type CommerceResource,\n PAYMENT_INPUT_FIELD,\n type PaymentMethodName,\n} from '../../core/index.js';\n\n/**\n * MCP tool names must match SEP-986: 1-128 chars of [A-Za-z0-9._-].\n *\n * Mirrors the pattern enforced by @modelcontextprotocol/sdk@1.30.0 itself\n * (`dist/esm/shared/toolNameValidation.js`: `TOOL_NAME_REGEX =\n * /^[A-Za-z0-9._-]{1,128}$/`), read from the installed build rather than\n * guessed. We validate independently (instead of importing that internal,\n * unexported module path) so a resource with an illegal id fails loudly here\n * instead of being silently registered and warned about by the SDK.\n */\nexport const MCP_TOOL_NAME_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;\n\nexport function isValidToolName(id: string): boolean {\n return MCP_TOOL_NAME_PATTERN.test(id);\n}\n\nexport function isPaidResource(resource: CommerceResource): boolean {\n return resource.pricing.type !== 'free';\n}\n\n/**\n * The rail a resource actually accepts, per its own canonical configuration.\n * Never hard-coded here — the adapter does not decide which payment method a\n * resource uses, it only reflects what the resource declares. `undefined`\n * when the resource lists none (still possible for a priced resource; the\n * pipeline is the one that decides what happens then, not this adapter).\n */\nfunction primaryPaymentMethod(resource: CommerceResource): PaymentMethodName | undefined {\n return resource.paymentMethods[0];\n}\n\n/** Human-facing note on how to supply a proof, generic when no rail is configured. */\nfunction paymentProofNote(resource: CommerceResource): string {\n const method = primaryPaymentMethod(resource);\n const rail = method !== undefined ? `a ${method}` : 'a';\n return `Requires ${rail} payment proof in the \"${PAYMENT_INPUT_FIELD}\" input field (obtained from a previous payment-required response).`;\n}\n\n/**\n * Description for the reserved `_payment` input property. Mentions x402's\n * `PAYMENT-SIGNATURE` header convention by name only when the resource\n * actually lists x402 as its method — a different future rail would have a\n * different proof encoding, so that detail must not be asserted for it.\n */\nfunction paymentInputFieldDescription(resource: CommerceResource): string {\n const method = primaryPaymentMethod(resource);\n if (method === 'x402') {\n return 'x402 payment proof (base64 PAYMENT-SIGNATURE value) returned from a previous payment-required response.';\n }\n if (method !== undefined) {\n return `${method} payment proof (base64-encoded) returned from a previous payment-required response.`;\n }\n return 'Payment proof returned from a previous payment-required response.';\n}\n\n/**\n * Tool description. For a paid resource this appends a clear, unavoidable\n * price notice so an agent can see the resource costs money before calling\n * it — never buried only in the input schema.\n */\nexport function buildToolDescription(resource: CommerceResource): string {\n const base = resource.description ?? resource.name;\n switch (resource.pricing.type) {\n case 'free':\n return base;\n case 'fixed': {\n const { amount, currency } = resource.pricing;\n return `${base} Costs ${amount} ${currency} per call. ${paymentProofNote(resource)}`;\n }\n case 'dynamic':\n return `${base} Requires payment (amount determined at request time). ${paymentProofNote(resource)}`;\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Builds the MCP `Tool.inputSchema` from the canonical `CommerceResource.inputSchema`.\n *\n * The canonical schema is already JSON Schema, so it is carried through\n * verbatim (properties, descriptions, `required`, and any other JSON Schema\n * keyword) — only `type` is forced to the literal `'object'` MCP requires,\n * and `properties`/`required` are merged rather than replaced. For a paid\n * resource, the reserved optional `_payment` string property is added.\n */\nexport function buildInputSchema(resource: CommerceResource): Tool['inputSchema'] {\n const base = resource.inputSchema;\n const baseIsObject = isPlainObject(base);\n\n const basePropertyEntries: readonly [string, object][] =\n baseIsObject && isPlainObject(base.properties)\n ? Object.entries(base.properties).filter((entry): entry is [string, object] =>\n isPlainObject(entry[1]),\n )\n : [];\n const properties: Record<string, object> = Object.fromEntries(basePropertyEntries);\n\n if (isPaidResource(resource)) {\n // Overwrites any resource-declared `_payment` property. Config is\n // responsible for rejecting that collision at load time — this is not\n // re-checked here.\n properties[PAYMENT_INPUT_FIELD] = {\n type: 'string',\n description: paymentInputFieldDescription(resource),\n };\n }\n\n const required =\n baseIsObject && Array.isArray(base.required)\n ? base.required.filter((v): v is string => typeof v === 'string')\n : [];\n\n const extra = baseIsObject\n ? Object.fromEntries(\n Object.entries(base).filter(\n ([key]) => key !== 'type' && key !== 'properties' && key !== 'required',\n ),\n )\n : {};\n\n return {\n ...extra,\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n}\n","/**\n * MCP protocol adapter.\n *\n * One MCP tool per canonical resource exposed via `exposedVia: ['mcp']`.\n * Every `tools/call` builds a `CanonicalRequest` and goes through\n * `context.pipeline.execute()` — this file never calls a merchant backend and\n * never inspects a payment object, it only surfaces what the pipeline\n * returns.\n *\n * Transport: Streamable HTTP, **stateless** mode (no `sessionIdGenerator`,\n * i.e. session id generation left undefined). A fresh low-level `Server` +\n * `StreamableHTTPServerTransport` pair is created per HTTP request and torn\n * down when the response closes —\n * this is the pattern @modelcontextprotocol/sdk@1.30.0's own\n * `examples/server/simpleStatelessStreamableHttp.js` uses, and it avoids\n * holding cross-request session state the gateway has no lifecycle hook for.\n *\n * Tool registration uses the low-level `Server` (`setRequestHandler` for\n * `ListToolsRequestSchema` / `CallToolRequestSchema`) rather than the\n * higher-level `McpServer.registerTool`. `McpServer.registerTool`'s\n * `inputSchema` only accepts a Zod schema or a raw Zod shape\n * (`server/zod-compat.d.ts`: `AnySchema = z3.ZodTypeAny | z4.$ZodType`) — it\n * does not accept a raw JSON Schema object. The canonical\n * `CommerceResource.inputSchema` is already JSON Schema, and the MCP wire\n * format for `Tool.inputSchema` *is* JSON Schema, so building `Tool` objects\n * directly (via the low-level `Server`) carries it through verbatim with no\n * lossy JSON-Schema-to-Zod conversion. `Server` is marked `@deprecated` in\n * favour of `McpServer`'s ergonomics, but remains fully supported — its\n * documented use is exactly this kind of advanced, non-Zod case.\n *\n * Origin/Host validation (DNS-rebinding protection): deliberately NOT done\n * here. `StreamableHTTPServerTransport` is constructed with no\n * `allowedHosts`/`allowedOrigins`/`enableDnsRebindingProtection` — all three\n * are `@deprecated` in the pinned SDK's own\n * `webStandardStreamableHttp.d.ts`, in favour of exactly the fix applied\n * here: an allowlist enforced by the *host* before a request ever reaches an\n * adapter. `src/gateway`'s `onRequest` hook is that enforcement point —\n * it covers `/mcp` and the HTTP routes together, so there is one allowlist\n * for the whole gateway instead of one per adapter. This adapter has no\n * config surface to build a second one from: `McpAdapterOptions` is frozen\n * (docs/contracts.md) to `{ mountPath?, serverName?, serverVersion? }`, and\n * the only signal available without a contract change —\n * `context.publicBaseUrl` — is one string that may not match what a\n * reverse-proxied deployment's `Host`/`Origin` headers actually carry. A\n * second, narrower allowlist built from it would not add coverage the\n * gateway's hook doesn't already provide; it would only add a second place\n * that can reject legitimate traffic the gateway just allowed, for a\n * deprecated code path upstream is steering consumers away from. Revisit\n * this if the adapter is ever meant to be mounted somewhere other than this\n * gateway. See `descriptor.unsupported` — this reliance on the host is\n * recorded there too, not just here, so `doctor`/`.well-known` surface it.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n type Tool,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n type AdapterDescriptor,\n type AdapterHealth,\n type CanonicalRequest,\n CommerceError,\n type CommerceResource,\n extractReservedInputFields,\n type HttpProtocolAdapter,\n type ProtocolAdapterContext,\n toCommerceError,\n} from '../../core/index.js';\nimport { buildDescriptor, PACKAGE_VERSION } from './descriptor.js';\nimport { errorResult, mapOutcome } from './result-mapping.js';\nimport {\n buildInputSchema,\n buildToolDescription,\n isValidToolName,\n MCP_TOOL_NAME_PATTERN,\n} from './tool-mapping.js';\n\nexport interface McpAdapterOptions {\n /** Path prefix the gateway mounts this adapter at. Default '/mcp'. */\n readonly mountPath?: string;\n /** MCP `Implementation.name` reported during initialize. */\n readonly serverName?: string;\n /** MCP `Implementation.version` reported during initialize. Default: this package's version. */\n readonly serverVersion?: string;\n}\n\ninterface RegisteredTool {\n readonly resource: CommerceResource;\n readonly tool: Tool;\n}\n\ninterface SkippedResource {\n readonly id: string;\n readonly reason: string;\n}\n\nconst DEFAULT_MOUNT_PATH = '/mcp';\nconst DEFAULT_SERVER_NAME = 'agent-commerce';\n\n/**\n * The pinned MCP SDK's Streamable HTTP transport\n * accepts a JSON-RPC **batch** (a bare array in the POST body) and dispatches\n * every element to this adapter's `tools/call` handler in one synchronous\n * `for` loop with no `await` between iterations and no cap on the array's\n * length (`webStandardStreamableHttp.js`'s `handlePostRequest`, via\n * `shared/protocol.js`'s `_onrequest`, which fires the handler and returns\n * without waiting for it to settle). Nothing between the transport and this\n * adapter enforces stateless mode's own precondition that `tools/call`\n * requires no prior `initialize` — so one POST, no handshake, N `tools/call`\n * messages, is a legal request that becomes N concurrent\n * `context.pipeline.execute()` calls, each of which may end in a live\n * `fetch()` to the merchant's backend. 8 keeps a handful of genuinely\n * concurrent tool calls (the common case for an agent working a multi-step\n * task) from ever queuing, while still bounding the worst case to a small,\n * fixed number of simultaneous outbound connections regardless of how large\n * a batch a caller sends. The worst case measured without it was 5000\n * concurrent backend calls from a single request.\n */\nconst MAX_CONCURRENT_TOOL_CALLS = 8;\n\n/**\n * The semaphore above bounds concurrency but not\n * queue depth — `acquireToolCallSlot` pushed one resolver per waiting call\n * onto `toolCallWaiters` with no ceiling, so an oversized batch (thousands\n * of `tools/call` messages, still well under the gateway's own 1 MB body\n * cap) queued in full and then *ran* in full, including the ~30 seconds\n * after the client had already disconnected. 64 is 8x\n * MAX_CONCURRENT_TOOL_CALLS: enough that a legitimate short burst from one\n * agent never gets rejected (the measured honest case tops out at a\n * handful of concurrent calls), while capping the adapter's total\n * exposure — in flight plus queued — to a small, fixed number of real\n * `pipeline.execute()` calls no matter how large a batch a caller sends.\n * Calls beyond the queue fail fast with no backend call at all, rather\n * than piling up behind it.\n *\n * Scope note: this cap is per `McpProtocolAdapter` instance.\n * The gateway's own SSE-subscriber cap is per gateway instance. Both\n * happen to be one-per-process today, so the two read the same in\n * practice — but they are not the same scope, and that stops being true\n * the moment either one is ever instantiated more than once per process.\n */\nconst MAX_QUEUED_TOOL_CALLS = 64;\n\nexport class McpProtocolAdapter implements HttpProtocolAdapter {\n readonly name = 'mcp' as const;\n readonly mountPath: string;\n readonly descriptor: AdapterDescriptor;\n\n private readonly serverName: string;\n private readonly serverVersion: string;\n\n private context: ProtocolAdapterContext | undefined;\n private started = false;\n private tools: readonly RegisteredTool[] = [];\n private toolsByResourceId: ReadonlyMap<string, CommerceResource> = new Map();\n private skipped: readonly SkippedResource[] = [];\n private readonly activeTransports = new Set<StreamableHTTPServerTransport>();\n\n // Counting semaphore bounding concurrent `context.pipeline.execute()`\n // calls. Lives on the adapter instance (one per gateway mount, for the\n // process lifetime), not per-request, so the cap holds across concurrent\n // `/mcp` requests too — not just within one oversized batch. A request\n // only ever waits here once MAX_CONCURRENT_TOOL_CALLS executions are\n // already in flight adapter-wide, which is the throttle working as\n // intended, not two unrelated single-call requests blocking each other.\n private inFlightToolCalls = 0;\n private readonly toolCallWaiters: Array<() => void> = [];\n\n constructor(options: McpAdapterOptions = {}) {\n this.mountPath = options.mountPath ?? DEFAULT_MOUNT_PATH;\n this.serverName = options.serverName ?? DEFAULT_SERVER_NAME;\n this.serverVersion = options.serverVersion ?? PACKAGE_VERSION;\n this.descriptor = buildDescriptor(PACKAGE_VERSION);\n }\n\n async start(context: ProtocolAdapterContext): Promise<void> {\n this.context = context;\n this.started = false;\n\n let resources: readonly CommerceResource[] = [];\n try {\n resources = context.resources.listExposedVia('mcp');\n } catch (err) {\n context.logger.error(\n { adapter: 'mcp', err: toCommerceError(err).toInfo() },\n 'mcp adapter: failed to list mcp-exposed resources',\n );\n resources = [];\n }\n\n const tools: RegisteredTool[] = [];\n const toolsByResourceId = new Map<string, CommerceResource>();\n const skipped: SkippedResource[] = [];\n\n for (const resource of resources) {\n try {\n if (!isValidToolName(resource.id)) {\n skipped.push({\n id: resource.id,\n reason: `resource id is not a legal MCP tool name (must match ${MCP_TOOL_NAME_PATTERN.source})`,\n });\n continue;\n }\n if (toolsByResourceId.has(resource.id)) {\n skipped.push({ id: resource.id, reason: 'duplicate tool name' });\n continue;\n }\n const tool: Tool = {\n name: resource.id,\n description: buildToolDescription(resource),\n inputSchema: buildInputSchema(resource),\n };\n tools.push({ resource, tool });\n toolsByResourceId.set(resource.id, resource);\n } catch (err) {\n skipped.push({\n id: resource.id,\n reason: `failed to build MCP tool: ${toCommerceError(err).message}`,\n });\n }\n }\n\n for (const s of skipped) {\n context.logger.warn(\n { adapter: 'mcp', resourceId: s.id, reason: s.reason },\n 'mcp adapter: resource skipped',\n );\n }\n\n this.tools = tools;\n this.toolsByResourceId = toolsByResourceId;\n this.skipped = skipped;\n this.started = true;\n\n context.logger.info(\n {\n adapter: 'mcp',\n mountPath: this.mountPath,\n toolCount: tools.length,\n skippedCount: skipped.length,\n },\n 'mcp adapter started',\n );\n }\n\n async handleHttp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n if (!this.started || !this.context) {\n this.writeJsonRpcError(res, 503, 'MCP adapter is not running.');\n return;\n }\n if (req.method !== 'POST') {\n this.writeJsonRpcError(res, 405, 'Method not allowed. This endpoint only accepts POST.');\n return;\n }\n\n // one AbortController per HTTP request, aborted\n // from the same `res` 'close' handler that already tears down the\n // transport/server pair. `handleToolCall` checks this after acquiring\n // its concurrency slot — never mid-`pipeline.execute()`, since a call\n // that already reached settlement must be allowed to finish (aborting\n // there is worse than finishing: the buyer may already be charged).\n const abortController = new AbortController();\n const server = this.buildServer(abortController.signal);\n // Stateless mode: omitting `sessionIdGenerator` (rather than setting it\n // to `undefined`) is required under `exactOptionalPropertyTypes`, and\n // has identical runtime behaviour — see\n // dist/esm/server/webStandardStreamableHttp.js: session handling is\n // gated on `!this.sessionIdGenerator`, true either way.\n const transport = new StreamableHTTPServerTransport();\n this.activeTransports.add(transport);\n\n const cleanup = (): void => {\n abortController.abort();\n this.activeTransports.delete(transport);\n transport.close().catch(() => {});\n server.close().catch(() => {});\n };\n res.once('close', cleanup);\n\n // `StreamableHTTPServerTransport implements Transport` per the SDK's\n // own declaration; the cast works around its `onclose`/`onerror`\n // accessors being typed `T | undefined` where `Transport` declares a\n // bare optional `T`, which only conflicts under this project's\n // `exactOptionalPropertyTypes`.\n await server.connect(transport as Transport);\n await transport.handleRequest(req, res);\n } catch (err) {\n this.context?.logger.error(\n { adapter: 'mcp', err: toCommerceError(err).toInfo() },\n 'mcp adapter: request handling failed',\n );\n this.writeJsonRpcError(res, 500, 'Internal server error.');\n }\n }\n\n async health(): Promise<AdapterHealth> {\n const checkedAt = this.context?.clock.nowIso() ?? new Date().toISOString();\n try {\n if (!this.started || !this.context) {\n return { status: 'fail', detail: 'MCP adapter has not been started.', checkedAt };\n }\n const toolCount = this.tools.length;\n if (this.skipped.length > 0) {\n const detail = `${toolCount} tool(s) registered; ${this.skipped.length} resource(s) skipped: ${this.skipped\n .map((s) => `${s.id} (${s.reason})`)\n .join('; ')}`;\n return { status: 'warn', detail, checkedAt };\n }\n return { status: 'pass', detail: `${toolCount} tool(s) registered.`, checkedAt };\n } catch (err) {\n return {\n status: 'fail',\n detail: `mcp adapter health check failed: ${toCommerceError(err).message}`,\n checkedAt,\n };\n }\n }\n\n async stop(): Promise<void> {\n this.started = false;\n const transports = [...this.activeTransports];\n this.activeTransports.clear();\n await Promise.all(\n transports.map(async (transport) => {\n try {\n await transport.close();\n } catch {\n // best-effort cleanup — stop() must be idempotent and never throw.\n }\n }),\n );\n this.context = undefined;\n }\n\n private writeJsonRpcError(res: ServerResponse, status: number, message: string): void {\n if (res.headersSent) return;\n res.writeHead(status, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32000, message }, id: null }));\n }\n\n private buildServer(signal: AbortSignal): Server {\n const server = new Server(\n { name: this.serverName, version: this.serverVersion },\n { capabilities: { tools: {} } },\n );\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: this.tools.map((t) => t.tool),\n }));\n server.setRequestHandler(CallToolRequestSchema, async (request) =>\n this.handleToolCall(request.params.name, request.params.arguments ?? {}, signal),\n );\n return server;\n }\n\n private async handleToolCall(\n resourceId: string,\n rawArgs: Record<string, unknown>,\n signal: AbortSignal,\n ): Promise<CallToolResult> {\n const context = this.context;\n if (!context) {\n return errorResult(new CommerceError('INTERNAL_ERROR', 'MCP adapter is not running.'));\n }\n try {\n // Defence in depth: `tools/list` only ever advertises mcp-exposed,\n // legal-name resources, but a client can still send `tools/call` for\n // any name. Gate here too (core also enforces exposedVia in the\n // pipeline) — do not rely on core alone. Message stays identical to a\n // genuinely unknown id so we never reveal that a resource exists but\n // is scoped to another protocol.\n const resource = this.toolsByResourceId.get(resourceId);\n if (!resource) {\n return errorResult(\n new CommerceError('RESOURCE_NOT_FOUND', `Unknown tool \"${resourceId}\".`, { resourceId }),\n );\n }\n const requestId = context.ids.next('mcp');\n const { input, payment, authorization } = extractReservedInputFields(\n rawArgs,\n resource,\n requestId,\n );\n const request: CanonicalRequest = {\n requestId,\n resourceId,\n input,\n protocol: 'mcp',\n receivedAt: context.clock.nowIso(),\n ...(payment !== undefined ? { payment } : {}),\n ...(authorization !== undefined ? { authorization } : {}),\n };\n await this.acquireToolCallSlot(signal);\n try {\n // the only cancellation point. A call queued\n // behind a full semaphore, whose caller has since disconnected,\n // must not start a fresh pipeline.execute() (and possibly a live\n // merchant-backend fetch) — that is the \"runs for 30s after the\n // client left\" bug. Checked here and nowhere else: once execute()\n // is called it may reach settle(), and an in-flight payment must be\n // allowed to finish rather than be abandoned mid-flight.\n if (signal.aborted) {\n // deliberately *not* GATEWAY_BUSY. That code\n // means \"transient, back off and retry\" — true for the queue-full\n // case below, false here: there is no caller left to retry, so\n // telling one to would be meaningless. PROTOCOL_UNSUPPORTED is the\n // least dishonest fit among the frozen codes (non-retryable, which\n // is the one property that matters for a response nobody reads),\n // not a precise description of \"the caller went away\" — none of\n // the frozen codes names that condition. Left flagged as a known\n // gap rather than reused past what it's honestly for.\n return errorResult(\n new CommerceError(\n 'PROTOCOL_UNSUPPORTED',\n 'Client disconnected before this call started.',\n ),\n );\n }\n const outcome = await context.pipeline.execute(request);\n return mapOutcome(outcome);\n } finally {\n // Always release, even if execute() throws — a stranded permit\n // would shrink MAX_CONCURRENT_TOOL_CALLS by one forever and\n // eventually deadlock the adapter, which is worse.\n this.releaseToolCallSlot();\n }\n } catch (err) {\n return errorResult(toCommerceError(err));\n }\n }\n\n /**\n * Blocks until fewer than MAX_CONCURRENT_TOOL_CALLS executions are in\n * flight, or throws if the queue behind that gate is already full or the\n * caller disconnected while waiting. Throwing\n * here never leaks a permit: `inFlightToolCalls` is only incremented on\n * the success path below, after every rejection point.\n */\n private async acquireToolCallSlot(signal: AbortSignal): Promise<void> {\n if (this.toolCallWaiters.length >= MAX_QUEUED_TOOL_CALLS) {\n // GATEWAY_BUSY, not PROTOCOL_UNSUPPORTED. This\n // is load shedding, which is transient by definition — the caller\n // should back off and retry, matching the message below. Before\n // GATEWAY_BUSY existed this threw PROTOCOL_UNSUPPORTED (HTTP 501,\n // `retryable: false`), so the envelope told an agent framework keyed\n // on the machine-readable flag that a momentary throttle was a\n // permanent capability gap — contradicting this exact message.\n throw new CommerceError(\n 'GATEWAY_BUSY',\n 'Too many tool calls already queued on this adapter; retry later.',\n );\n }\n // `while`, not `if`. A wake-up only means a slot\n // was *freed*, not that this waiter is now entitled to it regardless of\n // what else has happened since — re-check the same condition the loop\n // waited on rather than assume one wake-up means one free slot forever.\n // (Currently that assumption would also happen to hold, since\n // `releaseToolCallSlot` decrements before waking the next waiter and JS\n // has no thread to race it — but that is a scheduling fact about this\n // file, not something `if` states, and it is exactly the kind of thing\n // a later refactor breaks silently. `while` doesn't depend on it.)\n while (this.inFlightToolCalls >= MAX_CONCURRENT_TOOL_CALLS) {\n await new Promise<void>((resolve) => this.toolCallWaiters.push(resolve));\n if (signal.aborted) {\n // This waiter is declining the slot that was just freed for it —\n // pass it straight to the next waiter in line instead of stranding\n // everyone behind it. Without this, a disconnect partway through a\n // deep queue leaves every later waiter's promise waiting on a\n // wake-up call that only its own dedicated release() would have\n // sent — and that release never comes, because this waiter never\n // takes the slot that would have produced it.\n this.toolCallWaiters.shift()?.();\n // PROTOCOL_UNSUPPORTED, not GATEWAY_BUSY —\n // same reasoning as the other disconnect check above. Non-retryable\n // is correct here (nobody is listening to retry); \"unsupported\" is\n // not a precise name for \"the caller left\", it's just the least\n // dishonest fit among the frozen codes.\n throw new CommerceError('PROTOCOL_UNSUPPORTED', 'Client disconnected while queued.');\n }\n }\n this.inFlightToolCalls++;\n }\n\n private releaseToolCallSlot(): void {\n this.inFlightToolCalls--;\n // Wake the oldest waiter, if any; it will re-increment once it resumes.\n this.toolCallWaiters.shift()?.();\n }\n}\n\nexport function createMcpAdapter(options?: McpAdapterOptions): HttpProtocolAdapter {\n return new McpProtocolAdapter(options ?? {});\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/protocols/mcp/descriptor.ts","../src/protocols/mcp/result-mapping.ts","../src/protocols/mcp/tool-mapping.ts","../src/protocols/mcp/adapter.ts"],"names":[],"mappings":"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","file":"mcp.js","sourcesContent":["/**\n * Adapter self-description.\n *\n * `supportedSpec` reports the MCP protocol revision this adapter targets, as\n * negotiated by the installed @modelcontextprotocol/sdk@1.30.0 build.\n *\n * Verified against the shipped SDK (not guessed):\n * `dist/esm/types.js` exports `LATEST_PROTOCOL_VERSION = '2025-11-25'` and\n * `SUPPORTED_PROTOCOL_VERSIONS = [LATEST_PROTOCOL_VERSION, '2025-06-18',\n * '2025-03-26', '2024-11-05', '2024-10-07']`. `dist/esm/server/index.js`\n * (`_oninitialize`) negotiates by echoing the client-requested version when\n * it is in `SUPPORTED_PROTOCOL_VERSIONS`, and falling back to\n * `LATEST_PROTOCOL_VERSION` otherwise — so `LATEST_PROTOCOL_VERSION` is the\n * single most accurate value to report as \"the\" supported spec revision.\n */\nimport { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';\nimport type { AdapterDescriptor } from '../../core/index.js';\n\n/** This package's own version — independent of the negotiated MCP spec revision. */\nexport { PACKAGE_VERSION } from '../../version.js';\n\n/** The MCP protocol revision this adapter targets (see module doc above). */\nexport const MCP_SUPPORTED_SPEC = LATEST_PROTOCOL_VERSION;\n\n/** Tool-oriented capabilities this adapter actually implements. */\nexport const MCP_CAPABILITIES: readonly string[] = ['tools/list', 'tools/call'];\n\n/**\n * MCP surfaces this adapter does not implement in this release. Kept explicit\n * so `doctor` / the support matrix never imply blanket protocol compatibility.\n *\n * `dns-rebinding-protection` is not a missing *feature* so much as a\n * delegated one: this transport does not validate `Origin`/`Host` itself\n * (see adapter.ts's module doc for why) — the gateway's `onRequest` hook\n * does, for `/mcp` and the HTTP routes together. Listed here so alpha\n * honesty holds even for a security property, not just a protocol surface:\n * an operator reading this adapter's own descriptor should not conclude it\n * provides Origin validation on its own.\n */\nexport const MCP_UNSUPPORTED: readonly string[] = [\n 'resources',\n 'prompts',\n 'sampling',\n 'completions',\n 'elicitation',\n 'roots',\n 'logging',\n 'notifications/tools/list_changed',\n 'tasks',\n 'dns-rebinding-protection',\n];\n\nexport function buildDescriptor(implementationVersion: string): AdapterDescriptor {\n return {\n name: 'mcp',\n kind: 'protocol',\n implementationVersion,\n supportedSpec: MCP_SUPPORTED_SPEC,\n capabilities: MCP_CAPABILITIES,\n status: 'stable',\n unsupported: MCP_UNSUPPORTED,\n };\n}\n","/**\n * Maps execution-pipeline results and payment-proof input to their MCP wire\n * representation. Uses only the frozen wire helpers from core\n * (`toErrorEnvelope`, `toPaymentRequiredEnvelope`) so the MCP adapter, the\n * HTTP route and the demo buyer agent can never drift apart.\n */\n\nimport type { CallToolResult } from '@modelcontextprotocol/sdk/types.js';\nimport {\n type CommerceError,\n DELIVERY_SUMMARY_META_KEY,\n type DeliveredOutcome,\n type ExecutionOutcome,\n PAYMENT_INPUT_FIELD,\n type PaymentRequiredOutcome,\n toDeliverySummary,\n toErrorEnvelope,\n toPaymentRequiredEnvelope,\n} from '../../core/index.js';\n\nfunction toRecord(value: object): Record<string, unknown> {\n return value as Record<string, unknown>;\n}\n\nexport function deliveredResult(outcome: DeliveredOutcome): CallToolResult {\n const body = outcome.body;\n const text = typeof body === 'string' ? body : JSON.stringify(body ?? null);\n const isStructured = typeof body === 'object' && body !== null && !Array.isArray(body);\n return {\n content: [{ type: 'text', text }],\n ...(isStructured ? { structuredContent: toRecord(body) } : {}),\n _meta: { [DELIVERY_SUMMARY_META_KEY]: toRecord(toDeliverySummary(outcome)) },\n };\n}\n\nexport function paymentRequiredResult(outcome: PaymentRequiredOutcome): CallToolResult {\n const envelope = toPaymentRequiredEnvelope(outcome);\n const p = envelope.payment;\n const text = `Payment required: ${p.amount} ${p.currency} to ${p.destination} for resource \"${outcome.resourceId}\". Retry the call with a ${p.provider} payment proof in the \"${PAYMENT_INPUT_FIELD}\" input field.`;\n return {\n isError: true,\n content: [{ type: 'text', text }],\n structuredContent: toRecord(envelope),\n };\n}\n\nexport function errorResult(error: CommerceError): CallToolResult {\n const envelope = toErrorEnvelope(error);\n return {\n isError: true,\n content: [{ type: 'text', text: `${envelope.code}: ${envelope.message}` }],\n structuredContent: toRecord(envelope),\n };\n}\n\nexport function mapOutcome(outcome: ExecutionOutcome): CallToolResult {\n return outcome.kind === 'delivered' ? deliveredResult(outcome) : paymentRequiredResult(outcome);\n}\n","/**\n * Maps a canonical `CommerceResource` to an MCP `Tool`.\n *\n * One tool per resource: tool name = resource id, description carries a\n * clear price notice for paid resources, and input schema is the canonical\n * JSON Schema (preserved as-is, including per-property descriptions) with the\n * reserved `_payment` property added for paid resources.\n */\n\nimport type { Tool } from '@modelcontextprotocol/sdk/types.js';\nimport {\n type CommerceResource,\n PAYMENT_INPUT_FIELD,\n type PaymentMethodName,\n} from '../../core/index.js';\n\n/**\n * MCP tool names must match SEP-986: 1-128 chars of [A-Za-z0-9._-].\n *\n * Mirrors the pattern enforced by @modelcontextprotocol/sdk@1.30.0 itself\n * (`dist/esm/shared/toolNameValidation.js`: `TOOL_NAME_REGEX =\n * /^[A-Za-z0-9._-]{1,128}$/`), read from the installed build rather than\n * guessed. We validate independently (instead of importing that internal,\n * unexported module path) so a resource with an illegal id fails loudly here\n * instead of being silently registered and warned about by the SDK.\n */\nexport const MCP_TOOL_NAME_PATTERN = /^[A-Za-z0-9._-]{1,128}$/;\n\nexport function isValidToolName(id: string): boolean {\n return MCP_TOOL_NAME_PATTERN.test(id);\n}\n\nexport function isPaidResource(resource: CommerceResource): boolean {\n return resource.pricing.type !== 'free';\n}\n\n/**\n * The rail a resource actually accepts, per its own canonical configuration.\n * Never hard-coded here — the adapter does not decide which payment method a\n * resource uses, it only reflects what the resource declares. `undefined`\n * when the resource lists none (still possible for a priced resource; the\n * pipeline is the one that decides what happens then, not this adapter).\n */\nfunction primaryPaymentMethod(resource: CommerceResource): PaymentMethodName | undefined {\n return resource.paymentMethods[0];\n}\n\n/** Human-facing note on how to supply a proof, generic when no rail is configured. */\nfunction paymentProofNote(resource: CommerceResource): string {\n const method = primaryPaymentMethod(resource);\n const rail = method !== undefined ? `a ${method}` : 'a';\n return `Requires ${rail} payment proof in the \"${PAYMENT_INPUT_FIELD}\" input field (obtained from a previous payment-required response).`;\n}\n\n/**\n * Description for the reserved `_payment` input property, in the proof\n * encoding of the resource's own rail.\n */\nfunction paymentInputFieldDescription(resource: CommerceResource): string {\n const method = primaryPaymentMethod(resource);\n if (method === 'x402') {\n return 'x402 payment proof (base64 PAYMENT-SIGNATURE value) returned from a previous payment-required response.';\n }\n if (method === 'mpp') {\n return 'MPP credential (the full \"Authorization: Payment ...\" value) for the challenge in a previous payment-required response.';\n }\n if (method !== undefined) {\n return `${method} payment proof (base64-encoded) returned from a previous payment-required response.`;\n }\n return 'Payment proof returned from a previous payment-required response.';\n}\n\n/**\n * Tool description. For a paid resource this appends a clear, unavoidable\n * price notice so an agent can see the resource costs money before calling\n * it — never buried only in the input schema.\n */\nexport function buildToolDescription(resource: CommerceResource): string {\n const base = resource.description ?? resource.name;\n switch (resource.pricing.type) {\n case 'free':\n return base;\n case 'fixed': {\n const { amount, currency } = resource.pricing;\n return `${base} Costs ${amount} ${currency} per call. ${paymentProofNote(resource)}`;\n }\n case 'dynamic':\n return `${base} Requires payment (amount determined at request time). ${paymentProofNote(resource)}`;\n }\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Builds the MCP `Tool.inputSchema` from the canonical `CommerceResource.inputSchema`.\n *\n * The canonical schema is already JSON Schema, so it is carried through\n * verbatim (properties, descriptions, `required`, and any other JSON Schema\n * keyword) — only `type` is forced to the literal `'object'` MCP requires,\n * and `properties`/`required` are merged rather than replaced. For a paid\n * resource, the reserved optional `_payment` string property is added.\n */\nexport function buildInputSchema(resource: CommerceResource): Tool['inputSchema'] {\n const base = resource.inputSchema;\n const baseIsObject = isPlainObject(base);\n\n const basePropertyEntries: readonly [string, object][] =\n baseIsObject && isPlainObject(base.properties)\n ? Object.entries(base.properties).filter((entry): entry is [string, object] =>\n isPlainObject(entry[1]),\n )\n : [];\n const properties: Record<string, object> = Object.fromEntries(basePropertyEntries);\n\n if (isPaidResource(resource)) {\n // Overwrites any resource-declared `_payment` property. Config is\n // responsible for rejecting that collision at load time — this is not\n // re-checked here.\n properties[PAYMENT_INPUT_FIELD] = {\n type: 'string',\n description: paymentInputFieldDescription(resource),\n };\n }\n\n const required =\n baseIsObject && Array.isArray(base.required)\n ? base.required.filter((v): v is string => typeof v === 'string')\n : [];\n\n const extra = baseIsObject\n ? Object.fromEntries(\n Object.entries(base).filter(\n ([key]) => key !== 'type' && key !== 'properties' && key !== 'required',\n ),\n )\n : {};\n\n return {\n ...extra,\n type: 'object',\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n}\n","/**\n * MCP protocol adapter.\n *\n * One MCP tool per canonical resource exposed via `exposedVia: ['mcp']`.\n * Every `tools/call` builds a `CanonicalRequest` and goes through\n * `context.pipeline.execute()` — this file never calls a merchant backend and\n * never inspects a payment object, it only surfaces what the pipeline\n * returns.\n *\n * Transport: Streamable HTTP, **stateless** mode (no `sessionIdGenerator`,\n * i.e. session id generation left undefined). A fresh low-level `Server` +\n * `StreamableHTTPServerTransport` pair is created per HTTP request and torn\n * down when the response closes —\n * this is the pattern @modelcontextprotocol/sdk@1.30.0's own\n * `examples/server/simpleStatelessStreamableHttp.js` uses, and it avoids\n * holding cross-request session state the gateway has no lifecycle hook for.\n *\n * Tool registration uses the low-level `Server` (`setRequestHandler` for\n * `ListToolsRequestSchema` / `CallToolRequestSchema`) rather than the\n * higher-level `McpServer.registerTool`. `McpServer.registerTool`'s\n * `inputSchema` only accepts a Zod schema or a raw Zod shape\n * (`server/zod-compat.d.ts`: `AnySchema = z3.ZodTypeAny | z4.$ZodType`) — it\n * does not accept a raw JSON Schema object. The canonical\n * `CommerceResource.inputSchema` is already JSON Schema, and the MCP wire\n * format for `Tool.inputSchema` *is* JSON Schema, so building `Tool` objects\n * directly (via the low-level `Server`) carries it through verbatim with no\n * lossy JSON-Schema-to-Zod conversion. `Server` is marked `@deprecated` in\n * favour of `McpServer`'s ergonomics, but remains fully supported — its\n * documented use is exactly this kind of advanced, non-Zod case.\n *\n * Origin/Host validation (DNS-rebinding protection): deliberately NOT done\n * here. `StreamableHTTPServerTransport` is constructed with no\n * `allowedHosts`/`allowedOrigins`/`enableDnsRebindingProtection` — all three\n * are `@deprecated` in the pinned SDK's own\n * `webStandardStreamableHttp.d.ts`, in favour of exactly the fix applied\n * here: an allowlist enforced by the *host* before a request ever reaches an\n * adapter. `src/gateway`'s `onRequest` hook is that enforcement point —\n * it covers `/mcp` and the HTTP routes together, so there is one allowlist\n * for the whole gateway instead of one per adapter. This adapter has no\n * config surface to build a second one from: `McpAdapterOptions` is frozen\n * (docs/contracts.md) to `{ mountPath?, serverName?, serverVersion? }`, and\n * the only signal available without a contract change —\n * `context.publicBaseUrl` — is one string that may not match what a\n * reverse-proxied deployment's `Host`/`Origin` headers actually carry. A\n * second, narrower allowlist built from it would not add coverage the\n * gateway's hook doesn't already provide; it would only add a second place\n * that can reject legitimate traffic the gateway just allowed, for a\n * deprecated code path upstream is steering consumers away from. Revisit\n * this if the adapter is ever meant to be mounted somewhere other than this\n * gateway. See `descriptor.unsupported` — this reliance on the host is\n * recorded there too, not just here, so `doctor`/`.well-known` surface it.\n */\nimport type { IncomingMessage, ServerResponse } from 'node:http';\nimport { Server } from '@modelcontextprotocol/sdk/server/index.js';\nimport { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';\nimport type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';\nimport {\n CallToolRequestSchema,\n type CallToolResult,\n ListToolsRequestSchema,\n type Tool,\n} from '@modelcontextprotocol/sdk/types.js';\nimport {\n type AdapterDescriptor,\n type AdapterHealth,\n type CanonicalRequest,\n CommerceError,\n type CommerceResource,\n extractReservedInputFields,\n type HttpProtocolAdapter,\n type ProtocolAdapterContext,\n toCommerceError,\n} from '../../core/index.js';\nimport { buildDescriptor, PACKAGE_VERSION } from './descriptor.js';\nimport { errorResult, mapOutcome } from './result-mapping.js';\nimport {\n buildInputSchema,\n buildToolDescription,\n isValidToolName,\n MCP_TOOL_NAME_PATTERN,\n} from './tool-mapping.js';\n\nexport interface McpAdapterOptions {\n /** Path prefix the gateway mounts this adapter at. Default '/mcp'. */\n readonly mountPath?: string;\n /** MCP `Implementation.name` reported during initialize. */\n readonly serverName?: string;\n /** MCP `Implementation.version` reported during initialize. Default: this package's version. */\n readonly serverVersion?: string;\n}\n\ninterface RegisteredTool {\n readonly resource: CommerceResource;\n readonly tool: Tool;\n}\n\ninterface SkippedResource {\n readonly id: string;\n readonly reason: string;\n}\n\nconst DEFAULT_MOUNT_PATH = '/mcp';\nconst DEFAULT_SERVER_NAME = 'agent-commerce';\n\n/**\n * The pinned MCP SDK's Streamable HTTP transport\n * accepts a JSON-RPC **batch** (a bare array in the POST body) and dispatches\n * every element to this adapter's `tools/call` handler in one synchronous\n * `for` loop with no `await` between iterations and no cap on the array's\n * length (`webStandardStreamableHttp.js`'s `handlePostRequest`, via\n * `shared/protocol.js`'s `_onrequest`, which fires the handler and returns\n * without waiting for it to settle). Nothing between the transport and this\n * adapter enforces stateless mode's own precondition that `tools/call`\n * requires no prior `initialize` — so one POST, no handshake, N `tools/call`\n * messages, is a legal request that becomes N concurrent\n * `context.pipeline.execute()` calls, each of which may end in a live\n * `fetch()` to the merchant's backend. 8 keeps a handful of genuinely\n * concurrent tool calls (the common case for an agent working a multi-step\n * task) from ever queuing, while still bounding the worst case to a small,\n * fixed number of simultaneous outbound connections regardless of how large\n * a batch a caller sends. The worst case measured without it was 5000\n * concurrent backend calls from a single request.\n */\nconst MAX_CONCURRENT_TOOL_CALLS = 8;\n\n/**\n * The semaphore above bounds concurrency but not\n * queue depth — `acquireToolCallSlot` pushed one resolver per waiting call\n * onto `toolCallWaiters` with no ceiling, so an oversized batch (thousands\n * of `tools/call` messages, still well under the gateway's own 1 MB body\n * cap) queued in full and then *ran* in full, including the ~30 seconds\n * after the client had already disconnected. 64 is 8x\n * MAX_CONCURRENT_TOOL_CALLS: enough that a legitimate short burst from one\n * agent never gets rejected (the measured honest case tops out at a\n * handful of concurrent calls), while capping the adapter's total\n * exposure — in flight plus queued — to a small, fixed number of real\n * `pipeline.execute()` calls no matter how large a batch a caller sends.\n * Calls beyond the queue fail fast with no backend call at all, rather\n * than piling up behind it.\n *\n * Scope note: this cap is per `McpProtocolAdapter` instance.\n * The gateway's own SSE-subscriber cap is per gateway instance. Both\n * happen to be one-per-process today, so the two read the same in\n * practice — but they are not the same scope, and that stops being true\n * the moment either one is ever instantiated more than once per process.\n */\nconst MAX_QUEUED_TOOL_CALLS = 64;\n\nexport class McpProtocolAdapter implements HttpProtocolAdapter {\n readonly name = 'mcp' as const;\n readonly mountPath: string;\n readonly descriptor: AdapterDescriptor;\n\n private readonly serverName: string;\n private readonly serverVersion: string;\n\n private context: ProtocolAdapterContext | undefined;\n private started = false;\n private tools: readonly RegisteredTool[] = [];\n private toolsByResourceId: ReadonlyMap<string, CommerceResource> = new Map();\n private skipped: readonly SkippedResource[] = [];\n private readonly activeTransports = new Set<StreamableHTTPServerTransport>();\n\n // Counting semaphore bounding concurrent `context.pipeline.execute()`\n // calls. Lives on the adapter instance (one per gateway mount, for the\n // process lifetime), not per-request, so the cap holds across concurrent\n // `/mcp` requests too — not just within one oversized batch. A request\n // only ever waits here once MAX_CONCURRENT_TOOL_CALLS executions are\n // already in flight adapter-wide, which is the throttle working as\n // intended, not two unrelated single-call requests blocking each other.\n private inFlightToolCalls = 0;\n private readonly toolCallWaiters: Array<() => void> = [];\n\n constructor(options: McpAdapterOptions = {}) {\n this.mountPath = options.mountPath ?? DEFAULT_MOUNT_PATH;\n this.serverName = options.serverName ?? DEFAULT_SERVER_NAME;\n this.serverVersion = options.serverVersion ?? PACKAGE_VERSION;\n this.descriptor = buildDescriptor(PACKAGE_VERSION);\n }\n\n async start(context: ProtocolAdapterContext): Promise<void> {\n this.context = context;\n this.started = false;\n\n let resources: readonly CommerceResource[] = [];\n try {\n resources = context.resources.listExposedVia('mcp');\n } catch (err) {\n context.logger.error(\n { adapter: 'mcp', err: toCommerceError(err).toInfo() },\n 'mcp adapter: failed to list mcp-exposed resources',\n );\n resources = [];\n }\n\n const tools: RegisteredTool[] = [];\n const toolsByResourceId = new Map<string, CommerceResource>();\n const skipped: SkippedResource[] = [];\n\n for (const resource of resources) {\n try {\n if (!isValidToolName(resource.id)) {\n skipped.push({\n id: resource.id,\n reason: `resource id is not a legal MCP tool name (must match ${MCP_TOOL_NAME_PATTERN.source})`,\n });\n continue;\n }\n if (toolsByResourceId.has(resource.id)) {\n skipped.push({ id: resource.id, reason: 'duplicate tool name' });\n continue;\n }\n const tool: Tool = {\n name: resource.id,\n description: buildToolDescription(resource),\n inputSchema: buildInputSchema(resource),\n };\n tools.push({ resource, tool });\n toolsByResourceId.set(resource.id, resource);\n } catch (err) {\n skipped.push({\n id: resource.id,\n reason: `failed to build MCP tool: ${toCommerceError(err).message}`,\n });\n }\n }\n\n for (const s of skipped) {\n context.logger.warn(\n { adapter: 'mcp', resourceId: s.id, reason: s.reason },\n 'mcp adapter: resource skipped',\n );\n }\n\n this.tools = tools;\n this.toolsByResourceId = toolsByResourceId;\n this.skipped = skipped;\n this.started = true;\n\n context.logger.info(\n {\n adapter: 'mcp',\n mountPath: this.mountPath,\n toolCount: tools.length,\n skippedCount: skipped.length,\n },\n 'mcp adapter started',\n );\n }\n\n async handleHttp(req: IncomingMessage, res: ServerResponse): Promise<void> {\n try {\n if (!this.started || !this.context) {\n this.writeJsonRpcError(res, 503, 'MCP adapter is not running.');\n return;\n }\n if (req.method !== 'POST') {\n this.writeJsonRpcError(res, 405, 'Method not allowed. This endpoint only accepts POST.');\n return;\n }\n\n // one AbortController per HTTP request, aborted\n // from the same `res` 'close' handler that already tears down the\n // transport/server pair. `handleToolCall` checks this after acquiring\n // its concurrency slot — never mid-`pipeline.execute()`, since a call\n // that already reached settlement must be allowed to finish (aborting\n // there is worse than finishing: the buyer may already be charged).\n const abortController = new AbortController();\n const server = this.buildServer(abortController.signal);\n // Stateless mode: omitting `sessionIdGenerator` (rather than setting it\n // to `undefined`) is required under `exactOptionalPropertyTypes`, and\n // has identical runtime behaviour — see\n // dist/esm/server/webStandardStreamableHttp.js: session handling is\n // gated on `!this.sessionIdGenerator`, true either way.\n const transport = new StreamableHTTPServerTransport();\n this.activeTransports.add(transport);\n\n const cleanup = (): void => {\n abortController.abort();\n this.activeTransports.delete(transport);\n transport.close().catch(() => {});\n server.close().catch(() => {});\n };\n res.once('close', cleanup);\n\n // `StreamableHTTPServerTransport implements Transport` per the SDK's\n // own declaration; the cast works around its `onclose`/`onerror`\n // accessors being typed `T | undefined` where `Transport` declares a\n // bare optional `T`, which only conflicts under this project's\n // `exactOptionalPropertyTypes`.\n await server.connect(transport as Transport);\n await transport.handleRequest(req, res);\n } catch (err) {\n this.context?.logger.error(\n { adapter: 'mcp', err: toCommerceError(err).toInfo() },\n 'mcp adapter: request handling failed',\n );\n this.writeJsonRpcError(res, 500, 'Internal server error.');\n }\n }\n\n async health(): Promise<AdapterHealth> {\n const checkedAt = this.context?.clock.nowIso() ?? new Date().toISOString();\n try {\n if (!this.started || !this.context) {\n return { status: 'fail', detail: 'MCP adapter has not been started.', checkedAt };\n }\n const toolCount = this.tools.length;\n if (this.skipped.length > 0) {\n const detail = `${toolCount} tool(s) registered; ${this.skipped.length} resource(s) skipped: ${this.skipped\n .map((s) => `${s.id} (${s.reason})`)\n .join('; ')}`;\n return { status: 'warn', detail, checkedAt };\n }\n return { status: 'pass', detail: `${toolCount} tool(s) registered.`, checkedAt };\n } catch (err) {\n return {\n status: 'fail',\n detail: `mcp adapter health check failed: ${toCommerceError(err).message}`,\n checkedAt,\n };\n }\n }\n\n async stop(): Promise<void> {\n this.started = false;\n const transports = [...this.activeTransports];\n this.activeTransports.clear();\n await Promise.all(\n transports.map(async (transport) => {\n try {\n await transport.close();\n } catch {\n // best-effort cleanup — stop() must be idempotent and never throw.\n }\n }),\n );\n this.context = undefined;\n }\n\n private writeJsonRpcError(res: ServerResponse, status: number, message: string): void {\n if (res.headersSent) return;\n res.writeHead(status, { 'content-type': 'application/json' });\n res.end(JSON.stringify({ jsonrpc: '2.0', error: { code: -32000, message }, id: null }));\n }\n\n private buildServer(signal: AbortSignal): Server {\n const server = new Server(\n { name: this.serverName, version: this.serverVersion },\n { capabilities: { tools: {} } },\n );\n server.setRequestHandler(ListToolsRequestSchema, async () => ({\n tools: this.tools.map((t) => t.tool),\n }));\n server.setRequestHandler(CallToolRequestSchema, async (request) =>\n this.handleToolCall(request.params.name, request.params.arguments ?? {}, signal),\n );\n return server;\n }\n\n private async handleToolCall(\n resourceId: string,\n rawArgs: Record<string, unknown>,\n signal: AbortSignal,\n ): Promise<CallToolResult> {\n const context = this.context;\n if (!context) {\n return errorResult(new CommerceError('INTERNAL_ERROR', 'MCP adapter is not running.'));\n }\n try {\n // Defence in depth: `tools/list` only ever advertises mcp-exposed,\n // legal-name resources, but a client can still send `tools/call` for\n // any name. Gate here too (core also enforces exposedVia in the\n // pipeline) — do not rely on core alone. Message stays identical to a\n // genuinely unknown id so we never reveal that a resource exists but\n // is scoped to another protocol.\n const resource = this.toolsByResourceId.get(resourceId);\n if (!resource) {\n return errorResult(\n new CommerceError('RESOURCE_NOT_FOUND', `Unknown tool \"${resourceId}\".`, { resourceId }),\n );\n }\n const requestId = context.ids.next('mcp');\n const { input, payment, authorization } = extractReservedInputFields(\n rawArgs,\n resource,\n requestId,\n );\n const request: CanonicalRequest = {\n requestId,\n resourceId,\n input,\n protocol: 'mcp',\n receivedAt: context.clock.nowIso(),\n ...(payment !== undefined ? { payment } : {}),\n ...(authorization !== undefined ? { authorization } : {}),\n };\n await this.acquireToolCallSlot(signal);\n try {\n // the only cancellation point. A call queued\n // behind a full semaphore, whose caller has since disconnected,\n // must not start a fresh pipeline.execute() (and possibly a live\n // merchant-backend fetch) — that is the \"runs for 30s after the\n // client left\" bug. Checked here and nowhere else: once execute()\n // is called it may reach settle(), and an in-flight payment must be\n // allowed to finish rather than be abandoned mid-flight.\n if (signal.aborted) {\n // deliberately *not* GATEWAY_BUSY. That code\n // means \"transient, back off and retry\" — true for the queue-full\n // case below, false here: there is no caller left to retry, so\n // telling one to would be meaningless. PROTOCOL_UNSUPPORTED is the\n // least dishonest fit among the frozen codes (non-retryable, which\n // is the one property that matters for a response nobody reads),\n // not a precise description of \"the caller went away\" — none of\n // the frozen codes names that condition. Left flagged as a known\n // gap rather than reused past what it's honestly for.\n return errorResult(\n new CommerceError(\n 'PROTOCOL_UNSUPPORTED',\n 'Client disconnected before this call started.',\n ),\n );\n }\n const outcome = await context.pipeline.execute(request);\n return mapOutcome(outcome);\n } finally {\n // Always release, even if execute() throws — a stranded permit\n // would shrink MAX_CONCURRENT_TOOL_CALLS by one forever and\n // eventually deadlock the adapter, which is worse.\n this.releaseToolCallSlot();\n }\n } catch (err) {\n return errorResult(toCommerceError(err));\n }\n }\n\n /**\n * Blocks until fewer than MAX_CONCURRENT_TOOL_CALLS executions are in\n * flight, or throws if the queue behind that gate is already full or the\n * caller disconnected while waiting. Throwing\n * here never leaks a permit: `inFlightToolCalls` is only incremented on\n * the success path below, after every rejection point.\n */\n private async acquireToolCallSlot(signal: AbortSignal): Promise<void> {\n if (this.toolCallWaiters.length >= MAX_QUEUED_TOOL_CALLS) {\n // GATEWAY_BUSY, not PROTOCOL_UNSUPPORTED. This\n // is load shedding, which is transient by definition — the caller\n // should back off and retry, matching the message below. Before\n // GATEWAY_BUSY existed this threw PROTOCOL_UNSUPPORTED (HTTP 501,\n // `retryable: false`), so the envelope told an agent framework keyed\n // on the machine-readable flag that a momentary throttle was a\n // permanent capability gap — contradicting this exact message.\n throw new CommerceError(\n 'GATEWAY_BUSY',\n 'Too many tool calls already queued on this adapter; retry later.',\n );\n }\n // `while`, not `if`. A wake-up only means a slot\n // was *freed*, not that this waiter is now entitled to it regardless of\n // what else has happened since — re-check the same condition the loop\n // waited on rather than assume one wake-up means one free slot forever.\n // (Currently that assumption would also happen to hold, since\n // `releaseToolCallSlot` decrements before waking the next waiter and JS\n // has no thread to race it — but that is a scheduling fact about this\n // file, not something `if` states, and it is exactly the kind of thing\n // a later refactor breaks silently. `while` doesn't depend on it.)\n while (this.inFlightToolCalls >= MAX_CONCURRENT_TOOL_CALLS) {\n await new Promise<void>((resolve) => this.toolCallWaiters.push(resolve));\n if (signal.aborted) {\n // This waiter is declining the slot that was just freed for it —\n // pass it straight to the next waiter in line instead of stranding\n // everyone behind it. Without this, a disconnect partway through a\n // deep queue leaves every later waiter's promise waiting on a\n // wake-up call that only its own dedicated release() would have\n // sent — and that release never comes, because this waiter never\n // takes the slot that would have produced it.\n this.toolCallWaiters.shift()?.();\n // PROTOCOL_UNSUPPORTED, not GATEWAY_BUSY —\n // same reasoning as the other disconnect check above. Non-retryable\n // is correct here (nobody is listening to retry); \"unsupported\" is\n // not a precise name for \"the caller left\", it's just the least\n // dishonest fit among the frozen codes.\n throw new CommerceError('PROTOCOL_UNSUPPORTED', 'Client disconnected while queued.');\n }\n }\n this.inFlightToolCalls++;\n }\n\n private releaseToolCallSlot(): void {\n this.inFlightToolCalls--;\n // Wake the oldest waiter, if any; it will re-increment once it resumes.\n this.toolCallWaiters.shift()?.();\n }\n}\n\nexport function createMcpAdapter(options?: McpAdapterOptions): HttpProtocolAdapter {\n return new McpProtocolAdapter(options ?? {});\n}\n"]}
|
package/dist/mpp.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
export { a as MPPX_VERSION, b as MPP_PROFILE, c as MPP_SPEC_COMMIT, d as MPP_SPEC_DRAFTS, e as MPP_SPEC_REPOSITORY, f as MPP_SUPPORTED_SPEC } from './constants-6mypC60h.js';
|
|
2
|
+
import { A as AdapterDescriptor, L as Logger, C as Clock, e as IdGenerator, d as PaymentProvider } from './runtime-DC5XQ9Cc.js';
|
|
3
|
+
import { X as X402FacilitatorConfig } from './guardrails-Dmwi63KB.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Describes the MPP profile and its unsupported variants.
|
|
7
|
+
*
|
|
8
|
+
* The protocol name alone cannot identify a compatible intent, method and
|
|
9
|
+
* extension set, so the descriptor lists both the target and its gaps.
|
|
10
|
+
*
|
|
11
|
+
* Importing the descriptor does not load `mppx`.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
declare const MPP_DESCRIPTOR: AdapterDescriptor;
|
|
15
|
+
|
|
16
|
+
interface MppProviderOptions {
|
|
17
|
+
/** Merchant-controlled settlement destination. Never gateway-owned */
|
|
18
|
+
readonly recipient: `0x${string}`;
|
|
19
|
+
/** EIP-3009 token the charge is paid in */
|
|
20
|
+
readonly asset: `0x${string}`;
|
|
21
|
+
/** EIP-712 domain name of the asset, e.g. 'USDC' or 'MockUSDC' */
|
|
22
|
+
readonly assetName: string;
|
|
23
|
+
/** EIP-712 domain version of the asset, e.g. '2' */
|
|
24
|
+
readonly assetVersion: string;
|
|
25
|
+
/** Value of each challenge's `realm`, such as the gateway's host */
|
|
26
|
+
readonly realm: string;
|
|
27
|
+
/** Key that binds each challenge to this gateway. Never logged or published */
|
|
28
|
+
readonly challengeSecret: string;
|
|
29
|
+
/** RPC endpoint of the settlement chain */
|
|
30
|
+
readonly rpcUrl: string;
|
|
31
|
+
/** The x402 facilitator that verifies and broadcasts the authorization */
|
|
32
|
+
readonly facilitator: X402FacilitatorConfig;
|
|
33
|
+
/** Must be `true` before anything settles on a mainnet. Never a default */
|
|
34
|
+
readonly allowMainnet?: boolean;
|
|
35
|
+
/** Must be `true` to settle on a mainnet through a facilitator that takes no credential */
|
|
36
|
+
readonly allowUnauthenticatedFacilitator?: boolean;
|
|
37
|
+
readonly logger?: Logger;
|
|
38
|
+
/**
|
|
39
|
+
* Seconds a challenge stays valid, 300 by default. The mppx client signs its
|
|
40
|
+
* authorization to expire at the same moment.
|
|
41
|
+
*/
|
|
42
|
+
readonly challengeTtlSeconds?: number;
|
|
43
|
+
/** CAIP-2 network; accepts `eip155:84532` or `eip155:8453` and defaults to the former */
|
|
44
|
+
readonly network?: string;
|
|
45
|
+
readonly clock?: Clock;
|
|
46
|
+
readonly ids?: IdGenerator;
|
|
47
|
+
}
|
|
48
|
+
declare function createMppPaymentProvider(options: MppProviderOptions): PaymentProvider;
|
|
49
|
+
|
|
50
|
+
export { MPP_DESCRIPTOR, type MppProviderOptions, createMppPaymentProvider, createMppPaymentProvider as mpp };
|