UNPKG

agents

Version:

A home for your AI agents

260 lines (259 loc) 7.83 kB
import { t as bindMcpClient } from "../../invoker-CHMnoxIA.js"; import { HTTPFacilitatorClient, x402ResourceServer } from "@x402/core/server"; import { x402Client } from "@x402/core/client"; import { registerExactEvmScheme } from "@x402/evm/exact/server"; import { registerExactEvmScheme as registerExactEvmScheme$1 } from "@x402/evm/exact/client"; //#region src/mcp/client/x402.ts /** * Map of legacy v1 network names to CAIP-2 identifiers. * Allows backward compatibility with v1 config. */ const LEGACY_NETWORK_MAP = { "base-sepolia": "eip155:84532", base: "eip155:8453", ethereum: "eip155:1", sepolia: "eip155:11155111" }; /** * Normalize a network identifier to CAIP-2 format. * Accepts both legacy v1 names ("base-sepolia") and CAIP-2 ("eip155:84532"). */ function normalizeNetwork(network) { return LEGACY_NETWORK_MAP[network] ?? network; } function withX402(server, cfg) { const network = normalizeNetwork(cfg.network); const resourceServer = new x402ResourceServer(new HTTPFacilitatorClient(cfg.facilitator ?? { url: "https://x402.org/facilitator" })); registerExactEvmScheme(resourceServer); let initPromise = null; function ensureInitialized() { if (!initPromise) initPromise = resourceServer.initialize().catch((err) => { initPromise = null; throw err; }); return initPromise; } function paidTool(name, description, priceUSD, paramsSchema, annotations, cb) { return server.registerTool(name, { description, inputSchema: paramsSchema, annotations, _meta: { "agents-x402/paymentRequired": true, "agents-x402/priceUSD": priceUSD } }, (async (args, extra) => { await ensureInitialized(); const resourceConfig = { scheme: "exact", payTo: cfg.recipient, price: priceUSD, network, maxTimeoutSeconds: 300 }; let requirements; try { requirements = await resourceServer.buildPaymentRequirements(resourceConfig); } catch { const payload = { x402Version: 2, error: "PRICE_COMPUTE_FAILED" }; return { isError: true, _meta: { "x402/error": payload }, content: [{ type: "text", text: JSON.stringify(payload) }] }; } const resourceInfo = { url: `x402://${name}`, description, mimeType: "application/json" }; const headers = extra?.requestInfo?.headers ?? {}; const token = extra?._meta?.["x402/payment"] ?? headers["PAYMENT-SIGNATURE"] ?? headers["X-PAYMENT"]; const paymentRequired = (reason = "PAYMENT_REQUIRED", extraFields = {}) => { const payload = { x402Version: 2, error: reason, resource: resourceInfo, accepts: requirements, ...extraFields }; return { isError: true, _meta: { "x402/error": payload }, content: [{ type: "text", text: JSON.stringify(payload) }] }; }; if (!token || typeof token !== "string") return paymentRequired(); let paymentPayload; try { paymentPayload = JSON.parse(atob(token)); } catch { return paymentRequired("INVALID_PAYMENT"); } const matchingReq = resourceServer.findMatchingRequirements(requirements, paymentPayload); if (!matchingReq) return paymentRequired("INVALID_PAYMENT"); try { const vr = await resourceServer.verifyPayment(paymentPayload, matchingReq); if (!vr.isValid) return paymentRequired(vr.invalidReason ?? "INVALID_PAYMENT", { payer: vr.payer }); } catch { return paymentRequired("INVALID_PAYMENT"); } let result; let failed = false; try { result = await cb(args, extra); if (result && typeof result === "object" && "isError" in result && result.isError) failed = true; } catch (e) { failed = true; result = { isError: true, content: [{ type: "text", text: `Tool execution failed: ${String(e)}` }] }; } if (!failed) try { const s = await resourceServer.settlePayment(paymentPayload, matchingReq); if (s.success) { result._meta ??= {}; result._meta["x402/payment-response"] = { success: true, transaction: s.transaction, network: s.network, payer: s.payer }; } else return paymentRequired(s.errorReason ?? "SETTLEMENT_FAILED"); } catch { return paymentRequired("SETTLEMENT_FAILED"); } return result; })); } Object.defineProperty(server, "paidTool", { value: paidTool, writable: false, enumerable: false, configurable: true }); return server; } function withX402Client(client, x402Config) { const invoker = bindMcpClient(client); const { account } = x402Config; const maxPaymentValue = x402Config.maxPaymentValue ?? BigInt(1e5); const paymentClient = new x402Client(); registerExactEvmScheme$1(paymentClient, { signer: account }); if (x402Config.network) { const preferredNetwork = normalizeNetwork(x402Config.network); paymentClient.registerPolicy((_version, reqs) => { const matching = reqs.filter((r) => r.network === preferredNetwork); return matching.length > 0 ? matching : reqs; }); } const listTools = async (params, options) => { const toolsRes = await invoker.listTools(params, options); return { ...toolsRes, tools: toolsRes.tools.map((tool) => { let description = tool.description; if (tool._meta?.["agents-x402/paymentRequired"]) { const cost = tool._meta?.["agents-x402/priceUSD"] ? `$${tool._meta?.["agents-x402/priceUSD"]}` : "an unknown amount"; description += ` (This is a paid tool, you will be charged ${cost} for its execution)`; } return { ...tool, description }; }) }; }; const callToolWithPayment = async (x402ConfirmationCallback, params, schemaOrOptions, options) => { const invoke = (callParams) => invoker.callTool(callParams, schemaOrOptions, options); const res = await invoke(params); const maybeX402Error = res._meta?.["x402/error"]; if (res.isError && maybeX402Error && maybeX402Error.accepts && Array.isArray(maybeX402Error.accepts) && maybeX402Error.accepts.length > 0) { const accepts = maybeX402Error.accepts; const confirmationCallback = x402ConfirmationCallback ?? x402Config.confirmationCallback; if (confirmationCallback && !await confirmationCallback(accepts)) return { isError: true, content: [{ type: "text", text: "User declined payment" }] }; const selectedReq = accepts[0]; if (!selectedReq || selectedReq.scheme !== "exact") return res; let amount; try { amount = BigInt(selectedReq.amount); } catch { return res; } if (amount > maxPaymentValue) return { isError: true, content: [{ type: "text", text: `Payment exceeds client cap: ${amount} > ${maxPaymentValue}` }] }; const paymentRequiredResponse = { x402Version: maybeX402Error.x402Version ?? 2, resource: maybeX402Error.resource ?? { url: "", description: "", mimeType: "application/json" }, accepts, extensions: maybeX402Error.extensions }; let paymentPayload; try { paymentPayload = await paymentClient.createPaymentPayload(paymentRequiredResponse); } catch { return { isError: true, content: [{ type: "text", text: "Failed to create payment payload" }] }; } const token = btoa(JSON.stringify(paymentPayload)); return invoke({ ...params, _meta: { ...params._meta, "x402/payment": token } }); } return res; }; const _client = client; Object.defineProperty(_client, "listTools", { value: listTools, writable: false, enumerable: false, configurable: true }); Object.defineProperty(_client, "callTool", { value: callToolWithPayment, writable: false, enumerable: false, configurable: true }); return _client; } //#endregion export { normalizeNetwork, withX402, withX402Client }; //# sourceMappingURL=x402.js.map