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

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 (78) hide show
  1. package/README.md +125 -77
  2. package/bin/hpp-x402.js +5 -0
  3. package/bin/x402-mcp-bridge.js +0 -0
  4. package/dist/a2a.d.ts +70 -0
  5. package/dist/a2a.js +210 -0
  6. package/dist/a2a.js.map +1 -0
  7. package/dist/autoTopup.d.ts +2 -1
  8. package/dist/autoTopup.js.map +1 -1
  9. package/dist/cli/channel.d.ts +1 -0
  10. package/dist/cli/channel.js +323 -0
  11. package/dist/cli/channel.js.map +1 -0
  12. package/dist/cli/hpp-x402.d.ts +2 -0
  13. package/dist/cli/hpp-x402.js +375 -0
  14. package/dist/cli/hpp-x402.js.map +1 -0
  15. package/dist/cli/install-claude-code.d.ts +24 -0
  16. package/dist/cli/install-claude-code.js +50 -0
  17. package/dist/cli/install-claude-code.js.map +1 -0
  18. package/dist/cli/install-claude.d.ts +2 -20
  19. package/dist/cli/install-claude.js +12 -63
  20. package/dist/cli/install-claude.js.map +1 -1
  21. package/dist/cli/install-cursor.d.ts +7 -0
  22. package/dist/cli/install-cursor.js +26 -0
  23. package/dist/cli/install-cursor.js.map +1 -0
  24. package/dist/cli/install-mcp-host.d.ts +35 -0
  25. package/dist/cli/install-mcp-host.js +82 -0
  26. package/dist/cli/install-mcp-host.js.map +1 -0
  27. package/dist/cli/install-openclaw.d.ts +7 -0
  28. package/dist/cli/install-openclaw.js +28 -0
  29. package/dist/cli/install-openclaw.js.map +1 -0
  30. package/dist/cli/install-windsurf.d.ts +7 -0
  31. package/dist/cli/install-windsurf.js +37 -0
  32. package/dist/cli/install-windsurf.js.map +1 -0
  33. package/dist/cli/policy.d.ts +1 -0
  34. package/dist/cli/policy.js +212 -0
  35. package/dist/cli/policy.js.map +1 -0
  36. package/dist/cli/revoke.d.ts +1 -1
  37. package/dist/cli/revoke.js +1 -5
  38. package/dist/cli/revoke.js.map +1 -1
  39. package/dist/cli/safe.d.ts +4172 -9580
  40. package/dist/cli/setup.d.ts +1 -1
  41. package/dist/cli/setup.js +24 -6
  42. package/dist/cli/setup.js.map +1 -1
  43. package/dist/client.d.ts +25 -10
  44. package/dist/client.js +139 -2
  45. package/dist/client.js.map +1 -1
  46. package/dist/config.d.ts +50 -11
  47. package/dist/config.js +50 -10
  48. package/dist/config.js.map +1 -1
  49. package/dist/discovery.d.ts +43 -0
  50. package/dist/discovery.js +62 -0
  51. package/dist/discovery.js.map +1 -0
  52. package/dist/discoveryTools.d.ts +75 -0
  53. package/dist/discoveryTools.js +101 -0
  54. package/dist/discoveryTools.js.map +1 -0
  55. package/dist/funds/direct-balance.d.ts +27 -0
  56. package/dist/funds/direct-balance.js +58 -0
  57. package/dist/funds/direct-balance.js.map +1 -0
  58. package/dist/funds.d.ts +26 -0
  59. package/dist/funds.js +2 -0
  60. package/dist/funds.js.map +1 -0
  61. package/dist/httpX402.d.ts +45 -0
  62. package/dist/httpX402.js +214 -0
  63. package/dist/httpX402.js.map +1 -0
  64. package/dist/index.js +66 -20
  65. package/dist/index.js.map +1 -1
  66. package/dist/keychain.d.ts +23 -0
  67. package/dist/keychain.js +111 -0
  68. package/dist/keychain.js.map +1 -0
  69. package/dist/policy.d.ts +73 -0
  70. package/dist/policy.js +249 -0
  71. package/dist/policy.js.map +1 -0
  72. package/dist/server.d.ts +18 -1
  73. package/dist/server.js +120 -10
  74. package/dist/server.js.map +1 -1
  75. package/docs/policy.md +101 -0
  76. package/package.json +11 -8
  77. package/bin/hpp-x402-safe-revoke.js +0 -5
  78. package/bin/hpp-x402-safe-setup.js +0 -5
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Client for the HPP x402-discovery REST API — a curated, facilitator-indexed
3
+ * directory of paid x402 services on the HPP chain.
4
+ *
5
+ * Read-only from the bridge's side: we query discovery to *find* services,
6
+ * then pay them directly with the bridge's own wallet. Discovery never holds
7
+ * funds or sees our keys (non-custodial).
8
+ *
9
+ * REST contract (hpp-x402-discovery/spec/openapi.yaml → routes/discovery.ts):
10
+ * GET /discovery/resources?type&network&limit&offset -> { items: [...] }
11
+ * GET /discovery/search?q&type&network&sort&limit -> { items: [...] }
12
+ * GET /discovery/resources/:id -> ResourceDetail
13
+ */
14
+ import { log } from "./log.js";
15
+ export class DiscoveryClient {
16
+ baseUrl;
17
+ timeoutMs;
18
+ constructor(baseUrl, timeoutMs = 10_000) {
19
+ this.baseUrl = baseUrl;
20
+ this.timeoutMs = timeoutMs;
21
+ }
22
+ async get(path) {
23
+ const url = this.baseUrl.replace(/\/$/, "") + path;
24
+ const ac = new AbortController();
25
+ const t = setTimeout(() => ac.abort(), this.timeoutMs);
26
+ try {
27
+ const res = await fetch(url, {
28
+ signal: ac.signal,
29
+ headers: { accept: "application/json" },
30
+ });
31
+ if (!res.ok)
32
+ throw new Error(`discovery ${res.status} for ${path}`);
33
+ return (await res.json());
34
+ }
35
+ finally {
36
+ clearTimeout(t);
37
+ }
38
+ }
39
+ /** List or semantically search the directory. */
40
+ async discover(q) {
41
+ const type = q.type ?? "all";
42
+ const limit = Math.min(Math.max(q.limit ?? 20, 1), 50);
43
+ const params = new URLSearchParams();
44
+ params.set("type", type);
45
+ if (q.network)
46
+ params.set("network", q.network);
47
+ params.set("limit", String(limit));
48
+ const query = q.query?.trim();
49
+ const path = query
50
+ ? `/discovery/search?q=${encodeURIComponent(query)}&${params.toString()}`
51
+ : `/discovery/resources?${params.toString()}`;
52
+ const out = await this.get(path);
53
+ const items = out.items ?? [];
54
+ log.debug("discovery.discover", { path, count: items.length });
55
+ return items;
56
+ }
57
+ /** Full detail for one resource (incl. metadata.schema when present). */
58
+ async detail(id) {
59
+ return this.get(`/discovery/resources/${encodeURIComponent(id)}`);
60
+ }
61
+ }
62
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAmC/B,MAAM,OAAO,eAAe;IAEP;IACA;IAFnB,YACmB,OAAe,EACf,YAAY,MAAM;QADlB,YAAO,GAAP,OAAO,CAAQ;QACf,cAAS,GAAT,SAAS,CAAS;IAClC,CAAC;IAEI,KAAK,CAAC,GAAG,CAAI,IAAY;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC;QACnD,MAAM,EAAE,GAAG,IAAI,eAAe,EAAE,CAAC;QACjC,MAAM,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAC3B,MAAM,EAAE,EAAE,CAAC,MAAM;gBACjB,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;aACxC,CAAC,CAAC;YACH,IAAI,CAAC,GAAG,CAAC,EAAE;gBAAE,MAAM,IAAI,KAAK,CAAC,aAAa,GAAG,CAAC,MAAM,QAAQ,IAAI,EAAE,CAAC,CAAC;YACpE,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAM,CAAC;QACjC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,iDAAiD;IACjD,KAAK,CAAC,QAAQ,CAAC,CAAgB;QAC7B,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC;QAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;QACrC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzB,IAAI,CAAC,CAAC,OAAO;YAAE,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAEnC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;QAC9B,MAAM,IAAI,GAAG,KAAK;YAChB,CAAC,CAAC,uBAAuB,kBAAkB,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,EAAE;YACzE,CAAC,CAAC,wBAAwB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;QAEhD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAmC,IAAI,CAAC,CAAC;QACnE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC;QAC9B,GAAG,CAAC,KAAK,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC/D,OAAO,KAAK,CAAC;IACf,CAAC;IAED,yEAAyE;IACzE,KAAK,CAAC,MAAM,CAAC,EAAU;QACrB,OAAO,IAAI,CAAC,GAAG,CACb,wBAAwB,kBAAkB,CAAC,EAAE,CAAC,EAAE,CACjD,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Discovery-backed local tools: hpp_discover + hpp_call.
3
+ *
4
+ * The multi-service UX decision (SERVICE_CONNECTION_DESIGN §멀티서비스 UX):
5
+ * instead of proxying every discovered service's tools (context explosion),
6
+ * expose two generic tools —
7
+ * - hpp_discover: list/search the curated directory (read-only, no payment)
8
+ * - hpp_call: call one discovered service by id (payment via our wallet)
9
+ *
10
+ * hpp_call routes HTTP-typed resources through the same x402 HTTP payment path
11
+ * as x402_http_call, but marks the call `trustedSource` so it skips the manual
12
+ * host allowlist — curated discovery is the trust boundary — while keeping the
13
+ * daily spend cap. MCP/A2A-typed resources return connection guidance.
14
+ */
15
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
16
+ import type { DiscoveryClient } from "./discovery.js";
17
+ import { type HttpX402Deps } from "./httpX402.js";
18
+ export declare const HPP_DISCOVER_TOOL: {
19
+ readonly name: "hpp_discover";
20
+ readonly description: string;
21
+ readonly inputSchema: {
22
+ readonly type: "object";
23
+ readonly properties: {
24
+ readonly query: {
25
+ readonly type: "string";
26
+ readonly description: "Optional free-text search over the directory.";
27
+ };
28
+ readonly type: {
29
+ readonly type: "string";
30
+ readonly enum: readonly ["http", "mcp", "a2a", "all"];
31
+ readonly description: "Filter by resource type (default all).";
32
+ };
33
+ readonly network: {
34
+ readonly type: "string";
35
+ readonly description: "Filter by CAIP-2 network, e.g. eip155:190415.";
36
+ };
37
+ readonly limit: {
38
+ readonly type: "number";
39
+ readonly description: "Max results (default 20, max 50).";
40
+ };
41
+ };
42
+ readonly additionalProperties: false;
43
+ };
44
+ };
45
+ export declare const HPP_CALL_TOOL: {
46
+ readonly name: "hpp_call";
47
+ readonly description: string;
48
+ readonly inputSchema: {
49
+ readonly type: "object";
50
+ readonly properties: {
51
+ readonly resourceId: {
52
+ readonly type: "string";
53
+ readonly description: "Service id returned by hpp_discover.";
54
+ };
55
+ readonly body: {
56
+ readonly type: "object";
57
+ readonly description: "Request body / input args for the service.";
58
+ };
59
+ };
60
+ readonly required: readonly ["resourceId"];
61
+ readonly additionalProperties: false;
62
+ };
63
+ };
64
+ export interface DiscoverArgs {
65
+ query?: string;
66
+ type?: "http" | "mcp" | "a2a" | "all";
67
+ network?: string;
68
+ limit?: number;
69
+ }
70
+ export interface HppCallArgs {
71
+ resourceId: string;
72
+ body?: unknown;
73
+ }
74
+ export declare function hppDiscover(client: DiscoveryClient, args: DiscoverArgs): Promise<CallToolResult>;
75
+ export declare function hppCall(deps: HttpX402Deps, client: DiscoveryClient, args: HppCallArgs): Promise<CallToolResult>;
@@ -0,0 +1,101 @@
1
+ import { x402HttpCall } from "./httpX402.js";
2
+ export const HPP_DISCOVER_TOOL = {
3
+ name: "hpp_discover",
4
+ description: "Discover paid x402 services on the HPP chain from the curated discovery " +
5
+ "directory. Returns services with their resourceId, description, price " +
6
+ "(USDC.e atomic units), network and type. Pass `query` for a semantic " +
7
+ "search (e.g. 'image generation'), or omit it to browse. Then invoke one " +
8
+ "with hpp_call({ resourceId, body }).",
9
+ inputSchema: {
10
+ type: "object",
11
+ properties: {
12
+ query: {
13
+ type: "string",
14
+ description: "Optional free-text search over the directory.",
15
+ },
16
+ type: {
17
+ type: "string",
18
+ enum: ["http", "mcp", "a2a", "all"],
19
+ description: "Filter by resource type (default all).",
20
+ },
21
+ network: {
22
+ type: "string",
23
+ description: "Filter by CAIP-2 network, e.g. eip155:190415.",
24
+ },
25
+ limit: { type: "number", description: "Max results (default 20, max 50)." },
26
+ },
27
+ additionalProperties: false,
28
+ },
29
+ };
30
+ export const HPP_CALL_TOOL = {
31
+ name: "hpp_call",
32
+ description: "Call a service found via hpp_discover. Pass its `resourceId` and a `body` " +
33
+ "(the service's input args). Payment (USDC.e) is handled automatically with " +
34
+ "your wallet, subject to the daily spend cap — you do not sign anything. " +
35
+ "HTTP-typed services are called directly; MCP/A2A-typed services return " +
36
+ "connection guidance.",
37
+ inputSchema: {
38
+ type: "object",
39
+ properties: {
40
+ resourceId: {
41
+ type: "string",
42
+ description: "Service id returned by hpp_discover.",
43
+ },
44
+ body: {
45
+ type: "object",
46
+ description: "Request body / input args for the service.",
47
+ },
48
+ },
49
+ required: ["resourceId"],
50
+ additionalProperties: false,
51
+ },
52
+ };
53
+ function errorResult(text) {
54
+ return { content: [{ type: "text", text }], isError: true };
55
+ }
56
+ export async function hppDiscover(client, args) {
57
+ const resources = await client.discover(args);
58
+ const services = resources.map((r) => ({
59
+ resourceId: r.id,
60
+ type: r.type,
61
+ description: r.description ?? r.toolName ?? r.resourceUrl,
62
+ priceAtomic: r.priceAtomic,
63
+ asset: r.asset,
64
+ network: r.network,
65
+ scheme: r.scheme,
66
+ ...(r.toolName ? { toolName: r.toolName } : {}),
67
+ }));
68
+ return {
69
+ content: [
70
+ { type: "text", text: JSON.stringify({ count: services.length, services }) },
71
+ ],
72
+ };
73
+ }
74
+ export async function hppCall(deps, client, args) {
75
+ if (!args.resourceId || typeof args.resourceId !== "string") {
76
+ return errorResult("resourceId required");
77
+ }
78
+ let detail;
79
+ try {
80
+ detail = await client.detail(args.resourceId);
81
+ }
82
+ catch (err) {
83
+ return errorResult(`discovery lookup failed: ${err.message}`);
84
+ }
85
+ if (detail.type !== "http") {
86
+ return errorResult(`resource "${args.resourceId}" is type "${detail.type}" — connect to it ` +
87
+ `directly at ${detail.resourceUrl}` +
88
+ (detail.type === "a2a"
89
+ ? ` (use pay_a2a_agent with its skill id).`
90
+ : ` (MCP transport).`));
91
+ }
92
+ // Curated discovery is the trust boundary → skip the manual host allowlist
93
+ // (trustedSource) but keep the spend cap. Exact-scheme only today; upto/batch
94
+ // resources surface a clear "no exact accept" error (follow-up).
95
+ return x402HttpCall({ ...deps, trustedSource: true }, {
96
+ url: detail.resourceUrl,
97
+ method: detail.httpMethod ?? "POST",
98
+ body: args.body,
99
+ });
100
+ }
101
+ //# sourceMappingURL=discoveryTools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discoveryTools.js","sourceRoot":"","sources":["../src/discoveryTools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * DirectBalance — light wallet mode (Safe-less).
3
+ *
4
+ * The delegate EOA holds USDC.e directly (funded by sending USDC.e straight to
5
+ * its address). No Safe, no AllowanceModule, no autoTopup — and because x402
6
+ * settlement is gasless (the facilitator submits EIP-3009 / sponsors the upto
7
+ * Permit2 approval), the delegate needs no native gas either. So funding the
8
+ * wallet is a single USDC.e transfer.
9
+ *
10
+ * This `Funds` impl simply reads the delegate's balance before each payment and,
11
+ * when short, throws an error whose message doubles as a funding instruction the
12
+ * MCP host surfaces to the LLM/user.
13
+ */
14
+ import { type Address, type Hex } from "viem";
15
+ import type { Funds } from "../funds.js";
16
+ export declare class DirectBalance implements Funds {
17
+ private readonly delegate;
18
+ private readonly token;
19
+ private readonly publicClient;
20
+ constructor(delegate: Address, token: Address, chainId: number, rpcUrl: string);
21
+ /**
22
+ * Light mode never performs an on-chain topup, so this either returns null
23
+ * (sufficient balance) or throws with a funding instruction. It never returns
24
+ * a tx hash.
25
+ */
26
+ ensure(requiredAtomic: bigint): Promise<Hex | null>;
27
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * DirectBalance — light wallet mode (Safe-less).
3
+ *
4
+ * The delegate EOA holds USDC.e directly (funded by sending USDC.e straight to
5
+ * its address). No Safe, no AllowanceModule, no autoTopup — and because x402
6
+ * settlement is gasless (the facilitator submits EIP-3009 / sponsors the upto
7
+ * Permit2 approval), the delegate needs no native gas either. So funding the
8
+ * wallet is a single USDC.e transfer.
9
+ *
10
+ * This `Funds` impl simply reads the delegate's balance before each payment and,
11
+ * when short, throws an error whose message doubles as a funding instruction the
12
+ * MCP host surfaces to the LLM/user.
13
+ */
14
+ import { createPublicClient, http, defineChain, } from "viem";
15
+ const ERC20_BALANCE_ABI = [
16
+ {
17
+ type: "function",
18
+ name: "balanceOf",
19
+ inputs: [{ name: "account", type: "address" }],
20
+ outputs: [{ name: "", type: "uint256" }],
21
+ stateMutability: "view",
22
+ },
23
+ ];
24
+ export class DirectBalance {
25
+ delegate;
26
+ token;
27
+ publicClient;
28
+ constructor(delegate, token, chainId, rpcUrl) {
29
+ this.delegate = delegate;
30
+ this.token = token;
31
+ const chain = defineChain({
32
+ id: chainId,
33
+ name: `chain-${chainId}`,
34
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
35
+ rpcUrls: { default: { http: [rpcUrl] } },
36
+ });
37
+ this.publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
38
+ }
39
+ /**
40
+ * Light mode never performs an on-chain topup, so this either returns null
41
+ * (sufficient balance) or throws with a funding instruction. It never returns
42
+ * a tx hash.
43
+ */
44
+ async ensure(requiredAtomic) {
45
+ const balance = (await this.publicClient.readContract({
46
+ address: this.token,
47
+ abi: ERC20_BALANCE_ABI,
48
+ functionName: "balanceOf",
49
+ args: [this.delegate],
50
+ }));
51
+ if (balance >= requiredAtomic)
52
+ return null;
53
+ throw new Error(`insufficient USDC.e: need ${requiredAtomic}, have ${balance}. ` +
54
+ `Send USDC.e to ${this.delegate} on this network to top up ` +
55
+ `(no native gas required).`);
56
+ }
57
+ }
58
+ //# sourceMappingURL=direct-balance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"direct-balance.js","sourceRoot":"","sources":["../../src/funds/direct-balance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EACL,kBAAkB,EAClB,IAAI,EACJ,WAAW,GAIZ,MAAM,MAAM,CAAC;AAId,MAAM,iBAAiB,GAAG;IACxB;QACE,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,WAAW;QACjB,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC9C,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACxC,eAAe,EAAE,MAAM;KACxB;CACO,CAAC;AAEX,MAAM,OAAO,aAAa;IAIL;IACA;IAJF,YAAY,CAAe;IAE5C,YACmB,QAAiB,EACjB,KAAc,EAC/B,OAAe,EACf,MAAc;QAHG,aAAQ,GAAR,QAAQ,CAAS;QACjB,UAAK,GAAL,KAAK,CAAS;QAI/B,MAAM,KAAK,GAAG,WAAW,CAAC;YACxB,EAAE,EAAE,OAAO;YACX,IAAI,EAAE,SAAS,OAAO,EAAE;YACxB,cAAc,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE;YAC9D,OAAO,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,MAAM,CAAC,EAAE,EAAE;SACzC,CAAC,CAAC;QACH,IAAI,CAAC,YAAY,GAAG,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,MAAM,CAAC,cAAsB;QACjC,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC;YACpD,OAAO,EAAE,IAAI,CAAC,KAAK;YACnB,GAAG,EAAE,iBAAiB;YACtB,YAAY,EAAE,WAAW;YACzB,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;SACtB,CAAC,CAAW,CAAC;QAEd,IAAI,OAAO,IAAI,cAAc;YAAE,OAAO,IAAI,CAAC;QAE3C,MAAM,IAAI,KAAK,CACb,6BAA6B,cAAc,UAAU,OAAO,IAAI;YAC9D,kBAAkB,IAAI,CAAC,QAAQ,6BAA6B;YAC5D,2BAA2B,CAC9B,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Funds — abstraction over "ensure the delegate can cover this payment".
3
+ *
4
+ * Two implementations back the two wallet modes:
5
+ * - AutoTopup (Safe mode): pulls USDC.e from the user's Safe to the delegate
6
+ * EOA via AllowanceModule.executeAllowanceTransfer, within the on-chain
7
+ * daily cap, when the delegate balance is short.
8
+ * - DirectBalance (light mode): the delegate EOA holds USDC.e directly; this
9
+ * impl only verifies the balance and surfaces a clear funding instruction
10
+ * when short — no Safe, no on-chain topup, no native gas.
11
+ *
12
+ * The payment path (client.ts onPaymentRequested) depends only on this
13
+ * interface, so the two modes share a single code path.
14
+ */
15
+ import type { Hex } from "viem";
16
+ export interface Funds {
17
+ /**
18
+ * Ensure the delegate holds at least `requiredAtomic` of the payment asset
19
+ * before the x402 payment is signed.
20
+ *
21
+ * Returns the topup tx hash when an on-chain refill was performed (Safe mode),
22
+ * or `null` when no action was needed (already sufficient). Throws a clear,
23
+ * host-surfaceable error when funds are insufficient and cannot be topped up.
24
+ */
25
+ ensure(requiredAtomic: bigint): Promise<Hex | null>;
26
+ }
package/dist/funds.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=funds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"funds.js","sourceRoot":"","sources":["../src/funds.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import type { Network } from "@x402/core/types";
2
+ import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
3
+ import type { Funds } from "./funds.js";
4
+ import type { RawEoaSigner } from "./signers/raw-eoa.js";
5
+ export interface HttpX402Deps {
6
+ signer: RawEoaSigner;
7
+ network: Network;
8
+ /** Ensure the delegate holds enough USDC.e before paying. */
9
+ funds?: Funds;
10
+ /**
11
+ * Set by hpp_call for curated-discovery resources: skip the manual host
12
+ * allowlist + local credential injection (discovery is the trust boundary).
13
+ * The spend cap (default limits, per-call amount, cooldown) still applies.
14
+ */
15
+ trustedSource?: boolean;
16
+ }
17
+ export declare const X402_HTTP_TOOL: {
18
+ readonly name: "x402_http_call";
19
+ readonly description: string;
20
+ readonly inputSchema: {
21
+ readonly type: "object";
22
+ readonly properties: {
23
+ readonly url: {
24
+ readonly type: "string";
25
+ readonly description: "Target endpoint URL (host must be allow-listed).";
26
+ };
27
+ readonly method: {
28
+ readonly type: "string";
29
+ readonly description: "HTTP method (default POST).";
30
+ };
31
+ readonly body: {
32
+ readonly type: "object";
33
+ readonly description: "JSON request body (for POST/PUT/...).";
34
+ };
35
+ };
36
+ readonly required: readonly ["url"];
37
+ readonly additionalProperties: false;
38
+ };
39
+ };
40
+ export interface X402HttpArgs {
41
+ url: string;
42
+ method?: string;
43
+ body?: unknown;
44
+ }
45
+ export declare function x402HttpCall(deps: HttpX402Deps, args: X402HttpArgs): Promise<CallToolResult>;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Generic HTTP x402 tool for the bridge.
3
+ *
4
+ * Like `pay_a2a_agent`, this is a *local* tool (not forwarded upstream):
5
+ * it lets the host call an x402-protected HTTP endpoint. The first use is
6
+ * HPP Hub credit top-up (`POST /api/web3/credit/topup`), but nothing here
7
+ * is Hub-specific — the per-host auth header + spend limits come from the
8
+ * generic policy (see ./policy.ts), so any "x402 + auth header" service
9
+ * works with one policy entry and no code change.
10
+ *
11
+ * Flow (mirrors a2a.ts: gate → spend-cap → sign → re-send):
12
+ * 1. pre-flight guard: host allowlist + https (policy.checkAccess)
13
+ * 2. inject auth headers from local policy (policy.resolveCredentials)
14
+ * 3. unpaid fetch; non-402 → passthrough (e.g. GET usage)
15
+ * 4. parse 402 → pick the (exact, ourNetwork) accept (a2a.pickExactAccept)
16
+ * 5. per-call amount cap (policy.checkAmount)
17
+ * 6. autoTopup the delegate from the Safe (reused)
18
+ * 7. sign exact payload, encode Payment-Signature, re-send
19
+ *
20
+ * Secrets (api keys) never travel through tool args — only `{url, method,
21
+ * body}` come from the host/LLM. Identity is the X-Api-Key injected locally.
22
+ */
23
+ import { x402Client, x402HTTPClient } from "@x402/core/client";
24
+ import { ExactEvmScheme } from "@x402/evm/exact/client";
25
+ import { pickExactAccept } from "./a2a.js";
26
+ import { loadPolicy, checkAccess, checkAmount, resolveCredentials, checkCooldown, recordPaid, acquireHostLock, } from "./policy.js";
27
+ import { log } from "./log.js";
28
+ export const X402_HTTP_TOOL = {
29
+ name: "x402_http_call",
30
+ description: "Call an x402-protected HTTP endpoint and return its response. Payment " +
31
+ "(USDC.e) is handled automatically with your wallet, subject to the daily " +
32
+ "spend cap; per-host auth headers come from local policy (you do NOT pass " +
33
+ "keys). Only allow-listed hosts can be called. Use for paid HTTP APIs and " +
34
+ "account actions such as Hub credit top-up " +
35
+ "(POST <hub>/api/web3/credit/topup {amount}) and usage checks " +
36
+ "(GET <hub>/api/web3/credit/usage).",
37
+ inputSchema: {
38
+ type: "object",
39
+ properties: {
40
+ url: { type: "string", description: "Target endpoint URL (host must be allow-listed)." },
41
+ method: { type: "string", description: "HTTP method (default POST)." },
42
+ body: { type: "object", description: "JSON request body (for POST/PUT/...)." },
43
+ },
44
+ required: ["url"],
45
+ additionalProperties: false,
46
+ },
47
+ };
48
+ function errorResult(text) {
49
+ return { content: [{ type: "text", text }], isError: true };
50
+ }
51
+ async function toToolResult(res) {
52
+ const text = await res.text();
53
+ let parsed = text;
54
+ try {
55
+ parsed = JSON.parse(text);
56
+ }
57
+ catch {
58
+ /* keep raw text */
59
+ }
60
+ return {
61
+ content: [
62
+ { type: "text", text: JSON.stringify({ status: res.status, ok: res.ok, body: parsed }) },
63
+ ],
64
+ isError: !res.ok,
65
+ };
66
+ }
67
+ export async function x402HttpCall(deps, args) {
68
+ const url = args.url;
69
+ if (!url || typeof url !== "string")
70
+ return errorResult("url required");
71
+ const method = (args.method ?? "POST").toUpperCase();
72
+ const policy = loadPolicy();
73
+ // 1. pre-flight guard — host allowlist + https (③ / H1·C1). Trusted
74
+ // (curated-discovery) calls skip the allowlist/https gate but still inherit
75
+ // the default spend limits carried on `access.limits`.
76
+ const access = checkAccess(policy, url);
77
+ if (!access.ok && !deps.trustedSource)
78
+ return errorResult(`blocked: ${access.error}`);
79
+ const host = new URL(url).host.toLowerCase();
80
+ // 2. inject auth headers from local policy (② — never from args/LLM). Trusted
81
+ // discovery services authenticate by payment (x402), not a local api key.
82
+ let authHeaders = {};
83
+ if (!deps.trustedSource) {
84
+ try {
85
+ authHeaders = resolveCredentials(policy, host);
86
+ }
87
+ catch (err) {
88
+ return errorResult(err.message);
89
+ }
90
+ }
91
+ const baseHeaders = { "Content-Type": "application/json", ...authHeaders };
92
+ const init = {
93
+ method,
94
+ headers: baseHeaders,
95
+ body: method === "GET" || method === "HEAD" ? undefined : JSON.stringify(args.body ?? {}),
96
+ };
97
+ // 3. unpaid request — non-402 passes through (e.g. GET /usage 200)
98
+ let res;
99
+ try {
100
+ res = await fetch(url, init);
101
+ }
102
+ catch (err) {
103
+ return errorResult(`request failed: ${err.message}`);
104
+ }
105
+ if (res.status !== 402)
106
+ return toToolResult(res);
107
+ // Paid path. Serialize per host so two near-simultaneous calls can't both
108
+ // pay (closes the cooldown's check-then-act race); combined with the
109
+ // cooldown below this dedupes agent-retry / heartbeat double-fire.
110
+ const release = acquireHostLock(host);
111
+ if (!release) {
112
+ log.info("x402_http_call.locked", { host });
113
+ return {
114
+ content: [
115
+ { type: "text", text: JSON.stringify({ inProgress: true, retry: true, message: `payment to ${host} already in progress` }) },
116
+ ],
117
+ };
118
+ }
119
+ try {
120
+ // H2 idempotency: if we paid this host within its cooldown window, return
121
+ // the previous result instead of paying again.
122
+ const cd = checkCooldown(host, access.limits.cooldownMs);
123
+ if (cd.throttled) {
124
+ let previous = cd.cachedResult;
125
+ try {
126
+ previous = JSON.parse(cd.cachedResult ?? "null");
127
+ }
128
+ catch {
129
+ /* keep raw */
130
+ }
131
+ log.info("x402_http_call.cooldown", { host, remainingMs: cd.remainingMs });
132
+ return {
133
+ content: [
134
+ { type: "text", text: JSON.stringify({ cooldown: true, retryAfterMs: cd.remainingMs, previous }) },
135
+ ],
136
+ };
137
+ }
138
+ // x402 client — also parses the 402 (v2 header / v1 body) and signs.
139
+ const client = new x402Client().register(deps.network, new ExactEvmScheme(deps.signer.viemAccount));
140
+ const httpClient = new x402HTTPClient(client);
141
+ // Parse 402 requirements. x402 v2 carries them in the PAYMENT-REQUIRED
142
+ // header (body is the v1 fallback) — getPaymentRequiredResponse handles
143
+ // those. Some servers (incl. HPP Hub) instead return v2-shaped requirements
144
+ // directly in the JSON body; fall back to that when the SDK parser rejects.
145
+ const body = (await res.json().catch(() => undefined));
146
+ let required;
147
+ try {
148
+ required = httpClient.getPaymentRequiredResponse((name) => res.headers.get(name), body);
149
+ }
150
+ catch {
151
+ if (body && Array.isArray(body.accepts)) {
152
+ required = body;
153
+ }
154
+ else {
155
+ return errorResult("no x402 payment requirements found (header or body)");
156
+ }
157
+ }
158
+ const accept = pickExactAccept(required, deps.network);
159
+ if (!accept) {
160
+ return errorResult(`no "exact" accept for network ${deps.network} ` +
161
+ `(offered: ${JSON.stringify((required.accepts ?? []).map((a) => ({ scheme: a.scheme, network: a.network })))})`);
162
+ }
163
+ const narrowedRequired = { ...required, accepts: [accept] };
164
+ const amount = BigInt(accept.amount ?? "0");
165
+ // per-call amount cap — before pulling any funds
166
+ const deny = checkAmount(access.limits, amount);
167
+ if (deny)
168
+ return errorResult(`blocked: ${deny}`);
169
+ // Ensure the delegate holds enough USDC.e (Safe autoTopup within the
170
+ // on-chain cap, or a light-mode balance check — same gate either way).
171
+ if (deps.funds) {
172
+ try {
173
+ await deps.funds.ensure(amount);
174
+ }
175
+ catch (err) {
176
+ return errorResult(`funds check failed (spend cap / insufficient balance?): ${err.message}`);
177
+ }
178
+ }
179
+ // sign exact payload + encode Payment-Signature header
180
+ let payHeaders;
181
+ try {
182
+ const payload = await httpClient.createPaymentPayload(narrowedRequired);
183
+ payHeaders = httpClient.encodePaymentSignatureHeader(payload);
184
+ }
185
+ catch (err) {
186
+ return errorResult(`failed to sign payment: ${err.message}`);
187
+ }
188
+ // re-send with payment + preserved auth headers
189
+ let paid;
190
+ try {
191
+ paid = await fetch(url, { ...init, headers: { ...baseHeaders, ...payHeaders } });
192
+ }
193
+ catch (err) {
194
+ return errorResult(`paid request failed: ${err.message}`);
195
+ }
196
+ const result = await toToolResult(paid);
197
+ // Record only successful paid calls so the cooldown gate can dedupe
198
+ // retries; a failed settle (isError) stays retryable.
199
+ if (!result.isError) {
200
+ recordPaid(host, result.content[0].text ?? "");
201
+ }
202
+ log.info("x402_http_call.done", {
203
+ host,
204
+ status: paid.status,
205
+ amountAtomic: amount.toString(),
206
+ paid: !result.isError,
207
+ });
208
+ return result;
209
+ }
210
+ finally {
211
+ release();
212
+ }
213
+ }
214
+ //# sourceMappingURL=httpX402.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"httpX402.js","sourceRoot":"","sources":["../src/httpX402.ts"],"names":[],"mappings":"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"}