@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
@@ -0,0 +1,330 @@
1
+ /**
2
+ * hpp-x402-channel — inspect / manage local batch-settlement channels.
3
+ *
4
+ * Subcommands:
5
+ *
6
+ * ls List all channels persisted under HPP_X402_HOME.
7
+ * status <channelId> Print full local channel context.
8
+ * refund <url> [amount] Cooperative refund — server co-signs, single
9
+ * multicall(claim + refund) onchain. Immediate.
10
+ * Omit `amount` for a full refund.
11
+ * withdraw <url> [--finalize] Unilateral withdraw — server-free escape hatch.
12
+ * Without --finalize: initiateWithdraw onchain.
13
+ * With --finalize: finalizeWithdraw after
14
+ * the channel's withdrawDelay elapsed.
15
+ *
16
+ * Storage layout matches `FileClientChannelStorage`:
17
+ * {HPP_X402_HOME or ~/.hpp-x402}/client/<channelId>.json
18
+ *
19
+ * Env required for mutating commands (refund, withdraw):
20
+ * AGENT_PRIVATE_KEY payer wallet (0x + 64 hex)
21
+ * HPP_RPC_URL e.g. https://sepolia.hpp.io/<key>
22
+ * HPP_NETWORK CAIP-2 (e.g. eip155:181228)
23
+ * PAYER_SALT optional — bytes32 hex used to derive channelId.
24
+ * Must match the salt the channel was opened with.
25
+ * Defaults to 0x00…0 (SDK default).
26
+ *
27
+ * Usage:
28
+ * hpp-x402-channel ls
29
+ * hpp-x402-channel status 0xe3fd…
30
+ * hpp-x402-channel refund http://localhost:4021/paid/compute/hello-world
31
+ * hpp-x402-channel refund http://localhost:4021/paid/compute/hello-world 5000
32
+ * hpp-x402-channel withdraw http://localhost:4021/paid/compute/hello-world
33
+ * hpp-x402-channel withdraw http://localhost:4021/paid/compute/hello-world --finalize
34
+ */
35
+ import { homedir } from "node:os";
36
+ import { resolve, join } from "node:path";
37
+ import { readdir } from "node:fs/promises";
38
+ import { FileClientChannelStorage } from "@x402/evm/batch-settlement/client/file-storage";
39
+ import { BatchSettlementEvmScheme } from "@x402/evm/batch-settlement/client";
40
+ import { toClientEvmSigner } from "@x402/evm";
41
+ import { decodePaymentRequiredHeader } from "@x402/core/http";
42
+ import { createPublicClient, createWalletClient, defineChain, http, parseAbi, } from "viem";
43
+ import { privateKeyToAccount } from "viem/accounts";
44
+ const STORAGE_ROOT = process.env.HPP_X402_HOME ?? resolve(homedir(), ".hpp-x402");
45
+ const X402_BATCH_SETTLEMENT = "0x4020074e9dF2ce1deE5A9C1b5c3f541D02a10003";
46
+ const CONTRACT_ABI = parseAbi([
47
+ "function channels(bytes32 channelId) view returns (uint128 balance, uint128 totalClaimed)",
48
+ "function pendingWithdrawals(bytes32 channelId) view returns (uint128 amount, uint40 initiatedAt)",
49
+ "function getChannelId((address payer, address payerAuthorizer, address receiver, address receiverAuthorizer, address token, uint40 withdrawDelay, bytes32 salt) config) view returns (bytes32)",
50
+ "function initiateWithdraw((address payer, address payerAuthorizer, address receiver, address receiverAuthorizer, address token, uint40 withdrawDelay, bytes32 salt) config, uint128 amount)",
51
+ "function finalizeWithdraw((address payer, address payerAuthorizer, address receiver, address receiverAuthorizer, address token, uint40 withdrawDelay, bytes32 salt) config)",
52
+ ]);
53
+ function usage() {
54
+ console.error("Usage: hpp-x402-channel <ls|status|refund|withdraw> [args]");
55
+ console.error(" ls List local channels");
56
+ console.error(" status <channelId> Show channel detail");
57
+ console.error(" refund <url> [amount] Cooperative refund (server co-signs)");
58
+ console.error(" withdraw <url> [--finalize] Unilateral withdraw (server-free)");
59
+ process.exit(1);
60
+ }
61
+ function reqEnv(name) {
62
+ const v = process.env[name];
63
+ if (!v || v.length === 0) {
64
+ console.error(`Missing env: ${name}`);
65
+ process.exit(2);
66
+ }
67
+ return v;
68
+ }
69
+ function loadSignerCtx() {
70
+ const key = reqEnv("AGENT_PRIVATE_KEY");
71
+ if (!/^0x[0-9a-fA-F]{64}$/.test(key)) {
72
+ console.error("AGENT_PRIVATE_KEY must be 0x + 64 hex chars");
73
+ process.exit(2);
74
+ }
75
+ const rpcUrl = reqEnv("HPP_RPC_URL");
76
+ const network = reqEnv("HPP_NETWORK");
77
+ if (!/^eip155:\d+$/.test(network)) {
78
+ console.error('HPP_NETWORK must match "eip155:<chainId>"');
79
+ process.exit(2);
80
+ }
81
+ const saltRaw = process.env.PAYER_SALT ?? `0x${"0".repeat(64)}`;
82
+ if (!/^0x[0-9a-fA-F]{64}$/.test(saltRaw)) {
83
+ console.error("PAYER_SALT must be 0x + 64 hex chars");
84
+ process.exit(2);
85
+ }
86
+ const salt = saltRaw;
87
+ const chainId = Number(network.split(":")[1]);
88
+ const account = privateKeyToAccount(key);
89
+ const chain = defineChain({
90
+ id: chainId,
91
+ name: `hpp-${chainId}`,
92
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
93
+ rpcUrls: { default: { http: [rpcUrl] } },
94
+ });
95
+ const publicClient = createPublicClient({ chain, transport: http(rpcUrl) });
96
+ return { account, network, chainId, rpcUrl, salt, publicClient };
97
+ }
98
+ async function probeRequirements(url) {
99
+ const r = await fetch(url, { method: "GET" });
100
+ if (r.status !== 402) {
101
+ throw new Error(`probe expected 402, got ${r.status} (server may not advertise this URL)`);
102
+ }
103
+ const header = r.headers.get("PAYMENT-REQUIRED");
104
+ if (!header)
105
+ throw new Error("probe response missing PAYMENT-REQUIRED header");
106
+ const paymentRequired = decodePaymentRequiredHeader(header);
107
+ const requirements = paymentRequired.accepts.find((a) => a.scheme === "batch-settlement");
108
+ if (!requirements)
109
+ throw new Error("server does not advertise batch-settlement on this URL");
110
+ return requirements;
111
+ }
112
+ async function listChannelIds() {
113
+ const clientDir = join(STORAGE_ROOT, "client");
114
+ try {
115
+ const files = await readdir(clientDir);
116
+ return files
117
+ .filter((f) => f.endsWith(".json"))
118
+ .map((f) => f.replace(/\.json$/, ""))
119
+ .sort();
120
+ }
121
+ catch (err) {
122
+ if (err.code === "ENOENT") {
123
+ return [];
124
+ }
125
+ throw err;
126
+ }
127
+ }
128
+ async function cmdLs() {
129
+ const storage = new FileClientChannelStorage({ directory: STORAGE_ROOT });
130
+ const ids = await listChannelIds();
131
+ if (ids.length === 0) {
132
+ console.log(`(no channels under ${STORAGE_ROOT}/client/)`);
133
+ return;
134
+ }
135
+ console.log(`channels in ${STORAGE_ROOT}/client/:\n`);
136
+ for (const id of ids) {
137
+ const ctx = await storage.get(id);
138
+ if (!ctx)
139
+ continue;
140
+ const ch = ctx.channel;
141
+ if (!ch) {
142
+ console.log(` ${id} (no channel record)`);
143
+ continue;
144
+ }
145
+ const balance = String(ch.balance ?? "0");
146
+ const totalClaimed = String(ch.totalClaimed ?? "0");
147
+ const charged = String(ch.chargedCumulativeAmount ?? "0");
148
+ console.log(` ${id}\n` +
149
+ ` balance: ${balance} totalClaimed: ${totalClaimed} chargedCumulative: ${charged}`);
150
+ }
151
+ }
152
+ async function cmdStatus(channelId) {
153
+ if (!/^0x[0-9a-fA-F]{64}$/.test(channelId)) {
154
+ console.error("channelId must be 0x + 64 hex chars");
155
+ process.exit(2);
156
+ }
157
+ const storage = new FileClientChannelStorage({ directory: STORAGE_ROOT });
158
+ const ctx = await storage.get(channelId.toLowerCase());
159
+ if (!ctx) {
160
+ console.error(`channel ${channelId} not found under ${STORAGE_ROOT}/client/`);
161
+ process.exit(3);
162
+ }
163
+ console.log(JSON.stringify(ctx, null, 2));
164
+ }
165
+ async function cmdRefund(url, amountArg) {
166
+ if (amountArg !== undefined && !/^\d+$/.test(amountArg)) {
167
+ console.error("amount must be a positive integer (atomic token units)");
168
+ process.exit(2);
169
+ }
170
+ const { account, salt, publicClient } = loadSignerCtx();
171
+ const signer = toClientEvmSigner(account, publicClient);
172
+ // Persistent client storage so this CLI can recover a channel created
173
+ // by another bridge process (Claude Desktop / OpenClaw stdio).
174
+ const storage = new FileClientChannelStorage({ directory: STORAGE_ROOT });
175
+ const scheme = new BatchSettlementEvmScheme(signer, { salt, storage });
176
+ console.log(`refunding channel for ${url}${amountArg ? ` (amount=${amountArg})` : " (full drain)"}…`);
177
+ const settle = await scheme.refund(url, amountArg !== undefined ? { amount: amountArg } : undefined);
178
+ if (!settle.success) {
179
+ console.error(`refund failed: ${settle.errorReason ?? "unknown"} ${settle.errorMessage ?? ""}`);
180
+ process.exit(4);
181
+ }
182
+ console.log(`refund tx: ${settle.transaction}`);
183
+ const extra = settle.extra
184
+ ?.channelState;
185
+ if (extra) {
186
+ console.log("post-refund channel state:");
187
+ console.log(JSON.stringify(extra, null, 2));
188
+ }
189
+ }
190
+ async function cmdWithdraw(url, finalize) {
191
+ const { account, publicClient, chainId, rpcUrl, salt } = loadSignerCtx();
192
+ const signer = toClientEvmSigner(account, publicClient);
193
+ const storage = new FileClientChannelStorage({ directory: STORAGE_ROOT });
194
+ const scheme = new BatchSettlementEvmScheme(signer, { salt, storage });
195
+ const requirements = await probeRequirements(url);
196
+ const channelConfig = scheme.buildChannelConfig(requirements);
197
+ // viem walletClient for the direct onchain writes (initiate / finalize).
198
+ const chain = defineChain({
199
+ id: chainId,
200
+ name: `hpp-${chainId}`,
201
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
202
+ rpcUrls: { default: { http: [rpcUrl] } },
203
+ });
204
+ const walletClient = createWalletClient({
205
+ chain,
206
+ transport: http(rpcUrl),
207
+ account: account,
208
+ });
209
+ if (!finalize) {
210
+ // initiateWithdraw — amount = onchain balance - charged. Conservative,
211
+ // safe against server claiming up to charged during the delay window.
212
+ // Derive channelId via the contract's view (avoid depending on SDK
213
+ // internal `computeChannelId` whose export path is unstable).
214
+ const channelId = (await publicClient.readContract({
215
+ address: X402_BATCH_SETTLEMENT,
216
+ abi: CONTRACT_ABI,
217
+ functionName: "getChannelId",
218
+ args: [channelConfig],
219
+ }));
220
+ const [balance, _totalClaimed] = (await publicClient.readContract({
221
+ address: X402_BATCH_SETTLEMENT,
222
+ abi: CONTRACT_ABI,
223
+ functionName: "channels",
224
+ args: [channelId],
225
+ }));
226
+ // Read local charged-cumulative from storage.
227
+ const local = await storage.get(channelId.toLowerCase());
228
+ const charged = BigInt(local?.chargedCumulativeAmount ?? "0");
229
+ const withdrawAmount = balance - charged;
230
+ if (withdrawAmount <= 0n) {
231
+ console.error(`nothing to withdraw — balance(${balance}) <= chargedCumulative(${charged})`);
232
+ process.exit(5);
233
+ }
234
+ console.log(`initiateWithdraw amount=${withdrawAmount} (balance ${balance} - charged ${charged})`);
235
+ const txHash = await walletClient.writeContract({
236
+ account: account,
237
+ chain,
238
+ address: X402_BATCH_SETTLEMENT,
239
+ abi: CONTRACT_ABI,
240
+ functionName: "initiateWithdraw",
241
+ args: [channelConfig, withdrawAmount],
242
+ });
243
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
244
+ if (receipt.status !== "success") {
245
+ console.error(`initiateWithdraw tx reverted: ${txHash}`);
246
+ process.exit(6);
247
+ }
248
+ console.log(`initiate tx: ${txHash}`);
249
+ const [pendAmount, pendInitAt] = (await publicClient.readContract({
250
+ address: X402_BATCH_SETTLEMENT,
251
+ abi: CONTRACT_ABI,
252
+ functionName: "pendingWithdrawals",
253
+ args: [channelId],
254
+ }));
255
+ const block = await publicClient.getBlock();
256
+ const readyAt = pendInitAt + channelConfig.withdrawDelay;
257
+ const eta = readyAt - Number(block.timestamp);
258
+ console.log(`pendingWithdrawals: amount=${pendAmount} initiatedAt=${pendInitAt}`);
259
+ console.log(`finalize available in ~${eta}s (at block.timestamp >= ${readyAt}). Re-run with --finalize.`);
260
+ return;
261
+ }
262
+ // finalize ----------------------------------------------------------------
263
+ console.log("finalizeWithdraw…");
264
+ const txHash = await walletClient.writeContract({
265
+ account: account,
266
+ chain,
267
+ address: X402_BATCH_SETTLEMENT,
268
+ abi: CONTRACT_ABI,
269
+ functionName: "finalizeWithdraw",
270
+ args: [channelConfig],
271
+ });
272
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
273
+ if (receipt.status !== "success") {
274
+ console.error(`finalizeWithdraw tx reverted: ${txHash} (delay not yet elapsed, or amount overshot)`);
275
+ process.exit(6);
276
+ }
277
+ console.log(`finalize tx: ${txHash}`);
278
+ }
279
+ async function main() {
280
+ const args = process.argv.slice(2);
281
+ const subcmd = args[0];
282
+ switch (subcmd) {
283
+ case "ls":
284
+ await cmdLs();
285
+ break;
286
+ case "status":
287
+ if (!args[1]) {
288
+ console.error("status requires a channelId argument");
289
+ usage();
290
+ }
291
+ await cmdStatus(args[1]);
292
+ break;
293
+ case "refund":
294
+ if (!args[1]) {
295
+ console.error("refund requires a <url> argument");
296
+ usage();
297
+ }
298
+ await cmdRefund(args[1], args[2]);
299
+ break;
300
+ case "withdraw": {
301
+ if (!args[1]) {
302
+ console.error("withdraw requires a <url> argument");
303
+ usage();
304
+ }
305
+ const finalize = args.includes("--finalize");
306
+ await cmdWithdraw(args[1], finalize);
307
+ break;
308
+ }
309
+ case "topup":
310
+ console.error("topup is not yet implemented (needs ERC-3009 deposit signing flow). " +
311
+ "See https://github.com/hpp-io/noosphere-x402-server/issues/9");
312
+ process.exit(64);
313
+ break;
314
+ case "--help":
315
+ case "-h":
316
+ case undefined:
317
+ usage();
318
+ default:
319
+ console.error(`unknown subcommand: ${subcmd}`);
320
+ usage();
321
+ }
322
+ }
323
+ main().catch((err) => {
324
+ console.error("hpp-x402-channel fatal:", err.message ?? err);
325
+ if (process.env.LOG_LEVEL === "debug" && err instanceof Error && err.stack) {
326
+ console.error(err.stack);
327
+ }
328
+ process.exit(1);
329
+ });
330
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../../src/cli/channel.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,6 @@
1
+ import { type InstallEnv, type InstallResult } from "./install-mcp-host.js";
1
2
  export declare function configPath(): string;
