@hpp-io/x402-mcp-bridge 0.0.1 → 0.0.2

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 (54) hide show
  1. package/README.md +54 -4
  2. package/bin/hpp-x402-channel.js +5 -0
  3. package/bin/hpp-x402-keychain.js +5 -0
  4. package/bin/hpp-x402-policy.js +5 -0
  5. package/bin/x402-mcp-bridge.js +0 -0
  6. package/dist/a2a.d.ts +70 -0
  7. package/dist/a2a.js +210 -0
  8. package/dist/a2a.js.map +1 -0
  9. package/dist/autoSettlePickup.d.ts +69 -0
  10. package/dist/autoSettlePickup.js +150 -0
  11. package/dist/autoSettlePickup.js.map +1 -0
  12. package/dist/cli/channel.d.ts +1 -0
  13. package/dist/cli/channel.js +330 -0
  14. package/dist/cli/channel.js.map +1 -0
  15. package/dist/cli/install-claude.d.ts +2 -20
  16. package/dist/cli/install-claude.js +12 -63
  17. package/dist/cli/install-claude.js.map +1 -1
  18. package/dist/cli/install-mcp-host.d.ts +35 -0
  19. package/dist/cli/install-mcp-host.js +82 -0
  20. package/dist/cli/install-mcp-host.js.map +1 -0
  21. package/dist/cli/install-openclaw.d.ts +7 -0
  22. package/dist/cli/install-openclaw.js +28 -0
  23. package/dist/cli/install-openclaw.js.map +1 -0
  24. package/dist/cli/keychain.d.ts +1 -0
  25. package/dist/cli/keychain.js +147 -0
  26. package/dist/cli/keychain.js.map +1 -0
  27. package/dist/cli/policy.d.ts +1 -0
  28. package/dist/cli/policy.js +219 -0
  29. package/dist/cli/policy.js.map +1 -0
  30. package/dist/cli/safe.d.ts +4111 -9519
  31. package/dist/cli/setup.js +23 -1
  32. package/dist/cli/setup.js.map +1 -1
  33. package/dist/client.d.ts +19 -8
  34. package/dist/client.js +118 -0
  35. package/dist/client.js.map +1 -1
  36. package/dist/config.d.ts +4 -4
  37. package/dist/config.js +11 -5
  38. package/dist/config.js.map +1 -1
  39. package/dist/httpX402.d.ts +39 -0
  40. package/dist/httpX402.js +208 -0
  41. package/dist/httpX402.js.map +1 -0
  42. package/dist/index.js +43 -14
  43. package/dist/index.js.map +1 -1
  44. package/dist/keychain.d.ts +23 -0
  45. package/dist/keychain.js +111 -0
  46. package/dist/keychain.js.map +1 -0
  47. package/dist/policy.d.ts +73 -0
  48. package/dist/policy.js +249 -0
  49. package/dist/policy.js.map +1 -0
  50. package/dist/server.d.ts +15 -1
  51. package/dist/server.js +154 -10
  52. package/dist/server.js.map +1 -1
  53. package/docs/policy.md +101 -0
  54. package/package.json +12 -5
package/README.md CHANGED
@@ -31,7 +31,7 @@ The host sees a normal MCP server and never deals with payment.
31
31
  "command": "npx",
32
32
  "args": ["-y", "@hpp-io/x402-mcp-bridge"],
33
33
  "env": {
34
- "DELEGATE_PRIVATE_KEY": "0x...",
34
+ "DELEGATE_PRIVATE_KEY": "keychain://hpp-x402/delegate-default",
35
35
  "SAFE_ADDRESS": "0x...",
36
36
  "ALLOWANCE_MODULE_ADDRESS": "0x...",
37
37
  "USDCE_ADDRESS": "0x...",
@@ -44,11 +44,23 @@ The host sees a normal MCP server and never deals with payment.
44
44
  }
