@devlab.group/agent-commerce 1.6.0 → 2.0.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.
Files changed (41) hide show
  1. package/LICENSE +187 -2
  2. package/README.md +6 -6
  3. package/dist/ap2.d.ts +2 -2
  4. package/dist/ap2.js +94 -28
  5. package/dist/ap2.js.map +1 -1
  6. package/dist/{chunk-V2V2E7HX.js → chunk-3LUJHVKX.js} +4 -4
  7. package/dist/{chunk-V2V2E7HX.js.map → chunk-3LUJHVKX.js.map} +1 -1
  8. package/dist/{chunk-IVJC5YLE.js → chunk-53WXXIPR.js} +3 -3
  9. package/dist/{chunk-IVJC5YLE.js.map → chunk-53WXXIPR.js.map} +1 -1
  10. package/dist/chunk-CKJRITWY.js +113 -0
  11. package/dist/chunk-CKJRITWY.js.map +1 -0
  12. package/dist/chunk-HOZA3IWP.js +115 -0
  13. package/dist/chunk-HOZA3IWP.js.map +1 -0
  14. package/dist/{chunk-ATTWSFQP.js → chunk-RKBGCPCK.js} +78 -25
  15. package/dist/chunk-RKBGCPCK.js.map +1 -0
  16. package/dist/{chunk-RAJGPGJG.js → chunk-SYEGCNJZ.js} +3 -3
  17. package/dist/{chunk-RAJGPGJG.js.map → chunk-SYEGCNJZ.js.map} +1 -1
  18. package/dist/{chunk-74BSEXB5.js → chunk-TWRUNWDR.js} +11 -4
  19. package/dist/chunk-TWRUNWDR.js.map +1 -0
  20. package/dist/cli/index.js +143 -34
  21. package/dist/cli/index.js.map +1 -1
  22. package/dist/{constants-Bkq04FRZ.d.ts → constants-BSBRlKRR.d.ts} +2 -2
  23. package/dist/index.d.ts +42 -22
  24. package/dist/index.js +1254 -377
  25. package/dist/index.js.map +1 -1
  26. package/dist/mcp.d.ts +1 -1
  27. package/dist/mcp.js +247 -94
  28. package/dist/mcp.js.map +1 -1
  29. package/dist/mpp.d.ts +6 -2
  30. package/dist/mpp.js +65 -28
  31. package/dist/mpp.js.map +1 -1
  32. package/dist/{guardrails-71XwtXlT.d.ts → payment-flow-DCS882tR.d.ts} +9 -1
  33. package/dist/{protocol-adapter-DTkrXTev.d.ts → protocol-adapter-DonxfAwa.d.ts} +2 -0
  34. package/dist/{types-O6lg3Q5V.d.ts → types-CVw6Sf46.d.ts} +11 -0
  35. package/dist/x402.d.ts +11 -3
  36. package/dist/x402.js +4 -4
  37. package/package.json +22 -17
  38. package/dist/chunk-74BSEXB5.js.map +0 -1
  39. package/dist/chunk-AFI2CEZS.js +0 -10
  40. package/dist/chunk-AFI2CEZS.js.map +0 -1
  41. package/dist/chunk-ATTWSFQP.js.map +0 -1
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { H as HttpProtocolAdapter } from './protocol-adapter-DTkrXTev.js';
1
+ import { H as HttpProtocolAdapter } from './protocol-adapter-DonxfAwa.js';
2
2
  import 'node:http';
3
3
  import './runtime-CiYbgGpi.js';
4
4
  import './authorization-BpbWGGrf.js';