2
- export interface InstallEnv {
3
- DELEGATE_PRIVATE_KEY: string;
4
- SAFE_ADDRESS: string;
5
- ALLOWANCE_MODULE_ADDRESS: string;
6
- USDCE_ADDRESS: string;
7
- RESOURCE_SERVER_URL: string;
8
- HPP_RPC_URL: string;
9
- HPP_NETWORK: string;
10
- LOG_LEVEL?: string;
11
- }
12
- export interface InstallResult {
13
- configPath: string;
14
- backupPath: string | null;
15
- changed: boolean;
16
- preservedEntries: string[];
17
- }
18
- /**
19
- * Merge an `hpp-x402` server entry into the host config and write it.
20
- * `command`/`args` default to launching the published bridge via npx.
21
- */
3
+ export type { InstallEnv, InstallResult };
22
4
  export declare function installClaudeDesktop(env: InstallEnv, opts?: {
23
5
  force?: boolean;
24
6
  bridgeAbsPath?: string;
@@ -1,13 +1,13 @@
1
1
  /**
2
2
  * Merge an `hpp-x402` MCP server entry into the user's
3
- * claude_desktop_config.json. Importable function (used by setup CLI
4
- * with --install-claude) and a standalone bin entry.
3
+ * claude_desktop_config.json. Importable from the setup CLI
4
+ * (--install-claude flag).
5
5
  *
6
- * Preserves all other mcpServers entries; backs up the original.
6
+ * The merge logic is shared with OpenClaw see install-mcp-host.ts.
7
7
  */
8
- import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, } from "node:fs";
9
- import { resolve, dirname } from "node:path";
8
+ import { resolve } from "node:path";
10
9
  import { homedir, platform } from "node:os";
10
+ import { installMcpHost, } from "./install-mcp-host.js";
11
11
  const ENTRY_NAME = "hpp-x402";
12
12
  export function configPath() {
13
13
  const p = platform();
@@ -19,64 +19,13 @@ export function configPath() {
19
19
  }
20
20
  return resolve(homedir(), ".config/Claude/claude_desktop_config.json");
21
21
  }
22
- /**
23
- * Merge an `hpp-x402` server entry into the host config and write it.
24
- * `command`/`args` default to launching the published bridge via npx.
25
- */
26
22
  export function installClaudeDesktop(env, opts = {}) {
27
- const path = configPath();
28
- let existing = {};
29
- if (existsSync(path)) {
30
- existing = JSON.parse(readFileSync(path, "utf8"));
31
- }
32
- else {
33
- mkdirSync(dirname(path), { recursive: true });
34
- }
35
- const command = opts.bridgeAbsPath ? "node" : "npx";
36
- const args = opts.bridgeAbsPath
37
- ? [opts.bridgeAbsPath]
38
- : ["-y", "@hpp-io/x402-mcp-bridge"];
39
- const entry = {
40
- command,
41
- args,
42
- env: {
43
- DELEGATE_PRIVATE_KEY: env.DELEGATE_PRIVATE_KEY,
44
- SAFE_ADDRESS: env.SAFE_ADDRESS,
45
- ALLOWANCE_MODULE_ADDRESS: env.ALLOWANCE_MODULE_ADDRESS,
46
- USDCE_ADDRESS: env.USDCE_ADDRESS,
47
- RESOURCE_SERVER_URL: env.RESOURCE_SERVER_URL,
48
- HPP_RPC_URL: env.HPP_RPC_URL,
49
- HPP_NETWORK: env.HPP_NETWORK,
50
- LOG_LEVEL: env.LOG_LEVEL ?? "info",
51
- },
52
- };
53
- const mcpServers = (existing.mcpServers ??= {});
54
- const prior = mcpServers[ENTRY_NAME];
55
- if (prior && JSON.stringify(prior) === JSON.stringify(entry)) {
56
- return {
57
- configPath: path,
58
- backupPath: null,
59
- changed: false,
60
- preservedEntries: Object.keys(mcpServers).filter((k) => k !== ENTRY_NAME),
61
- };
62
- }
63
- if (prior && !opts.force) {
64
- throw new Error(`existing hpp-x402 entry differs; pass force:true (or --force in CLI) to overwrite`);
65
- }
66
- mcpServers[ENTRY_NAME] = entry;
67
- const merged = { ...existing, mcpServers };
68
- let backupPath = null;
69
- if (existsSync(path)) {
70
- const ts = new Date().toISOString().replace(/[:.]/g, "-");
71
- backupPath = path + "." + ts + ".bak";
72
- copyFileSync(path, backupPath);
73
- }
74
- writeFileSync(path, JSON.stringify(merged, null, 2) + "\n", "utf8");
75
- return {
76
- configPath: path,
77
- backupPath,
78
- changed: true,
79
- preservedEntries: Object.keys(mcpServers).filter((k) => k !== ENTRY_NAME),
80
- };
23
+ return installMcpHost({
24
+ configPath: configPath(),
25
+ entryName: ENTRY_NAME,
26
+ env,
27
+ force: opts.force,
28
+ bridgeAbsPath: opts.bridgeAbsPath,
29
+ });
81
30
  }
82
31
  //# sourceMappingURL=install-claude.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"install-claude.js","sourceRoot":"","sources":["../../src/cli/install-claude.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install-claude.js","sourceRoot":"","sources":["../../src/cli/install-claude.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,EACL,cAAc,GAGf,MAAM,uBAAuB,CAAC;AAE/B,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,UAAU,UAAU;IACxB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IACrB,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;QACnB,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,+DAA+D,CAAC,CAAC;IAC7F,CAAC;IACD,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,EAAE,mCAAmC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,2CAA2C,CAAC,CAAC;AACzE,CAAC;AAID,MAAM,UAAU,oBAAoB,CAClC,GAAe,EACf,OAAoD,EAAE;IAEtD,OAAO,cAAc,CAAC;QACpB,UAAU,EAAE,UAAU,EAAE;QACxB,SAAS,EAAE,UAAU;QACrB,GAAG;QACH,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,aAAa,EAAE,IAAI,CAAC,aAAa;KAClC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,35 @@
1
+ export interface InstallEnv {
2
+ DELEGATE_PRIVATE_KEY: string;
3
+ SAFE_ADDRESS: string;
4
+ ALLOWANCE_MODULE_ADDRESS: string;
5
+ USDCE_ADDRESS: string;
6
+ RESOURCE_SERVER_URL: string;
7
+ HPP_RPC_URL: string;
8
+ HPP_NETWORK: string;
9
+ LOG_LEVEL?: string;
10
+ }
11
+ export interface InstallResult {
12
+ configPath: string;
13
+ backupPath: string | null;
14
+ changed: boolean;
15
+ preservedEntries: string[];
16
+ }
17
+ export interface InstallOptions {
18
+ configPath: string;
19
+ entryName: string;
20
+ env: InstallEnv;
21
+ force?: boolean;
22
+ bridgeAbsPath?: string;
23
+ /**
24
+ * JSON key path where MCP servers live. Defaults to `["mcpServers"]`
25
+ * (Claude Desktop). OpenClaw uses `["mcp", "servers"]`.
26
+ */
27
+ serversKeyPath?: string[];
28
+ }
29
+ /**
30
+ * Merge an `<entryName>` MCP server entry into the host config and write it.
31
+ * Preserves all other entries; backs up the original if it exists.
32
+ * `command`/`args` default to launching the published bridge via npx;
33
+ * pass `bridgeAbsPath` for a local checkout.
34
+ */
35
+ export declare function installMcpHost(opts: InstallOptions): InstallResult;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Generic JSON-config merge for MCP hosts.
3
+ *
4
+ * Both Claude Desktop and OpenClaw store their MCP server registry as
5
+ * `{ mcpServers: { <name>: { command, args, env } } }` JSON. The merge
6
+ * logic is identical — only the file path differs. This module owns
7
+ * that logic; `install-claude.ts` / `install-openclaw.ts` are thin
8
+ * wrappers that pass the right path.
9
+ */
10
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, copyFileSync, } from "node:fs";
11
+ import { dirname } from "node:path";
12
+ function getOrCreateNested(root, keyPath) {
13
+ let cur = root;
14
+ for (const k of keyPath) {
15
+ if (typeof cur[k] !== "object" || cur[k] === null)
16
+ cur[k] = {};
17
+ cur = cur[k];
18
+ }
19
+ return cur;
20
+ }
21
+ /**
22
+ * Merge an `<entryName>` MCP server entry into the host config and write it.
23
+ * Preserves all other entries; backs up the original if it exists.
24
+ * `command`/`args` default to launching the published bridge via npx;
25
+ * pass `bridgeAbsPath` for a local checkout.
26
+ */
27
+ export function installMcpHost(opts) {
28
+ const { configPath, entryName, env, force, bridgeAbsPath, serversKeyPath = ["mcpServers"], } = opts;
29
+ let existing = {};
30
+ if (existsSync(configPath)) {
31
+ existing = JSON.parse(readFileSync(configPath, "utf8"));
32
+ }
33
+ else {
34
+ mkdirSync(dirname(configPath), { recursive: true });
35
+ }
36
+ const command = bridgeAbsPath ? "node" : "npx";
37
+ const args = bridgeAbsPath
38
+ ? [bridgeAbsPath]
39
+ : ["-y", "@hpp-io/x402-mcp-bridge"];
40
+ const entry = {
41
+ command,
42
+ args,
43
+ env: {
44
+ DELEGATE_PRIVATE_KEY: env.DELEGATE_PRIVATE_KEY,
45
+ SAFE_ADDRESS: env.SAFE_ADDRESS,
46
+ ALLOWANCE_MODULE_ADDRESS: env.ALLOWANCE_MODULE_ADDRESS,
47
+ USDCE_ADDRESS: env.USDCE_ADDRESS,
48
+ RESOURCE_SERVER_URL: env.RESOURCE_SERVER_URL,
49
+ HPP_RPC_URL: env.HPP_RPC_URL,
50
+ HPP_NETWORK: env.HPP_NETWORK,
51
+ LOG_LEVEL: env.LOG_LEVEL ?? "info",
52
+ },
53
+ };
54
+ const servers = getOrCreateNested(existing, serversKeyPath);
55
+ const prior = servers[entryName];
56
+ if (prior && JSON.stringify(prior) === JSON.stringify(entry)) {
57
+ return {
58
+ configPath,
59
+ backupPath: null,
60
+ changed: false,
61
+ preservedEntries: Object.keys(servers).filter((k) => k !== entryName),
62
+ };
63
+ }
64
+ if (prior && !force) {
65
+ throw new Error(`existing ${entryName} entry differs; pass force:true (or --force in CLI) to overwrite`);
66
+ }
67
+ servers[entryName] = entry;
68
+ let backupPath = null;
69
+ if (existsSync(configPath)) {
70
+ const ts = new Date().toISOString().replace(/[:.]/g, "-");
71
+ backupPath = configPath + "." + ts + ".bak";
72
+ copyFileSync(configPath, backupPath);
73
+ }
74
+ writeFileSync(configPath, JSON.stringify(existing, null, 2) + "\n", "utf8");
75
+ return {
76
+ configPath,
77
+ backupPath,
78
+ changed: true,
79
+ preservedEntries: Object.keys(servers).filter((k) => k !== entryName),
80
+ };
81
+ }
82
+ //# sourceMappingURL=install-mcp-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-mcp-host.js","sourceRoot":"","sources":["../../src/cli/install-mcp-host.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { type InstallEnv, type InstallResult } from "./install-mcp-host.js";
2
+ export declare function configPath(): string;
3
+ export declare function installOpenClaw(env: InstallEnv, opts?: {
4
+ force?: boolean;
5
+ bridgeAbsPath?: string;
6
+ configPathOverride?: string;
7
+ }): InstallResult;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Merge an `hpp-x402` MCP server entry into the user's OpenClaw config.
3
+ *
4
+ * OpenClaw stores its MCP gateway config as JSON at
5
+ * ~/.openclaw/openclaw.json (default)
6
+ *
7
+ * If a project / corp setup uses a non-default location, callers can
8
+ * pass `configPathOverride` to point at it directly. The merge logic
9
+ * is shared with Claude Desktop — see install-mcp-host.ts.
10
+ */
11
+ import { resolve } from "node:path";
12
+ import { homedir } from "node:os";
13
+ import { installMcpHost, } from "./install-mcp-host.js";
14
+ const ENTRY_NAME = "hpp-x402";
15
+ export function configPath() {
16
+ return resolve(homedir(), ".openclaw/openclaw.json");
17
+ }
18
+ export function installOpenClaw(env, opts = {}) {
19
+ return installMcpHost({
20
+ configPath: opts.configPathOverride ?? configPath(),
21
+ entryName: ENTRY_NAME,
22
+ env,
23
+ force: opts.force,
24
+ bridgeAbsPath: opts.bridgeAbsPath,
25
+ serversKeyPath: ["mcp", "servers"],
26
+ });
27
+ }
28
+ //# sourceMappingURL=install-openclaw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-openclaw.js","sourceRoot":"","sources":["../../src/cli/install-openclaw.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAElC,OAAO,EACL,cAAc,GAGf,MAAM,uBAAuB,CAAC;AAE/B,MAAM,UAAU,GAAG,UAAU,CAAC;AAE9B,MAAM,UAAU,UAAU;IACxB,OAAO,OAAO,CAAC,OAAO,EAAE,EAAE,yBAAyB,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,eAAe,CAC7B,GAAe,EACf,OAAiF,EAAE;IAEnF,OAAO,cAAc,CAAC;QACpB,UAAU,EAAE,IAAI,CAAC,kBAAkB,IAAI,UAAU,EAAE;QACnD,SAAS,EAAE,UAAU;QACrB,GAAG;QACH,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,CAAC;KACnC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1 @@
1
+ export {};