45
45
  ```
46
46
 
47
+ `DELEGATE_PRIVATE_KEY` accepts either form:
48
+
49
+ - `keychain://hpp-x402/<account>` — resolved via the OS keychain
50
+ (macOS Keychain / Windows Credential Vault / Linux libsecret) at
51
+ startup. **Recommended** — no plaintext key on disk.
52
+ - `0x[64 hex]` — raw key. Fine for quickstart / development.
53
+
54
+ To populate the keychain entry, see [Keychain CLI](#keychain-cli) below.
55
+
47
56
  Same config block works for OpenClaw and any other MCP host that supports
48
57
  stdio MCP servers. See [`examples/`](./examples/) for ready-to-merge JSON
49
58
  snippets and a [local development guide](./examples/local-dev.md) for using
50
59
  the bridge before it's published to npm.
51
60
 
61
+ 📖 **First time?** Walk through [docs/SETUP.md](./docs/SETUP.md) — covers Safe
62
+ deployment, OS keychain storage, and host registration step by step.
63
+
52
64
  ## Pre-flight (one-time, on-chain)
53
65
 
54
66
  Before the bridge can do anything, you need a Safe with USDC.e and an
@@ -66,6 +78,31 @@ AllowanceModule entry that authorises a delegate EOA to pull from it:
66
78
  Verified end-to-end on HPP Sepolia 2026-05-06 — the chain enforces the
67
79
  daily cap, and `deleteAllowance` instantly blocks future top-ups.
68
80
 
81
+ ## Keychain CLI
82
+
83
+ `hpp-x402-keychain` stores the delegate private key in the OS keychain
84
+ so it never lives in `.env` / `claude_desktop_config.json` plaintext.
85
+
86
+ ```bash
87
+ # Store an existing key (prompts, no echo):
88
+ npx -y -p @hpp-io/x402-mcp-bridge hpp-x402-keychain set
89
+ # → asks for "0x..." and prints the URI + derived address
90
+
91
+ # Or generate a fresh delegate + store it in one shot:
92
+ npx -y -p @hpp-io/x402-mcp-bridge hpp-x402-keychain generate
93
+ # → prints address — fund it with HPP gas, then add as Safe delegate
94
+
95
+ # Verify what's stored (address only, never the key):
96
+ npx -y -p @hpp-io/x402-mcp-bridge hpp-x402-keychain show
97
+
98
+ # Remove:
99
+ npx -y -p @hpp-io/x402-mcp-bridge hpp-x402-keychain delete
100
+ ```
101
+
102
+ All commands accept an optional `<account>` positional (default
103
+ `delegate-default`) so you can keep separate slots for sepolia /
104
+ mainnet / project-specific delegates.
105
+
69
106
  ## Architecture
70
107
 
71
108
  See [DESIGN.md in the parent task](../noosphere-evm/.claude/tasks/x402-mcp-wallet/design/DESIGN.md).
@@ -108,11 +145,24 @@ The `prepublishOnly` script in package.json runs `typecheck && build`
108
145
  locally too, so manual `npm publish` from a developer's machine still
109
146
  guards against shipping broken builds.
110
147
 
148
+ ## Related
149
+
150
+ This bridge is the **MCP-host** integration path (Claude Desktop, OpenClaw,
151
+ Cursor, …). If you're building an **agent / SDK** integration instead —
152
+ LangChain ReAct, OpenAI function-calling, Coinbase AgentKit, A2A
153
+ seller↔buyer, etc. — see the runnable Gallery:
154
+
155
+ → [hpp-io/hpp-x402-agent-sample](https://github.com/hpp-io/hpp-x402-agent-sample)
156
+
157
+ Both paths share the same wallet/x402 layer; pick whichever surface fits
158
+ your distribution.
159
+
111
160
  ## Status
112
161
 
113
- **v0.0.1 — PoC.** Working end-to-end against HPP Sepolia (smoke proves
114
- both the "delegate has balance" and "delegate empty → autoTopup → pay"
115
- paths). Not yet published to npm; install via local path or git clone.
162
+ **v0.0.1 — published on npm** as `@hpp-io/x402-mcp-bridge`. Working
163
+ end-to-end against HPP Sepolia (smoke proves both the "delegate has
164
+ balance" and "delegate empty autoTopup pay" paths). Install with
165
+ `npx -y @hpp-io/x402-mcp-bridge` or `npm i -g @hpp-io/x402-mcp-bridge`.
116
166
 
117
167
  Roadmap:
118
168
 
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import("../dist/cli/channel.js").catch((err) => {
3
+ process.stderr.write(`hpp-x402-channel fatal: ${err?.message ?? err}\n`);
4
+ process.exit(1);
5
+ });
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import("../dist/cli/keychain.js").catch((err) => {
3
+ process.stderr.write(`hpp-x402-keychain fatal: ${err?.message ?? err}\n`);
4
+ process.exit(1);
5
+ });
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import("../dist/cli/policy.js").catch((err) => {
3
+ process.stderr.write(`hpp-x402-policy fatal: ${err?.message ?? err}\n`);
4
+ process.exit(1);
5
+ });
File without changes
package/dist/a2a.d.ts ADDED
@@ -0,0 +1,70 @@
1
+ import type { Network } from "@x402/core/types";
2
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { AutoTopup } from "./autoTopup.js";
4
+ import type { RawEoaSigner } from "./signers/raw-eoa.js";
5
+ export interface A2aPayerDeps {
6
+ signer: RawEoaSigner;
7
+ network: Network;
8
+ /** Optional: ensure the delegate holds enough USDC.e before paying. */
9
+ autoTopup?: AutoTopup;
10
+ /**
11
+ * Per-request timeout for the gate + paid `message/send` JSON-RPC calls.
12
+ * Defaults to {@link DEFAULT_A2A_RPC_TIMEOUT_MS} (60s). Override via env
13
+ * `HPP_X402_A2A_RPC_TIMEOUT_MS` at startup.
14
+ */
15
+ rpcTimeoutMs?: number;
16
+ }
17
+ /**
18
+ * Pick the single `accept` entry the bridge will actually pay against:
19
+ * scheme === "exact" AND network === `deps.network`. The server may
20
+ * advertise multiple schemes (batch-settlement first, exact second is
21
+ * the noosphere-x402-server default); the SDK's
22
+ * `createPaymentPayload(required)` would internally re-select based on
23
+ * registered schemes — but our spend-cap topup happens *before* that
24
+ * call, so they must operate on the *same* accept or `accept.amount`
25
+ * (topup) and the signed amount can diverge silently. We narrow to one
26
+ * accept here and pass it to both the topup gate AND the SDK, so the
27
+ * choice is auditable + consistent.
28
+ */
29
+ export declare function pickExactAccept(required: {
30
+ accepts?: ReadonlyArray<Record<string, unknown>>;
31
+ }, network: Network): Record<string, unknown> | null;
32
+ export declare const PAY_A2A_TOOL: {
33
+ readonly name: "pay_a2a_agent";
34
+ readonly description: string;
35
+ readonly inputSchema: {
36
+ readonly type: "object";
37
+ readonly properties: {
38
+ readonly agentUrl: {
39
+ readonly type: "string";
40
+ readonly description: "The A2A agent's JSON-RPC endpoint URL (e.g. http://host:4021/a2a)";
41
+ };
42
+ readonly skill: {
43
+ readonly type: "string";
44
+ readonly description: "The skill id to invoke. Operator-supplied — this MVP does not auto-discover the AgentCard.";
45
+ };
46
+ readonly message: {
47
+ readonly type: "string";
48
+ readonly description: "Text input / prompt for the skill";
49
+ };
50
+ };
51
+ readonly required: readonly ["agentUrl", "skill", "message"];
52
+ readonly additionalProperties: false;
53
+ };
54
+ };
55
+ /**
56
+ * Per-request timeout for A2A JSON-RPC calls. Without this the bridge's
57
+ * tool call hangs as long as the external agent does — the MCP host's
58
+ * own timeout (~5min) is the only fallback, and it surfaces a generic
59
+ * error that doesn't identify A2A as the slow leg. 60s covers any
60
+ * realistic gate / paid-message-send wallclock for synchronous A2A
61
+ * skills; long-running compute is meant to use the agent's own pending /
62
+ * polling protocol, not a single message/send.
63
+ */
64
+ export declare const DEFAULT_A2A_RPC_TIMEOUT_MS = 60000;
65
+ export interface PayA2aArgs {
66
+ agentUrl: string;
67
+ skill: string;
68
+ message: string;
69
+ }
70
+ export declare function payA2aAgent(deps: A2aPayerDeps, args: PayA2aArgs): Promise<CallToolResult>;
package/dist/a2a.js ADDED
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Agent2Agent (A2A) buyer tool for the bridge.
3
+ *
4
+ * The bridge's host (Claude Desktop / OpenClaw) speaks MCP, not A2A. This
5
+ * tool lets the host pay an *external A2A agent*: the operator passes the
6
+ * agent's `/a2a` endpoint URL + skill id (no AgentCard discovery — that
7
+ * is post-MVP, see TODO below), the bridge drives the `message/send`
8
+ * gate-then-pay flow, and signs the x402 `exact` payment with the
9
+ * bridge's existing delegate EOA — the same signer + AllowanceModule
10
+ * spend-cap that gate the MCP/HTTP path.
11
+ *
12
+ * The payment travels inside A2A message metadata (the a2a-x402 extension),
13
+ * not an HTTP header — but the signed payload is produced by the same
14
+ * @x402/core client + @x402/evm exact scheme used everywhere else.
15
+ *
16
+ * TODO (post-MVP): GET `/.well-known/agent-card.json`, validate `skill`
17
+ * against the published skill list, surface card metadata in errors.
18
+ */
19
+ import { x402Client } from "@x402/core/client";
20
+ import { ExactEvmScheme } from "@x402/evm/exact/client";
21
+ import { log } from "./log.js";
22
+ /**
23
+ * Pick the single `accept` entry the bridge will actually pay against:
24
+ * scheme === "exact" AND network === `deps.network`. The server may
25
+ * advertise multiple schemes (batch-settlement first, exact second is
26
+ * the noosphere-x402-server default); the SDK's
27
+ * `createPaymentPayload(required)` would internally re-select based on
28
+ * registered schemes — but our spend-cap topup happens *before* that
29
+ * call, so they must operate on the *same* accept or `accept.amount`
30
+ * (topup) and the signed amount can diverge silently. We narrow to one
31
+ * accept here and pass it to both the topup gate AND the SDK, so the
32
+ * choice is auditable + consistent.
33
+ */
34
+ export function pickExactAccept(required, network) {
35
+ const accepts = required.accepts ?? [];
36
+ for (const a of accepts) {
37
+ if (a.scheme === "exact" && a.network === network)
38
+ return a;
39
+ }
40
+ return null;
41
+ }
42
+ export const PAY_A2A_TOOL = {
43
+ name: "pay_a2a_agent",
44
+ description: "Pay an external Agent2Agent (A2A) agent for one of its skills using x402 " +
45
+ "(exact scheme, USDC.e) and return the result. The operator supplies the " +
46
+ "agent's A2A endpoint URL (e.g. http://host:4021/a2a) and the skill id " +
47
+ "directly — this MVP does not yet fetch the AgentCard. The bridge gates " +
48
+ "(unpaid message/send), signs the x402 payment with its delegate wallet " +
49
+ "(subject to the daily spend cap), and re-sends with the payment in A2A " +
50
+ "metadata, returning the agent's output on success.",
51
+ inputSchema: {
52
+ type: "object",
53
+ properties: {
54
+ agentUrl: {
55
+ type: "string",
56
+ description: "The A2A agent's JSON-RPC endpoint URL (e.g. http://host:4021/a2a)",
57
+ },
58
+ skill: {
59
+ type: "string",
60
+ description: "The skill id to invoke. Operator-supplied — this MVP does not auto-discover the AgentCard.",
61
+ },
62
+ message: {
63
+ type: "string",
64
+ description: "Text input / prompt for the skill",
65
+ },
66
+ },
67
+ required: ["agentUrl", "skill", "message"],
68
+ additionalProperties: false,
69
+ },
70
+ };
71
+ const REQUIRED_KEY = "x402.payment.required";
72
+ const PAYLOAD_KEY = "x402.payment.payload";
73
+ const STATUS_KEY = "x402.payment.status";
74
+ /**
75
+ * Per-request timeout for A2A JSON-RPC calls. Without this the bridge's
76
+ * tool call hangs as long as the external agent does — the MCP host's
77
+ * own timeout (~5min) is the only fallback, and it surfaces a generic
78
+ * error that doesn't identify A2A as the slow leg. 60s covers any
79
+ * realistic gate / paid-message-send wallclock for synchronous A2A
80
+ * skills; long-running compute is meant to use the agent's own pending /
81
+ * polling protocol, not a single message/send.
82
+ */
83
+ export const DEFAULT_A2A_RPC_TIMEOUT_MS = 60_000;
84
+ let rpcId = 0;
85
+ async function a2aRpc(url, method, params, timeoutMs) {
86
+ let res;
87
+ try {
88
+ res = await fetch(url, {
89
+ method: "POST",
90
+ headers: { "content-type": "application/json" },
91
+ body: JSON.stringify({ jsonrpc: "2.0", id: ++rpcId, method, params }),
92
+ signal: AbortSignal.timeout(timeoutMs),
93
+ });
94
+ }
95
+ catch (err) {
96
+ if (err instanceof DOMException && err.name === "TimeoutError") {
97
+ throw new Error(`A2A ${method} timed out after ${Math.round(timeoutMs / 1000)}s (${url})`);
98
+ }
99
+ throw err;
100
+ }
101
+ const json = (await res.json());
102
+ if (json.error) {
103
+ throw new Error(`A2A JSON-RPC error: ${JSON.stringify(json.error)}`);
104
+ }
105
+ return json.result;
106
+ }
107
+ function userMessage(text, metadata) {
108
+ return {
109
+ message: {
110
+ kind: "message",
111
+ messageId: `bridge-a2a-${++rpcId}`,
112
+ role: "user",
113
+ parts: [{ kind: "text", text }],
114
+ metadata,
115
+ },
116
+ };
117
+ }
118
+ function errorResult(text) {
119
+ return { content: [{ type: "text", text }], isError: true };
120
+ }
121
+ export async function payA2aAgent(deps, args) {
122
+ const a2aUrl = args.agentUrl.replace(/\/+$/, "");
123
+ const timeoutMs = deps.rpcTimeoutMs ?? DEFAULT_A2A_RPC_TIMEOUT_MS;
124
+ // 1. Gate: send the request unpaid → expect input-required + requirements.
125
+ let gate;
126
+ try {
127
+ gate = await a2aRpc(a2aUrl, "message/send", userMessage(args.message, { skillId: args.skill }), timeoutMs);
128
+ }
129
+ catch (err) {
130
+ return errorResult(`A2A gate request failed: ${err.message}`);
131
+ }
132
+ const state = gate?.status?.state;
133
+ // Free agent (no payment needed) — return the result as-is.
134
+ if (state === "completed") {
135
+ return { content: [{ type: "text", text: JSON.stringify(extractResult(gate)) }] };
136
+ }
137
+ if (state !== "input-required") {
138
+ return errorResult(`unexpected A2A task state "${state}" (expected input-required)`);
139
+ }
140
+ const required = gate.metadata?.[REQUIRED_KEY];
141
+ if (!required?.accepts?.length) {
142
+ return errorResult("A2A agent did not return x402 payment requirements");
143
+ }
144
+ // Narrow to the (scheme=exact, network=deps.network) entry — the SDK
145
+ // would otherwise re-pick based on registered schemes and the topup
146
+ // amount could end up funding a different `accepts[i].amount` than the
147
+ // one actually signed. See pickExactAccept docstring.
148
+ const accept = pickExactAccept(required, deps.network);
149
+ if (!accept) {
150
+ return errorResult(`A2A agent advertised no "exact" accept for network ${deps.network} ` +
151
+ `(scheme/networks: ${JSON.stringify(required.accepts.map((a) => ({ scheme: a.scheme, network: a.network })))})`);
152
+ }
153
+ // Reconstruct a single-accept PaymentRequired for the SDK so its
154
+ // internal selection cannot diverge from what we just chose.
155
+ const narrowedRequired = { ...required, accepts: [accept] };
156
+ // 2. Spend-cap: ensure the delegate holds enough USDC.e (same gate as the
157
+ // MCP/HTTP path). Skipped when no autoTopup is wired.
158
+ if (deps.autoTopup) {
159
+ try {
160
+ const requiredAtomic = BigInt(accept.amount ?? "0");
161
+ await deps.autoTopup.ensure(requiredAtomic);
162
+ }
163
+ catch (err) {
164
+ return errorResult(`autoTopup failed (spend cap?): ${err.message}`);
165
+ }
166
+ }
167
+ // 3. Sign the exact payload with the bridge's delegate EOA against
168
+ // the *narrowed* PaymentRequired (single-accept) so the SDK's
169
+ // internal scheme/network selection cannot pick a different entry.
170
+ let payload;
171
+ try {
172
+ const client = new x402Client().register(deps.network, new ExactEvmScheme(deps.signer.viemAccount));
173
+ payload = await client.createPaymentPayload(narrowedRequired);
174
+ }
175
+ catch (err) {
176
+ return errorResult(`failed to sign x402 payment: ${err.message}`);
177
+ }
178
+ // 4. Re-send with the payload in A2A metadata → expect completed.
179
+ let task;
180
+ try {
181
+ task = await a2aRpc(a2aUrl, "message/send", userMessage(args.message, { skillId: args.skill, [PAYLOAD_KEY]: payload }), timeoutMs);
182
+ }
183
+ catch (err) {
184
+ return errorResult(`A2A paid request failed: ${err.message}`);
185
+ }
186
+ const finalState = task?.status?.state;
187
+ const payStatus = task?.metadata?.[STATUS_KEY];
188
+ log.info("a2a.paid", { agent: a2aUrl, skill: args.skill, state: finalState, payment: payStatus });
189
+ if (finalState !== "completed") {
190
+ return errorResult(`A2A payment did not complete (state="${finalState}", payment="${payStatus}"): ` +
191
+ JSON.stringify(task?.status?.message ?? task?.metadata ?? {}).slice(0, 300));
192
+ }
193
+ return {
194
+ content: [{ type: "text", text: JSON.stringify({ payment: payStatus, ...extractResult(task) }) }],
195
+ };
196
+ }
197
+ function extractResult(task) {
198
+ const artifact = (task?.artifacts ?? [])[0];
199
+ const part = artifact?.parts?.[0];
200
+ if (part?.kind === "text" && typeof part.text === "string") {
201
+ try {
202
+ return JSON.parse(part.text);
203
+ }
204
+ catch {
205
+ return { output: part.text };
206
+ }
207
+ }
208
+ return { taskId: task?.id, state: task?.status?.state };
209
+ }
210
+ //# sourceMappingURL=a2a.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"a2a.js","sourceRoot":"","sources":["../src/a2a.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Auto settle pickup for the deferred-settle batch-settlement model.
3
+ *
4
+ * Replaces the F-3a auto-refund poller. The server side moved settle
5
+ * out of the inline-pending response into the result poll endpoints
6
+ * (`get_compute_result` for MCP, `GET /paid/jobs/:jobId` for HTTP); the
7
+ * buyer is therefore *not* charged until the result actually arrives.
8
+ * Refund-on-failure is no longer needed — failed compute simply never
9
+ * settles, so the channel state is unchanged.
10
+ *
11
+ * What this poller does:
12
+ *
13
+ * 1. After a paid compute call returns `status: "pending"`, start a
14
+ * background loop that calls `get_compute_result(jobId)` every
15
+ * POLL_INTERVAL_MS.
16
+ * 2. When the response includes a PAYMENT-RESPONSE under
17
+ * `_meta["x402/payment-response"]`, hand it to the batch scheme's
18
+ * `processSettleResponse` so the local `chargedCumulativeAmount`
19
+ * tracks the now-settled cumulative.
20
+ * 3. On terminal `failed`, just exit — the server discarded the
21
+ * pending voucher, so the buyer keeps their full cumulative budget.
22
+ *
23
+ * Spec refs:
24
+ * docs/design/03-BUYER-SDK-SYNC §D — autoSettlePickup contract
25
+ * docs/design/03-BUYER-SDK-SYNC §H — operational envelope (poll
26
+ * interval, max attempts)
27
+ *
28
+ * Opt-out: `HPP_X402_AUTO_POLL=false` (default = on).
29
+ *
30
+ * Exact scheme isn't covered — exact settles on the initial response,
31
+ * so there's nothing left to pick up.
32
+ */
33
+ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
34
+ import type { BatchSettlementEvmScheme } from "@x402/evm/batch-settlement/client";
35
+ import type { SettleResponse } from "@x402/core/types";
36
+ export interface AutoSettlePickupDeps {
37
+ /** Same upstream MCP client used by the bridge's callTool path. */
38
+ base: Client;
39
+ /** The batch-settlement scheme instance for the buyer's local channel. */
40
+ batchScheme: BatchSettlementEvmScheme;
41
+ }
42
+ export interface AutoSettlePickupContext {
43
+ jobId: string;
44
+ channelId: string;
45
+ /** Compute tool name — for logging only. */
46
+ toolName: string;
47
+ }
48
+ /** Returns true unless the env explicitly opts out. */
49
+ export declare function isAutoPollEnabled(): boolean;
50
+ /** Parsed payload from a compute tool's text content. */
51
+ interface ComputeResultPayload {
52
+ status?: string;
53
+ jobId?: string;
54
+ error?: string;
55
+ }
56
+ export declare function parseComputeResultText(text: string): ComputeResultPayload | null;
57
+ /**
58
+ * Pulls a `SettleResponse` out of an MCP tool result's `_meta`, if
59
+ * present. Returns `undefined` when the server didn't attach one
60
+ * (the result is still pending, or this is a non-batch path).
61
+ */
62
+ export declare function extractSettleResponse(meta: unknown): SettleResponse | undefined;
63
+ /**
64
+ * Fire-and-forget background poller. Polls until terminal then either
65
+ * applies the settle pickup or just exits on failure. Errors inside
66
+ * the poller never propagate — they're logged and the task ends.
67
+ */
68
+ export declare function startAutoSettlePoller(deps: AutoSettlePickupDeps, ctx: AutoSettlePickupContext): void;
69
+ export {};
@@ -0,0 +1,150 @@
1
+ import { log } from "./log.js";
2
+ /** Default poll interval — design/03 §H.1. */
3
+ const POLL_INTERVAL_MS = (() => {
4
+ const raw = process.env.HPP_X402_POLL_INTERVAL_MS;
5
+ const n = raw ? Number(raw) : NaN;
6
+ return Number.isFinite(n) && n >= 1000 ? n : 30_000;
7
+ })();
8
+ /**
9
+ * Default cap of 2880 = 24h at 30s, matching the server-side TTL
10
+ * (design/02 §C, design/03 §H.3). Picking the same horizon means the
11
+ * client gives up exactly when the server discards the pending voucher.
12
+ */
13
+ const POLL_MAX_ATTEMPTS = (() => {
14
+ const raw = process.env.HPP_X402_POLL_MAX_ATTEMPTS;
15
+ const n = raw ? Number(raw) : NaN;
16
+ return Number.isFinite(n) && n >= 1 ? n : 2880;
17
+ })();
18
+ /**
19
+ * MCP payment-response meta key. Matches `@x402/mcp`'s
20
+ * `MCP_PAYMENT_RESPONSE_META_KEY`; we duplicate the string literal
21
+ * instead of importing the symbol so this module stays usable from
22
+ * non-MCP callers (e.g. an A2A entry point that picks up settle from a
23
+ * different transport).
24
+ */
25
+ const MCP_PAYMENT_RESPONSE_META_KEY = "x402/payment-response";
26
+ /** Returns true unless the env explicitly opts out. */
27
+ export function isAutoPollEnabled() {
28
+ const v = process.env.HPP_X402_AUTO_POLL?.toLowerCase().trim();
29
+ return !["false", "0", "no", "off"].includes(v ?? "");
30
+ }
31
+ export function parseComputeResultText(text) {
32
+ try {
33
+ const parsed = JSON.parse(text);
34
+ if (parsed && typeof parsed === "object")
35
+ return parsed;
36
+ }
37
+ catch {
38
+ // not JSON — some compute responses are plain strings ("hello world ...")
39
+ }
40
+ return null;
41
+ }
42
+ /**
43
+ * Pulls a `SettleResponse` out of an MCP tool result's `_meta`, if
44
+ * present. Returns `undefined` when the server didn't attach one
45
+ * (the result is still pending, or this is a non-batch path).
46
+ */
47
+ export function extractSettleResponse(meta) {
48
+ if (!meta || typeof meta !== "object")
49
+ return undefined;
50
+ const candidate = meta[MCP_PAYMENT_RESPONSE_META_KEY];
51
+ if (!candidate || typeof candidate !== "object")
52
+ return undefined;
53
+ return candidate;
54
+ }
55
+ /**
56
+ * Fire-and-forget background poller. Polls until terminal then either
57
+ * applies the settle pickup or just exits on failure. Errors inside
58
+ * the poller never propagate — they're logged and the task ends.
59
+ */
60
+ export function startAutoSettlePoller(deps, ctx) {
61
+ if (!isAutoPollEnabled()) {
62
+ log.info("autoSettle.disabled_by_env", { jobId: ctx.jobId });
63
+ return;
64
+ }
65
+ log.info("autoSettle.poller.start", {
66
+ jobId: ctx.jobId,
67
+ channelId: ctx.channelId,
68
+ pollIntervalMs: POLL_INTERVAL_MS,
69
+ maxAttempts: POLL_MAX_ATTEMPTS,
70
+ });
71
+ let attempt = 0;
72
+ const tick = async () => {
73
+ attempt += 1;
74
+ try {
75
+ const res = await deps.base.callTool({
76
+ name: "get_compute_result",
77
+ arguments: { jobId: ctx.jobId },
78
+ });
79
+ const content = res.content;
80
+ const text = content?.[0]?.type === "text" ? content[0]?.text : undefined;
81
+ const parsed = text ? parseComputeResultText(text) : null;
82
+ // Settle pickup first — once the server has attached a
83
+ // PAYMENT-RESPONSE we should apply it whatever the status reads.
84
+ const settleResponse = extractSettleResponse(res._meta);
85
+ if (parsed?.status === "succeeded" || settleResponse) {
86
+ if (settleResponse) {
87
+ try {
88
+ await deps.batchScheme.processSettleResponse(settleResponse);
89
+ log.info("autoSettle.settle_applied", {
90
+ jobId: ctx.jobId,
91
+ channelId: ctx.channelId,
92
+ attempts: attempt,
93
+ tool: ctx.toolName,
94
+ tx: settleResponse.transaction,
95
+ });
96
+ }
97
+ catch (err) {
98
+ // processSettleResponse shouldn't throw in steady state,
99
+ // but if it does (corrupted channel state, etc.) we log
100
+ // and abandon — a subsequent paid call will trigger a
101
+ // corrective 402 and resync.
102
+ log.error("autoSettle.settle_apply_failed", {
103
+ jobId: ctx.jobId,
104
+ channelId: ctx.channelId,
105
+ err: err.message,
106
+ });
107
+ }
108
+ }
109
+ else {
110
+ log.info("autoSettle.succeeded_without_payment_response", {
111
+ jobId: ctx.jobId,
112
+ attempts: attempt,
113
+ note: "server didn't attach PAYMENT-RESPONSE; nothing to apply",
114
+ });
115
+ }
116
+ return;
117
+ }
118
+ if (parsed?.status === "failed") {
119
+ // Deferred-settle model: the server never charged for a job that
120
+ // failed, so there's nothing to refund. Just exit.
121
+ log.info("autoSettle.poller.terminal_failed", {
122
+ jobId: ctx.jobId,
123
+ attempts: attempt,
124
+ serverError: parsed.error,
125
+ });
126
+ return;
127
+ }
128
+ }
129
+ catch (err) {
130
+ // Polling failure isn't fatal — server might be momentarily
131
+ // unreachable. Keep trying until the attempt cap.
132
+ log.debug("autoSettle.poller.probe_failed", {
133
+ jobId: ctx.jobId,
134
+ attempt,
135
+ err: err.message,
136
+ });
137
+ }
138
+ if (attempt >= POLL_MAX_ATTEMPTS) {
139
+ log.info("autoSettle.poller.timeout", {
140
+ jobId: ctx.jobId,
141
+ attempts: attempt,
142
+ elapsedMs: POLL_INTERVAL_MS * attempt,
143
+ });
144
+ return;
145
+ }
146
+ setTimeout(tick, POLL_INTERVAL_MS).unref();
147
+ };
148
+ setTimeout(tick, POLL_INTERVAL_MS).unref();
149
+ }
150
+ //# sourceMappingURL=autoSettlePickup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoSettlePickup.js","sourceRoot":"","sources":["../src/autoSettlePickup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};