package/dist/mcp.js CHANGED
@@ -1,10 +1,9 @@
1
- import { MCP_TOOL_NAME_PATTERN } from './chunk-AFI2CEZS.js';
2
- import { PACKAGE_VERSION, toLogInfo, toCommerceError, CommerceError, extractReservedInputFields, isRecord, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-IVJC5YLE.js';
3
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
4
- import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
5
- import { ListToolsRequestSchema, CallToolRequestSchema, LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
1
+ import { MCP_TOOL_NAME_PATTERN, readCappedBody, MCP_MODERN_PROTOCOL_REVISION, x402ErrorCode, settlementFailure, settlementResponseFromDetails, x402McpPaymentSubmission, X402_MCP_PAYMENT_META_KEY, X402_MCP_PAYMENT_RESPONSE_META_KEY, settlementResponse, X402_MCP_ERROR_META_KEY } from './chunk-HOZA3IWP.js';
2
+ import { mcpPaymentRequired, MPP_MCP_CREDENTIAL_META_KEY, receiptObject, MPP_MCP_RECEIPT_META_KEY, MPP_MCP_PAYMENT_REQUIRED_META_KEY } from './chunk-CKJRITWY.js';
3
+ import { PACKAGE_VERSION, toLogInfo, toCommerceError, CommerceError, extractReservedInputFields, isRecord, PAYMENT_INPUT_FIELD, AUTHORIZATION_INPUT_FIELD, toErrorEnvelope, DELIVERY_SUMMARY_META_KEY, toDeliverySummary, toPaymentRequiredEnvelope } from './chunk-53WXXIPR.js';
4
+ import { createMcpHandler, Server, ProtocolError, ProtocolErrorCode, LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/server';
6
5
 
7
- var MCP_SUPPORTED_SPEC = LATEST_PROTOCOL_VERSION;
6
+ var MCP_SUPPORTED_SPEC = `${MCP_MODERN_PROTOCOL_REVISION}, ${LATEST_PROTOCOL_VERSION}`;
8
7
  var MCP_CAPABILITIES = ["tools/list", "tools/call"];
9
8
  var MCP_UNSUPPORTED = [
10
9
  "resources",
@@ -16,7 +15,15 @@ var MCP_UNSUPPORTED = [
16
15
  "logging",
17
16
  "notifications/tools/list_changed",
18
17
  "tasks",
19
- "dns-rebinding-protection"
18
+ "dns-rebinding-protection",
19
+ "authorization",
20
+ "sessions",
21
+ "subscriptions",
22
+ "pagination",
23
+ "HTTP+SSE transport",
24
+ // mppx reads challenges and refusals from tool-result `_meta`.
25
+ "MPP payment-required as JSON-RPC error -32042",
26
+ "MPP verification failure as JSON-RPC error -32043"
20
27
  ];
21
28
  function buildDescriptor(implementationVersion) {
22
29
  return {
@@ -30,41 +37,6 @@ function buildDescriptor(implementationVersion) {
30
37
  };
31
38
  }
32
39
 
33
- // src/protocols/mcp/result-mapping.ts
34
- function toRecord(value) {
35
- return value;
36
- }
37
- function deliveredResult(outcome) {
38
- const body = outcome.body;
39
- const text = typeof body === "string" ? body : JSON.stringify(body ?? null);
40
- return {
41
- content: [{ type: "text", text }],
42
- ...isRecord(body) ? { structuredContent: body } : {},
43
- _meta: { [DELIVERY_SUMMARY_META_KEY]: toRecord(toDeliverySummary(outcome)) }
44
- };
45
- }
46
- function paymentRequiredResult(outcome) {
47
- const envelope = toPaymentRequiredEnvelope(outcome);
48
- const p = envelope.payment;
49
- 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.`;
50
- return {
51
- isError: true,
52
- content: [{ type: "text", text }],
53
- structuredContent: toRecord(envelope)
54
- };
55
- }
56
- function errorResult(error) {
57
- const envelope = toErrorEnvelope(error);
58
- return {
59
- isError: true,
60
- content: [{ type: "text", text: `${envelope.code}: ${envelope.message}` }],
61
- structuredContent: toRecord(envelope)
62
- };
63
- }
64
- function mapOutcome(outcome) {
65
- return outcome.kind === "delivered" ? deliveredResult(outcome) : paymentRequiredResult(outcome);
66
- }
67
-
68
40
  // src/protocols/mcp/tool-mapping.ts
69
41
  function isValidToolName(id) {
70
42
  return MCP_TOOL_NAME_PATTERN.test(id);
@@ -75,18 +47,25 @@ function isPaidResource(resource) {
75
47
  function primaryPaymentMethod(resource) {
76
48
  return resource.paymentMethods[0];
77
49
  }
50
+ function proofCarriers(method) {
51
+ const field = `the "${PAYMENT_INPUT_FIELD}" argument`;
52
+ if (method === "x402") return `_meta["${X402_MCP_PAYMENT_META_KEY}"] or ${field}`;
53
+ if (method === "mpp") return `_meta["${MPP_MCP_CREDENTIAL_META_KEY}"] or ${field}`;
54
+ return field;
55
+ }
78
56
  function paymentProofNote(resource) {
79
57
  const method = primaryPaymentMethod(resource);
80
- const rail = method !== void 0 ? `a ${method}` : "a";
81
- return `Requires ${rail} payment proof in the "${PAYMENT_INPUT_FIELD}" input field (obtained from a previous payment-required response).`;
58
+ const rail = method !== void 0 ? `an ${method}` : "a";
59
+ return `Requires ${rail} payment proof in ${proofCarriers(method)}, built from the payment-required response.`;
82
60
  }
61
+ var OMIT_NOTE = "Omit it when the client sends the proof in _meta.";
83
62
  function paymentInputFieldDescription(resource) {
84
63
  const method = primaryPaymentMethod(resource);
85
64
  if (method === "x402") {
86
- return "x402 payment proof (base64 PAYMENT-SIGNATURE value) returned from a previous payment-required response.";
65
+ return `x402 payment proof (base64 PAYMENT-SIGNATURE value) for a previous payment-required response. ${OMIT_NOTE}`;
87
66
  }
88
67
  if (method === "mpp") {
89
- return 'MPP credential (the full "Authorization: Payment ..." value) for the challenge in a previous payment-required response.';
68
+ return `MPP credential (the full "Authorization: Payment ..." value) for the challenge in a previous payment-required response. ${OMIT_NOTE}`;
90
69
  }
91
70
  if (method !== void 0) {
92
71
  return `${method} payment proof (base64-encoded) returned from a previous payment-required response.`;
@@ -152,11 +131,92 @@ function buildInputSchema(resource) {
152
131
  };
153
132
  }
154
133
 
134
+ // src/protocols/mcp/result-mapping.ts
135
+ function toRecord(value) {
136
+ return value;
137
+ }
138
+ function deliveredResult(outcome) {
139
+ const body = outcome.body;
140
+ const text = typeof body === "string" ? body : JSON.stringify(body ?? null);
141
+ const payment = outcome.payment;
142
+ const receipt = payment?.provider === "mpp" ? receiptObject(payment.metadata?.["receipt"]) : void 0;
143
+ return {
144
+ content: [{ type: "text", text }],
145
+ ...isRecord(body) ? { structuredContent: body } : {},
146
+ _meta: {
147
+ [DELIVERY_SUMMARY_META_KEY]: toRecord(toDeliverySummary(outcome)),
148
+ ...payment?.provider === "x402" ? { [X402_MCP_PAYMENT_RESPONSE_META_KEY]: settlementResponse(payment) } : {},
149
+ ...receipt !== void 0 ? { [MPP_MCP_RECEIPT_META_KEY]: receipt } : {}
150
+ }
151
+ };
152
+ }
153
+ function structuredError(structured, sentence, meta) {
154
+ return {
155
+ isError: true,
156
+ content: [
157
+ { type: "text", text: JSON.stringify(structured) },
158
+ { type: "text", text: sentence }
159
+ ],
160
+ structuredContent: structured,
161
+ ...meta !== void 0 ? { _meta: meta } : {}
162
+ };
163
+ }
164
+ function withX402Challenge(envelope, challenge) {
165
+ return { ...challenge, ...envelope };
166
+ }
167
+ function paymentRequiredResult(outcome) {
168
+ const envelope = toPaymentRequiredEnvelope(outcome);
169
+ const p = envelope.payment;
170
+ const x402Required = p.provider === "x402" ? p.envelope : void 0;
171
+ const structured = x402Required !== void 0 ? withX402Challenge(toRecord(envelope), x402Required) : toRecord(envelope);
172
+ const mppRequired = p.provider === "mpp" ? mcpPaymentRequired(p.envelope) : void 0;
173
+ let meta;
174
+ if (x402Required !== void 0) meta = { [X402_MCP_ERROR_META_KEY]: x402Required };
175
+ else if (mppRequired !== void 0) meta = { [MPP_MCP_PAYMENT_REQUIRED_META_KEY]: mppRequired };
176
+ return structuredError(
177
+ structured,
178
+ `Payment required: ${p.amount} ${p.currency} to ${p.destination} for resource "${outcome.resourceId}". Retry with an ${p.provider} payment proof in ${proofCarriers(p.provider)}.`,
179
+ meta
180
+ );
181
+ }
182
+ function errorResult(error, rail) {
183
+ const envelope = toErrorEnvelope(error);
184
+ const details = error.details;
185
+ const challenge = details?.["challenge"];
186
+ const refused = error.httpStatus === 402 && isRecord(challenge);
187
+ const x402Required = rail === "x402" && refused ? { ...challenge, error: x402ErrorCode(error.code, details?.["reason"]) } : void 0;
188
+ const structured = x402Required !== void 0 ? withX402Challenge(toRecord(envelope), x402Required) : toRecord(envelope);
189
+ let meta;
190
+ if (rail === "x402") {
191
+ const settlement = error.code === "PAYMENT_SETTLEMENT_FAILED" ? settlementFailure(details) : settlementResponseFromDetails(details);
192
+ if (settlement !== void 0 || x402Required !== void 0) {
193
+ meta = {
194
+ ...x402Required !== void 0 ? { [X402_MCP_ERROR_META_KEY]: x402Required } : {},
195
+ ...settlement !== void 0 ? { [X402_MCP_PAYMENT_RESPONSE_META_KEY]: settlement } : {}
196
+ };
197
+ }
198
+ } else if (rail === "mpp" && refused) {
199
+ const required = mcpPaymentRequired(challenge, {
200
+ code: error.code,
201
+ reason: details?.["reason"],
202
+ detail: error.message
203
+ });
204
+ if (required !== void 0) meta = { [MPP_MCP_PAYMENT_REQUIRED_META_KEY]: required };
205
+ }
206
+ return structuredError(structured, `${envelope.code}: ${envelope.message}`, meta);
207
+ }
208
+ function mapOutcome(outcome) {
209
+ return outcome.kind === "delivered" ? deliveredResult(outcome) : paymentRequiredResult(outcome);
210
+ }
211
+
155
212
  // src/protocols/mcp/adapter.ts
156
213
  var DEFAULT_MOUNT_PATH = "/mcp";
157
214
  var DEFAULT_SERVER_NAME = "agent-commerce";
158
215
  var MAX_CONCURRENT_TOOL_CALLS = 8;
216
+ var MAX_REQUEST_BODY_BYTES = 256 * 1024;
159
217
  var MAX_QUEUED_TOOL_CALLS = 64;
218
+ var MCP_BATCH_PROTOCOL_REVISION = "2025-03-26";
219
+ var TOOLS_LIST_CACHE_HINT = { ttlMs: 6e4, cacheScope: "public" };
160
220
  var McpProtocolAdapter = class {
161
221
  name = "mcp";
162
222
  mountPath;
@@ -168,7 +228,7 @@ var McpProtocolAdapter = class {
168
228
  tools = [];
169
229
  toolsByResourceId = /* @__PURE__ */ new Map();
170
230
  skipped = [];
171
- activeTransports = /* @__PURE__ */ new Set();
231
+ handler;
172
232
  // Counting semaphore on `pipeline.execute()`. It lives on the adapter, not
173
233
  // the request, so the cap holds across concurrent `/mcp` requests as well
174
234
  // as within one batch.
@@ -232,6 +292,14 @@ var McpProtocolAdapter = class {
232
292
  this.tools = tools;
233
293
  this.toolsByResourceId = toolsByResourceId;
234
294
  this.skipped = skipped;
295
+ this.handler = createMcpHandler(
296
+ (ctx) => this.buildServer(ctx.requestInfo?.signal ?? new AbortController().signal),
297
+ {
298
+ legacy: "stateless",
299
+ // Reporting only: a request the SDK rejects is already answered
300
+ onerror: (err) => context.logger.debug({ adapter: "mcp", err: toLogInfo(err) }, "mcp adapter: SDK error")
301
+ }
302
+ );
235
303
  this.started = true;
236
304
  context.logger.info(
237
305
  {
@@ -245,7 +313,7 @@ var McpProtocolAdapter = class {
245
313
  }
246
314
  async handleHttp(req, res) {
247
315
  try {
248
- if (!this.started || !this.context) {
316
+ if (!this.started || !this.context || !this.handler) {
249
317
  this.writeJsonRpcError(res, 503, "MCP adapter is not running.");
250
318
  return;
251
319
  }
@@ -254,20 +322,39 @@ var McpProtocolAdapter = class {
254
322
  return;
255
323
  }
256
324
  const abortController = new AbortController();
257
- const server = this.buildServer(abortController.signal);
258
- const transport = new StreamableHTTPServerTransport();
259
- this.activeTransports.add(transport);
260
- const cleanup = () => {
261
- abortController.abort();
262
- this.activeTransports.delete(transport);
263
- transport.close().catch(() => {
264
- });
265
- server.close().catch(() => {
266
- });
267
- };
268
- res.once("close", cleanup);
269
- await server.connect(transport);
270
- await transport.handleRequest(req, res);
325
+ res.once("close", () => abortController.abort());
326
+ const read = await readCappedBody(req, MAX_REQUEST_BODY_BYTES);
327
+ if (read.kind === "too-large") {
328
+ this.writeJsonRpcError(
329
+ res,
330
+ 413,
331
+ `Request body exceeds the ${MAX_REQUEST_BODY_BYTES}-byte limit.`
332
+ );
333
+ return;
334
+ }
335
+ if (read.kind !== "ok") {
336
+ this.writeJsonRpcError(res, 400, "Could not read the request body.");
337
+ return;
338
+ }
339
+ const body = parseJson(read.text);
340
+ const version = req.headers["mcp-protocol-version"];
341
+ if (Array.isArray(body) && version !== void 0 && version !== MCP_BATCH_PROTOCOL_REVISION) {
342
+ this.writeJsonRpcError(
343
+ res,
344
+ 400,
345
+ `Invalid Request: JSON-RPC batches are supported only in MCP ${MCP_BATCH_PROTOCOL_REVISION}.`
346
+ );
347
+ return;
348
+ }
349
+ const malformed = isModernRequest(req) ? void 0 : malformedToolCall(body);
350
+ if (malformed !== void 0) {
351
+ this.writeJsonRpcError(res, 200, malformed.message, -32602, malformed.id);
352
+ return;
353
+ }
354
+ const response = await this.handler.fetch(
355
+ toWebRequest(req, read.text, abortController.signal)
356
+ );
357
+ await writeWebResponse(response, res);
271
358
  } catch (err) {
272
359
  this.context?.logger.error(
273
360
  { adapter: "mcp", err: toLogInfo(err) },
@@ -290,55 +377,60 @@ var McpProtocolAdapter = class {
290
377
  }
291
378
  async stop() {
292
379
  this.started = false;
293
- const transports = [...this.activeTransports];
294
- this.activeTransports.clear();
295
- await Promise.all(
296
- transports.map(async (transport) => {
297
- try {
298
- await transport.close();
299
- } catch {
300
- }
301
- })
302
- );
380
+ const handler = this.handler;
381
+ this.handler = void 0;
382
+ try {
383
+ await handler?.close();
384
+ } catch {
385
+ }
303
386
  this.context = void 0;
304
387
  }
305
- writeJsonRpcError(res, status, message) {
388
+ // Use general JSON-RPC codes for transport errors
389
+ writeJsonRpcError(res, status, message, code = status >= 500 ? -32603 : -32600, id = null) {
306
390
  if (res.headersSent) return;
307
- res.writeHead(status, { "content-type": "application/json" });
308
- res.end(JSON.stringify({ jsonrpc: "2.0", error: { code: -32e3, message }, id: null }));
391
+ res.writeHead(status, {
392
+ "content-type": "application/json",
393
+ // RFC 9110 requires Allow on a 405, and this endpoint takes only POST
394
+ ...status === 405 ? { allow: "POST" } : {}
395
+ });
396
+ res.end(JSON.stringify({ jsonrpc: "2.0", error: { code, message }, id }));
309
397
  }
310
398
  buildServer(signal) {
311
399
  const server = new Server(
312
400
  { name: this.serverName, version: this.serverVersion },
313
- { capabilities: { tools: {} } }
401
+ { capabilities: { tools: {} }, cacheHints: { "tools/list": TOOLS_LIST_CACHE_HINT } }
314
402
  );
315
- server.setRequestHandler(ListToolsRequestSchema, async () => ({
316
- tools: this.tools.map((t) => t.tool)
317
- }));
403
+ server.setRequestHandler("tools/list", async (request) => {
404
+ if (request.params?.cursor !== void 0) {
405
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, "Invalid cursor.");
406
+ }
407
+ return { tools: this.tools.map((t) => t.tool) };
408
+ });
318
409
  server.setRequestHandler(
319
- CallToolRequestSchema,
320
- async (request) => this.handleToolCall(request.params.name, request.params.arguments ?? {}, signal)
410
+ "tools/call",
411
+ async (request) => this.handleToolCall(
412
+ request.params.name,
413
+ request.params.arguments ?? {},
414
+ request.params._meta,
415
+ signal
416
+ )
321
417
  );
322
418
  return server;
323
419
  }
324
- async handleToolCall(resourceId, rawArgs, signal) {
420
+ async handleToolCall(resourceId, rawArgs, meta, signal) {
325
421
  const context = this.context;
326
422
  if (!context) {
327
423
  return errorResult(new CommerceError("INTERNAL_ERROR", "MCP adapter is not running."));
328
424
  }
425
+ const resource = this.toolsByResourceId.get(resourceId);
426
+ if (!resource) {
427
+ throw new ProtocolError(ProtocolErrorCode.InvalidParams, `Unknown tool "${resourceId}".`);
428
+ }
329
429
  try {
330
- const resource = this.toolsByResourceId.get(resourceId);
331
- if (!resource) {
332
- return errorResult(
333
- new CommerceError("RESOURCE_NOT_FOUND", `Unknown tool "${resourceId}".`, { resourceId })
334
- );
335
- }
336
430
  const requestId = context.ids.next("mcp");
337
- const { input, payment, authorization } = extractReservedInputFields(
338
- rawArgs,
339
- resource,
340
- requestId
341
- );
431
+ const fields = extractReservedInputFields(rawArgs, resource, requestId);
432
+ const { input, authorization } = fields;
433
+ const payment = paymentFromMeta(meta, resource) ?? fields.payment;
342
434
  const request = {
343
435
  requestId,
344
436
  resourceId,
@@ -369,7 +461,7 @@ var McpProtocolAdapter = class {
369
461
  { adapter: "mcp", resourceId, err: toLogInfo(error) },
370
462
  "mcp adapter: execution failed"
371
463
  );
372
- return errorResult(error);
464
+ return errorResult(error, resource.paymentMethods[0]);
373
465
  }
374
466
  }
375
467
  /**
@@ -400,6 +492,67 @@ var McpProtocolAdapter = class {
400
492
  else this.inFlightToolCalls--;
401
493
  }
402
494
  };
495
+ function toWebRequest(req, body, signal) {
496
+ const headers = new Headers();
497
+ for (const [name, value] of Object.entries(req.headers)) {
498
+ if (value !== void 0) headers.set(name, Array.isArray(value) ? value.join(", ") : value);
499
+ }
500
+ return new Request(new URL(req.url ?? "/", "http://localhost"), {
501
+ method: req.method ?? "POST",
502
+ headers,
503
+ body,
504
+ signal
505
+ });
506
+ }
507
+ function isModernRequest(req) {
508
+ if (req.headers["mcp-method"] !== void 0) return true;
509
+ const version = req.headers["mcp-protocol-version"];
510
+ return typeof version === "string" && version >= MCP_MODERN_PROTOCOL_REVISION;
511
+ }
512
+ function parseJson(body) {
513
+ try {
514
+ return JSON.parse(body);
515
+ } catch {
516
+ return void 0;
517
+ }
518
+ }
519
+ function malformedToolCall(message) {
520
+ if (!isRecord(message) || message["method"] !== "tools/call") return void 0;
521
+ const id = message["id"];
522
+ if (typeof id !== "string" && typeof id !== "number") return void 0;
523
+ const params = message["params"];
524
+ let problem;
525
+ if (!isRecord(params)) problem = "params must be an object";
526
+ else if (typeof params["name"] !== "string") problem = '"name" must be a string';
527
+ else if (params["arguments"] !== void 0 && !isRecord(params["arguments"])) {
528
+ problem = '"arguments" must be an object';
529
+ } else if (params["_meta"] !== void 0 && !isRecord(params["_meta"])) {
530
+ problem = '"_meta" must be an object';
531
+ }
532
+ return problem === void 0 ? void 0 : { id, message: `Invalid tools/call params: ${problem}.` };
533
+ }
534
+ async function writeWebResponse(response, res) {
535
+ res.writeHead(response.status, Object.fromEntries(response.headers));
536
+ if (response.body !== null) {
537
+ for await (const chunk of response.body) {
538
+ if (res.destroyed) break;
539
+ res.write(chunk);
540
+ }
541
+ }
542
+ res.end();
543
+ }
544
+ function paymentFromMeta(meta, resource) {
545
+ const method = resource.paymentMethods[0];
546
+ if (method === "x402") {
547
+ const payload = x402McpPaymentSubmission(meta?.[X402_MCP_PAYMENT_META_KEY]);
548
+ if (payload !== void 0) return { method, payload };
549
+ }
550
+ const credential = meta?.[MPP_MCP_CREDENTIAL_META_KEY];
551
+ if (method === "mpp" && isRecord(credential)) {
552
+ return { method, payload: JSON.stringify(credential) };
553
+ }
554
+ return void 0;
555
+ }
403
556
  function createMcpAdapter(options) {
404
557
  return new McpProtocolAdapter(options);
405
558
  }