x402-proxy 0.8.6 → 0.9.1
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.
- package/CHANGELOG.md +34 -1
- package/README.md +25 -9
- package/dist/bin/cli.js +258 -35
- package/dist/{derive-BR6N1ZjI.js → derive-CAYmX-Yz.js} +1 -1
- package/dist/openclaw/plugin.js +1 -1
- package/dist/{setup-B1r-Opou.js → setup-B7YJa7s6.js} +79 -10
- package/dist/setup-xhtYsp7D.js +4 -0
- package/dist/{status-DjudJ6fD.js → status-BkURZYDA.js} +1 -1
- package/dist/{status-DvSu8reM.js → status-D3f5IVf6.js} +2 -2
- package/dist/{wallet-BkZ0DOJL.js → wallet-BM0ngyqk.js} +1 -1
- package/dist/{wallet-BiX5_XFY.js → wallet-DZsXptY7.js} +3 -3
- package/package.json +4 -3
- package/skills/SKILL.md +24 -7
- package/dist/setup-CH4woul8.js +0 -4
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.9.1] - 2026-03-26
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
- `setup --non-interactive` flag - auto-generates wallet and outputs addresses as JSON to stdout (`{"base":"0x...","tempo":"0x...","solana":"..."}`)
|
|
14
|
+
- `setup --import-mnemonic` flag - import existing BIP-39 mnemonic non-interactively
|
|
15
|
+
- MCP proxy auto-generates wallet on first run when no wallet exists (no more "No wallet configured" error)
|
|
16
|
+
- OpenClaw integration example in README and SKILL.md: `openclaw mcp set surf '{"command":"npx","args":["-y","x402-proxy","mcp","https://surf.cascade.fyi/mcp"]}'`
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
- `npx -y` flag added to all generated MCP configs (`mcp add` command and docs) - prevents npx install prompt from corrupting MCP stdio protocol
|
|
20
|
+
- MCP config examples no longer show `X402_PROXY_WALLET_MNEMONIC` env var as default - wallet file is the primary path, env vars are documented as fallback only
|
|
21
|
+
- All example MCP URLs updated to `https://surf.cascade.fyi/mcp`
|
|
22
|
+
- Non-interactive JSON output uses network names (`base`, `tempo`, `solana`) instead of generic `evm`
|
|
23
|
+
|
|
24
|
+
## [0.9.0] - 2026-03-25
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
- `mcp add` command - onboarding wizard to install MCP servers into Claude Code, Cursor, VS Code, and 16+ other AI clients via `@getmcp/generators`
|
|
28
|
+
- Auto-detects installed AI clients and highlights them in the selection list
|
|
29
|
+
- Shows config diff preview with green markers before writing
|
|
30
|
+
- Prompts to overwrite if server name already exists (shows current config)
|
|
31
|
+
- Wallet setup runs automatically if not yet configured
|
|
32
|
+
- Balance check and funding hints shown after successful install
|
|
33
|
+
- `-c` / `--config-dir` global flag to override config directory for all commands
|
|
34
|
+
- Custom config directory injected as `XDG_CONFIG_HOME` env var into generated MCP server configs
|
|
35
|
+
- Tempo address shown alongside Base address in setup wizard
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- Solana USDC balance shows `0` instead of `?` for fresh wallets (non-existent ATA means zero balance, not unknown)
|
|
39
|
+
- MPP payment protocol description corrected from "streaming micropayments" to "machine payments over HTTP 402"
|
|
40
|
+
|
|
10
41
|
## [0.8.6] - 2026-03-25
|
|
11
42
|
|
|
12
43
|
### Fixed
|
|
@@ -246,7 +277,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
246
277
|
- `appendHistory` / `readHistory` / `calcSpend` - JSONL transaction history
|
|
247
278
|
- Re-exports from `@x402/fetch`, `@x402/svm`, `@x402/evm`
|
|
248
279
|
|
|
249
|
-
[Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.
|
|
280
|
+
[Unreleased]: https://github.com/cascade-protocol/x402-proxy/compare/v0.9.1...HEAD
|
|
281
|
+
[0.9.1]: https://github.com/cascade-protocol/x402-proxy/compare/v0.9.0...v0.9.1
|
|
282
|
+
[0.9.0]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.6...v0.9.0
|
|
250
283
|
[0.8.6]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.5...v0.8.6
|
|
251
284
|
[0.8.5]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.4...v0.8.5
|
|
252
285
|
[0.8.4]: https://github.com/cascade-protocol/x402-proxy/compare/v0.8.3...v0.8.4
|
package/README.md
CHANGED
|
@@ -14,23 +14,38 @@ No wallet? It'll walk you through setup automatically. One mnemonic derives both
|
|
|
14
14
|
|
|
15
15
|
## MCP Proxy
|
|
16
16
|
|
|
17
|
-
Let your AI agent consume any paid MCP server.
|
|
17
|
+
Let your AI agent consume any paid MCP server.
|
|
18
|
+
|
|
19
|
+
### Quick setup
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npx x402-proxy mcp add surf https://surf.cascade.fyi/mcp
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Auto-detects installed AI clients (Claude Code, Cursor, VS Code, and 16+ others), shows a config preview, and writes it for you. Runs wallet setup if needed.
|
|
26
|
+
|
|
27
|
+
### Manual config
|
|
28
|
+
|
|
29
|
+
Or add to your client config directly:
|
|
18
30
|
|
|
19
31
|
```json
|
|
20
32
|
{
|
|
21
33
|
"mcpServers": {
|
|
22
|
-
"
|
|
34
|
+
"surf": {
|
|
23
35
|
"command": "npx",
|
|
24
|
-
"args": ["x402-proxy", "mcp", "https://
|
|
25
|
-
"env": {
|
|
26
|
-
"X402_PROXY_WALLET_MNEMONIC": "your 24 words here"
|
|
27
|
-
}
|
|
36
|
+
"args": ["-y", "x402-proxy", "mcp", "https://surf.cascade.fyi/mcp"]
|
|
28
37
|
}
|
|
29
38
|
}
|
|
30
39
|
}
|
|
31
40
|
```
|
|
32
41
|
|
|
33
|
-
The proxy
|
|
42
|
+
The proxy auto-generates a wallet on first run and uses `~/.config/x402-proxy/wallet.json`. No env vars needed. Your agent never touches crypto.
|
|
43
|
+
|
|
44
|
+
For OpenClaw:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
openclaw mcp set surf '{"command":"npx","args":["-y","x402-proxy","mcp","https://surf.cascade.fyi/mcp"]}'
|
|
48
|
+
```
|
|
34
49
|
|
|
35
50
|
## HTTP Requests
|
|
36
51
|
|
|
@@ -67,6 +82,7 @@ $ npx x402-proxy https://api.example.com/data | jq '.results'
|
|
|
67
82
|
```bash
|
|
68
83
|
$ npx x402-proxy <url> # paid HTTP request (default command)
|
|
69
84
|
$ npx x402-proxy mcp <url> # MCP stdio proxy for agents
|
|
85
|
+
$ npx x402-proxy mcp add <name> <url> # install MCP server into your AI client
|
|
70
86
|
$ npx x402-proxy setup # onboarding wizard
|
|
71
87
|
$ npx x402-proxy status # config + wallet + spend summary
|
|
72
88
|
$ npx x402-proxy config # show current configuration
|
|
@@ -77,7 +93,7 @@ $ npx x402-proxy wallet history # payment history
|
|
|
77
93
|
$ npx x402-proxy wallet export-key <target> # bare key/mnemonic to stdout (evm|solana|mnemonic)
|
|
78
94
|
```
|
|
79
95
|
|
|
80
|
-
All commands support `--help` for details.
|
|
96
|
+
All commands support `--help` for details. Use `-c <dir>` to override the config directory.
|
|
81
97
|
|
|
82
98
|
## Wallet
|
|
83
99
|
|
|
@@ -97,7 +113,7 @@ $ MY_MNEMONIC=$(npx x402-proxy wallet export-key mnemonic)
|
|
|
97
113
|
|
|
98
114
|
## Env Vars
|
|
99
115
|
|
|
100
|
-
Override wallet per-instance (
|
|
116
|
+
Override wallet per-instance (fallback for environments where the wallet file isn't accessible):
|
|
101
117
|
|
|
102
118
|
```
|
|
103
119
|
X402_PROXY_WALLET_MNEMONIC # BIP-39 mnemonic (derives both chains)
|
package/dist/bin/cli.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort, l as loadWalletFile, s as isConfigured, u as saveConfig } from "../derive-
|
|
3
|
-
import { _ as error, b as warn, c as resolveWallet, d as displayNetwork, f as formatAmount, g as dim, h as readHistory, l as appendHistory, m as formatUsdcValue, o as walletInfoCommand, p as formatTxLine, s as buildX402Client, u as calcSpend, v as info, y as isTTY } from "../wallet-
|
|
4
|
-
import { n as setupCommand } from "../setup-
|
|
5
|
-
import { n as statusCommand } from "../status-
|
|
2
|
+
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort, l as loadWalletFile, s as isConfigured, u as saveConfig } from "../derive-CAYmX-Yz.js";
|
|
3
|
+
import { _ as error, b as warn, c as resolveWallet, d as displayNetwork, f as formatAmount, g as dim, h as readHistory, l as appendHistory, m as formatUsdcValue, n as fetchAllBalances, o as walletInfoCommand, p as formatTxLine, s as buildX402Client, u as calcSpend, v as info, y as isTTY } from "../wallet-DZsXptY7.js";
|
|
4
|
+
import { n as setupCommand, t as runSetup } from "../setup-B7YJa7s6.js";
|
|
5
|
+
import { n as statusCommand } from "../status-D3f5IVf6.js";
|
|
6
|
+
import { dirname, join, normalize, resolve } from "node:path";
|
|
6
7
|
import { buildApplication, buildCommand, buildRouteMap, run } from "@stricli/core";
|
|
7
8
|
import pc from "picocolors";
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { homedir } from "node:os";
|
|
8
11
|
import { decodePaymentResponseHeader, wrapFetchWithPayment } from "@x402/fetch";
|
|
9
12
|
import { base58 } from "@scure/base";
|
|
10
13
|
import * as prompts from "@clack/prompts";
|
|
@@ -398,7 +401,7 @@ Examples:
|
|
|
398
401
|
};
|
|
399
402
|
if (!url) {
|
|
400
403
|
if (isConfigured()) {
|
|
401
|
-
const { displayStatus } = await import("../status-
|
|
404
|
+
const { displayStatus } = await import("../status-BkURZYDA.js");
|
|
402
405
|
await displayStatus();
|
|
403
406
|
console.log();
|
|
404
407
|
console.log(pc.dim(" Commands:"));
|
|
@@ -450,7 +453,7 @@ Examples:
|
|
|
450
453
|
process.exit(1);
|
|
451
454
|
}
|
|
452
455
|
dim(" No wallet found. Let's set one up first.\n");
|
|
453
|
-
const { runSetup } = await import("../setup-
|
|
456
|
+
const { runSetup } = await import("../setup-xhtYsp7D.js");
|
|
454
457
|
await runSetup();
|
|
455
458
|
console.log();
|
|
456
459
|
wallet = resolveWallet();
|
|
@@ -463,7 +466,7 @@ Examples:
|
|
|
463
466
|
verbose(`protocol: ${resolvedProtocol ?? "auto-detect"}, maxDeposit: ${maxDeposit}`);
|
|
464
467
|
let preferredNetwork = config?.defaultNetwork;
|
|
465
468
|
if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
|
|
466
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
469
|
+
const { fetchAllBalances } = await import("../wallet-BM0ngyqk.js");
|
|
467
470
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
468
471
|
const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
|
|
469
472
|
const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -630,7 +633,7 @@ Examples:
|
|
|
630
633
|
const hasSolana = accepts.some((a) => a.network.startsWith("solana:"));
|
|
631
634
|
const hasMpp = detected.mpp;
|
|
632
635
|
const hasOther = accepts.some((a) => !a.network.startsWith("eip155:") && !a.network.startsWith("solana:"));
|
|
633
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
636
|
+
const { fetchAllBalances } = await import("../wallet-BM0ngyqk.js");
|
|
634
637
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
635
638
|
const evmUsdc = hasEvm && balances.evm ? Number(balances.evm.usdc) : 0;
|
|
636
639
|
const solUsdc = hasSolana && balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -761,8 +764,9 @@ const mcpCommand = buildCommand({
|
|
|
761
764
|
|
|
762
765
|
Add to your MCP client config (Claude, Cursor, etc.):
|
|
763
766
|
"command": "npx",
|
|
764
|
-
"args": ["x402-proxy", "mcp", "https://
|
|
765
|
-
|
|
767
|
+
"args": ["-y", "x402-proxy", "mcp", "https://surf.cascade.fyi/mcp"]
|
|
768
|
+
|
|
769
|
+
Wallet is auto-generated on first run. No env vars needed.`
|
|
766
770
|
},
|
|
767
771
|
parameters: {
|
|
768
772
|
flags: {
|
|
@@ -805,8 +809,18 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
805
809
|
solanaKey: flags.solanaKey
|
|
806
810
|
});
|
|
807
811
|
if (wallet.source === "none") {
|
|
808
|
-
|
|
809
|
-
|
|
812
|
+
dim("No wallet found. Auto-generating...");
|
|
813
|
+
const { runSetup } = await import("../setup-xhtYsp7D.js");
|
|
814
|
+
await runSetup({ nonInteractive: true });
|
|
815
|
+
const fresh = resolveWallet({
|
|
816
|
+
evmKey: flags.evmKey,
|
|
817
|
+
solanaKey: flags.solanaKey
|
|
818
|
+
});
|
|
819
|
+
if (fresh.source === "none") {
|
|
820
|
+
error("Wallet auto-setup failed. Run: $ npx x402-proxy setup");
|
|
821
|
+
process.exit(1);
|
|
822
|
+
}
|
|
823
|
+
Object.assign(wallet, fresh);
|
|
810
824
|
}
|
|
811
825
|
dim(`x402-proxy MCP proxy -> ${remoteUrl}`);
|
|
812
826
|
if (wallet.evmAddress) dim(` EVM: ${wallet.evmAddress}`);
|
|
@@ -840,7 +854,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
840
854
|
async function startX402Proxy() {
|
|
841
855
|
let preferredNetwork = config?.defaultNetwork;
|
|
842
856
|
if (!preferredNetwork && wallet.evmAddress && wallet.solanaAddress) {
|
|
843
|
-
const { fetchAllBalances } = await import("../wallet-
|
|
857
|
+
const { fetchAllBalances } = await import("../wallet-BM0ngyqk.js");
|
|
844
858
|
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
845
859
|
const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
|
|
846
860
|
const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
|
|
@@ -860,7 +874,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
860
874
|
}
|
|
861
875
|
const remoteClient = new Client({
|
|
862
876
|
name: "x402-proxy",
|
|
863
|
-
version: "0.
|
|
877
|
+
version: "0.9.1"
|
|
864
878
|
});
|
|
865
879
|
const x402Mcp = new x402MCPClient(remoteClient, x402PaymentClient, {
|
|
866
880
|
autoPayment: true,
|
|
@@ -898,7 +912,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
898
912
|
}
|
|
899
913
|
const localServer = new Server({
|
|
900
914
|
name: "x402-proxy",
|
|
901
|
-
version: "0.
|
|
915
|
+
version: "0.9.1"
|
|
902
916
|
}, { capabilities: {
|
|
903
917
|
tools: tools.length > 0 ? {} : void 0,
|
|
904
918
|
resources: remoteResources.length > 0 ? {} : void 0
|
|
@@ -993,7 +1007,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
993
1007
|
}));
|
|
994
1008
|
const remoteClient = new Client({
|
|
995
1009
|
name: "x402-proxy",
|
|
996
|
-
version: "0.
|
|
1010
|
+
version: "0.9.1"
|
|
997
1011
|
});
|
|
998
1012
|
await connectTransport(remoteClient);
|
|
999
1013
|
const mppClient = McpClient.wrap(remoteClient, { methods: wrappedMethods });
|
|
@@ -1008,7 +1022,7 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
1008
1022
|
}
|
|
1009
1023
|
const localServer = new Server({
|
|
1010
1024
|
name: "x402-proxy",
|
|
1011
|
-
version: "0.
|
|
1025
|
+
version: "0.9.1"
|
|
1012
1026
|
}, { capabilities: {
|
|
1013
1027
|
tools: tools.length > 0 ? {} : void 0,
|
|
1014
1028
|
resources: remoteResources.length > 0 ? {} : void 0
|
|
@@ -1085,6 +1099,190 @@ Add to your MCP client config (Claude, Cursor, etc.):
|
|
|
1085
1099
|
}
|
|
1086
1100
|
});
|
|
1087
1101
|
|
|
1102
|
+
//#endregion
|
|
1103
|
+
//#region src/commands/mcp-add.ts
|
|
1104
|
+
function resolvePlatformPath(raw) {
|
|
1105
|
+
let p = raw;
|
|
1106
|
+
if (p.startsWith("~/")) p = join(homedir(), p.slice(2));
|
|
1107
|
+
p = p.replace(/%UserProfile%/gi, homedir());
|
|
1108
|
+
p = p.replace(/%AppData%/gi, process.env.APPDATA ?? join(homedir(), "AppData", "Roaming"));
|
|
1109
|
+
p = p.replace(/%LocalAppData%/gi, process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local"));
|
|
1110
|
+
return normalize(p);
|
|
1111
|
+
}
|
|
1112
|
+
function parseConfigFile(path, format) {
|
|
1113
|
+
if (!existsSync(path)) return {};
|
|
1114
|
+
const raw = readFileSync(path, "utf-8").trim();
|
|
1115
|
+
if (!raw) return {};
|
|
1116
|
+
if (format === "json" || format === "jsonc") {
|
|
1117
|
+
const stripped = format === "jsonc" ? raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "") : raw;
|
|
1118
|
+
return JSON.parse(stripped);
|
|
1119
|
+
}
|
|
1120
|
+
return JSON.parse(raw);
|
|
1121
|
+
}
|
|
1122
|
+
const mcpAddCommand = buildCommand({
|
|
1123
|
+
docs: {
|
|
1124
|
+
brief: "Add an MCP server to your AI client",
|
|
1125
|
+
fullDescription: "Add a remote MCP server to Claude Code, Cursor, VS Code, or other AI clients with automatic x402 payment proxy."
|
|
1126
|
+
},
|
|
1127
|
+
parameters: {
|
|
1128
|
+
flags: {
|
|
1129
|
+
client: {
|
|
1130
|
+
kind: "parsed",
|
|
1131
|
+
brief: "Target client (claude-code, cursor, vscode, etc.)",
|
|
1132
|
+
parse: String,
|
|
1133
|
+
optional: true
|
|
1134
|
+
},
|
|
1135
|
+
yes: {
|
|
1136
|
+
kind: "boolean",
|
|
1137
|
+
brief: "Skip confirmation prompt",
|
|
1138
|
+
default: false
|
|
1139
|
+
}
|
|
1140
|
+
},
|
|
1141
|
+
positional: {
|
|
1142
|
+
kind: "tuple",
|
|
1143
|
+
parameters: [{
|
|
1144
|
+
brief: "Server name",
|
|
1145
|
+
parse: String
|
|
1146
|
+
}, {
|
|
1147
|
+
brief: "Remote MCP server URL",
|
|
1148
|
+
parse: String
|
|
1149
|
+
}]
|
|
1150
|
+
}
|
|
1151
|
+
},
|
|
1152
|
+
async func(flags, name, url) {
|
|
1153
|
+
prompts.intro(pc.cyan("Add MCP server"));
|
|
1154
|
+
try {
|
|
1155
|
+
new URL(url);
|
|
1156
|
+
} catch {
|
|
1157
|
+
prompts.log.error(`Invalid URL: ${url}`);
|
|
1158
|
+
prompts.cancel("Aborted.");
|
|
1159
|
+
process.exit(1);
|
|
1160
|
+
}
|
|
1161
|
+
const serverName = name;
|
|
1162
|
+
if (!isConfigured()) {
|
|
1163
|
+
prompts.log.warn("No wallet configured. Let's set one up first.\n");
|
|
1164
|
+
await runSetup();
|
|
1165
|
+
console.log();
|
|
1166
|
+
prompts.log.step(pc.cyan("Continuing MCP setup..."));
|
|
1167
|
+
}
|
|
1168
|
+
const { generators, getAppIds, generateConfig, deepMerge } = await import("@getmcp/generators");
|
|
1169
|
+
let clientId;
|
|
1170
|
+
if (flags.client) {
|
|
1171
|
+
const appIds = getAppIds();
|
|
1172
|
+
if (!appIds.includes(flags.client)) {
|
|
1173
|
+
prompts.log.error(`Unknown client: ${flags.client}`);
|
|
1174
|
+
prompts.log.info(`Supported: ${appIds.join(", ")}`);
|
|
1175
|
+
prompts.cancel("Aborted.");
|
|
1176
|
+
process.exit(1);
|
|
1177
|
+
}
|
|
1178
|
+
clientId = flags.client;
|
|
1179
|
+
} else {
|
|
1180
|
+
const appIds = getAppIds();
|
|
1181
|
+
const detected = appIds.filter((id) => generators[id].detectInstalled());
|
|
1182
|
+
const selected = await prompts.select({
|
|
1183
|
+
message: "Where would you like to install the MCP server?",
|
|
1184
|
+
options: appIds.map((id) => ({
|
|
1185
|
+
value: id,
|
|
1186
|
+
label: `${generators[id].app.name}${detected.includes(id) ? pc.dim(" (detected)") : ""}`
|
|
1187
|
+
})),
|
|
1188
|
+
initialValue: detected.includes("claude-code") ? "claude-code" : detected[0] ?? "claude-code"
|
|
1189
|
+
});
|
|
1190
|
+
if (prompts.isCancel(selected)) {
|
|
1191
|
+
prompts.cancel("Cancelled.");
|
|
1192
|
+
process.exit(0);
|
|
1193
|
+
}
|
|
1194
|
+
clientId = selected;
|
|
1195
|
+
}
|
|
1196
|
+
const generator = generators[clientId];
|
|
1197
|
+
const globalPaths = generator.app.globalConfigPaths;
|
|
1198
|
+
const platform = process.platform;
|
|
1199
|
+
const rawPath = globalPaths?.[platform];
|
|
1200
|
+
if (!rawPath) {
|
|
1201
|
+
prompts.log.error(`No global config path for ${generator.app.name} on ${platform}`);
|
|
1202
|
+
prompts.cancel("Aborted.");
|
|
1203
|
+
process.exit(1);
|
|
1204
|
+
}
|
|
1205
|
+
const configPath = resolvePlatformPath(rawPath);
|
|
1206
|
+
const configFormat = generator.app.configFormat;
|
|
1207
|
+
const configDirOverride = process.env.X402_PROXY_CONFIG_DIR_OVERRIDE;
|
|
1208
|
+
const generated = generateConfig(clientId, serverName, {
|
|
1209
|
+
command: "npx",
|
|
1210
|
+
args: [
|
|
1211
|
+
"-y",
|
|
1212
|
+
"x402-proxy",
|
|
1213
|
+
"mcp",
|
|
1214
|
+
url
|
|
1215
|
+
],
|
|
1216
|
+
env: configDirOverride ? { XDG_CONFIG_HOME: configDirOverride } : {},
|
|
1217
|
+
transport: "stdio"
|
|
1218
|
+
});
|
|
1219
|
+
let existing;
|
|
1220
|
+
if (configFormat === "yaml") {
|
|
1221
|
+
const { default: YAML } = await import("yaml");
|
|
1222
|
+
if (existsSync(configPath)) {
|
|
1223
|
+
const raw = readFileSync(configPath, "utf-8").trim();
|
|
1224
|
+
existing = raw ? YAML.parse(raw) ?? {} : {};
|
|
1225
|
+
} else existing = {};
|
|
1226
|
+
} else existing = parseConfigFile(configPath, configFormat);
|
|
1227
|
+
const rootKey = Object.keys(generated)[0] ?? "mcpServers";
|
|
1228
|
+
const existingServers = existing[rootKey] ?? {};
|
|
1229
|
+
if (existingServers[serverName]) {
|
|
1230
|
+
prompts.log.warn(`Server ${pc.bold(serverName)} already exists in config`);
|
|
1231
|
+
prompts.log.message(pc.dim(JSON.stringify({ [serverName]: existingServers[serverName] }, null, 2)));
|
|
1232
|
+
const overwrite = await prompts.confirm({ message: "Overwrite?" });
|
|
1233
|
+
if (prompts.isCancel(overwrite) || !overwrite) {
|
|
1234
|
+
prompts.cancel("Cancelled.");
|
|
1235
|
+
process.exit(0);
|
|
1236
|
+
}
|
|
1237
|
+
}
|
|
1238
|
+
prompts.log.info(`Config will be added to ${pc.dim(configPath)}`);
|
|
1239
|
+
const previewLines = generator.serialize(generated).split("\n");
|
|
1240
|
+
const formatted = previewLines.map((line, i) => {
|
|
1241
|
+
if (i === 0 || i === previewLines.length - 1) return line;
|
|
1242
|
+
const trimmed = line.trimStart();
|
|
1243
|
+
if (trimmed.startsWith(`"${rootKey}"`) || trimmed.startsWith(`${rootKey}:`)) return line;
|
|
1244
|
+
return `${pc.green("+")} ${line}`;
|
|
1245
|
+
}).join("\n");
|
|
1246
|
+
prompts.log.message(formatted);
|
|
1247
|
+
if (!flags.yes) {
|
|
1248
|
+
const proceed = await prompts.confirm({ message: "Would you like to proceed?" });
|
|
1249
|
+
if (prompts.isCancel(proceed) || !proceed) {
|
|
1250
|
+
prompts.cancel("Cancelled.");
|
|
1251
|
+
process.exit(0);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
const merged = deepMerge(existing, generated);
|
|
1255
|
+
const dir = dirname(configPath);
|
|
1256
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
1257
|
+
const serialized = generator.serialize(merged);
|
|
1258
|
+
writeFileSync(configPath, serialized.endsWith("\n") ? serialized : `${serialized}\n`);
|
|
1259
|
+
prompts.log.success(`Added ${pc.bold(serverName)} MCP to ${pc.bold(generator.app.name)}`);
|
|
1260
|
+
const wallet = resolveWallet();
|
|
1261
|
+
if (wallet.source !== "none") {
|
|
1262
|
+
const balances = await fetchAllBalances(wallet.evmAddress, wallet.solanaAddress);
|
|
1263
|
+
const evmUsdc = balances.evm ? Number(balances.evm.usdc) : 0;
|
|
1264
|
+
const solUsdc = balances.sol ? Number(balances.sol.usdc) : 0;
|
|
1265
|
+
const tempoUsdc = balances.tempo ? Number(balances.tempo.usdc) : 0;
|
|
1266
|
+
if (evmUsdc === 0 && solUsdc === 0 && tempoUsdc === 0) {
|
|
1267
|
+
prompts.log.warn("Balance: 0 USDC");
|
|
1268
|
+
prompts.log.info("To use paid MCP tools, send USDC to your wallet:");
|
|
1269
|
+
if (wallet.evmAddress) prompts.log.message(` Base: ${pc.cyan(wallet.evmAddress)}`);
|
|
1270
|
+
if (wallet.solanaAddress) prompts.log.message(` Solana: ${pc.cyan(wallet.solanaAddress)}`);
|
|
1271
|
+
} else {
|
|
1272
|
+
const parts = [];
|
|
1273
|
+
if (balances.evm) parts.push(`Base: ${balances.evm.usdc} USDC`);
|
|
1274
|
+
if (balances.sol) parts.push(`Solana: ${balances.sol.usdc} USDC`);
|
|
1275
|
+
if (balances.tempo) parts.push(`Tempo: ${balances.tempo.usdc} USDC`);
|
|
1276
|
+
prompts.log.success(`Balance: ${parts.join(" | ")}`);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
prompts.log.step("Try your first request:");
|
|
1280
|
+
prompts.log.message(` ${pc.cyan("$ npx x402-proxy https://twitter.surf.cascade.fyi/users/cascade_fyi")}`);
|
|
1281
|
+
prompts.log.message(` ${pc.dim("Run")} ${pc.cyan("npx x402-proxy")} ${pc.dim("to see your wallet and balance")}`);
|
|
1282
|
+
prompts.outro(pc.green(`MCP server ${pc.bold(serverName)} is ready to use!`));
|
|
1283
|
+
}
|
|
1284
|
+
});
|
|
1285
|
+
|
|
1088
1286
|
//#endregion
|
|
1089
1287
|
//#region src/commands/wallet-export.ts
|
|
1090
1288
|
const walletExportCommand = buildCommand({
|
|
@@ -1190,28 +1388,37 @@ const walletHistoryCommand = buildCommand({
|
|
|
1190
1388
|
|
|
1191
1389
|
//#endregion
|
|
1192
1390
|
//#region src/app.ts
|
|
1391
|
+
const walletRoutes = buildRouteMap({
|
|
1392
|
+
routes: {
|
|
1393
|
+
info: walletInfoCommand,
|
|
1394
|
+
history: walletHistoryCommand,
|
|
1395
|
+
"export-key": walletExportCommand
|
|
1396
|
+
},
|
|
1397
|
+
defaultCommand: "info",
|
|
1398
|
+
docs: { brief: "Wallet management" }
|
|
1399
|
+
});
|
|
1400
|
+
const configRoutes = buildRouteMap({
|
|
1401
|
+
routes: {
|
|
1402
|
+
show: configShowCommand,
|
|
1403
|
+
set: configSetCommand,
|
|
1404
|
+
unset: configUnsetCommand
|
|
1405
|
+
},
|
|
1406
|
+
defaultCommand: "show",
|
|
1407
|
+
docs: { brief: "Manage configuration" }
|
|
1408
|
+
});
|
|
1193
1409
|
const routes = buildRouteMap({
|
|
1194
1410
|
routes: {
|
|
1195
1411
|
fetch: fetchCommand,
|
|
1196
|
-
mcp:
|
|
1197
|
-
wallet: buildRouteMap({
|
|
1412
|
+
mcp: buildRouteMap({
|
|
1198
1413
|
routes: {
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
"export-key": walletExportCommand
|
|
1414
|
+
proxy: mcpCommand,
|
|
1415
|
+
add: mcpAddCommand
|
|
1202
1416
|
},
|
|
1203
|
-
defaultCommand: "
|
|
1204
|
-
docs: { brief: "
|
|
1205
|
-
}),
|
|
1206
|
-
config: buildRouteMap({
|
|
1207
|
-
routes: {
|
|
1208
|
-
show: configShowCommand,
|
|
1209
|
-
set: configSetCommand,
|
|
1210
|
-
unset: configUnsetCommand
|
|
1211
|
-
},
|
|
1212
|
-
defaultCommand: "show",
|
|
1213
|
-
docs: { brief: "Manage configuration" }
|
|
1417
|
+
defaultCommand: "proxy",
|
|
1418
|
+
docs: { brief: "MCP proxy and management" }
|
|
1214
1419
|
}),
|
|
1420
|
+
wallet: walletRoutes,
|
|
1421
|
+
config: configRoutes,
|
|
1215
1422
|
setup: setupCommand,
|
|
1216
1423
|
status: statusCommand
|
|
1217
1424
|
},
|
|
@@ -1220,7 +1427,7 @@ const routes = buildRouteMap({
|
|
|
1220
1427
|
});
|
|
1221
1428
|
const app = buildApplication(routes, {
|
|
1222
1429
|
name: "x402-proxy",
|
|
1223
|
-
versionInfo: { currentVersion: "0.
|
|
1430
|
+
versionInfo: { currentVersion: "0.9.1" },
|
|
1224
1431
|
scanner: { caseStyle: "allow-kebab-for-camel" }
|
|
1225
1432
|
});
|
|
1226
1433
|
|
|
@@ -1232,7 +1439,23 @@ function buildContext(process) {
|
|
|
1232
1439
|
|
|
1233
1440
|
//#endregion
|
|
1234
1441
|
//#region src/bin/cli.ts
|
|
1235
|
-
|
|
1442
|
+
process.on("SIGINT", () => process.exit(130));
|
|
1443
|
+
const rawArgs = process.argv.slice(2);
|
|
1444
|
+
const args = [];
|
|
1445
|
+
for (let i = 0; i < rawArgs.length; i++) {
|
|
1446
|
+
const a = rawArgs[i];
|
|
1447
|
+
if (a === "-H") args.push("--header");
|
|
1448
|
+
else if ((a === "--config-dir" || a === "-c") && i + 1 < rawArgs.length) {
|
|
1449
|
+
const dir = resolve(rawArgs[++i]);
|
|
1450
|
+
process.env.XDG_CONFIG_HOME = dir;
|
|
1451
|
+
process.env.X402_PROXY_CONFIG_DIR_OVERRIDE = dir;
|
|
1452
|
+
} else if (a.startsWith("--config-dir=")) {
|
|
1453
|
+
const dir = resolve(a.slice(13));
|
|
1454
|
+
process.env.XDG_CONFIG_HOME = dir;
|
|
1455
|
+
process.env.X402_PROXY_CONFIG_DIR_OVERRIDE = dir;
|
|
1456
|
+
} else args.push(a);
|
|
1457
|
+
}
|
|
1458
|
+
await run(app, args, buildContext(process));
|
|
1236
1459
|
|
|
1237
1460
|
//#endregion
|
|
1238
1461
|
export { };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import fs from "node:fs";
|
|
3
4
|
import os from "node:os";
|
|
4
|
-
import path from "node:path";
|
|
5
5
|
import { parse, stringify } from "yaml";
|
|
6
6
|
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
7
7
|
import { base58 } from "@scure/base";
|
package/dist/openclaw/plugin.js
CHANGED
|
@@ -726,7 +726,7 @@ function createWalletCommand(ctx) {
|
|
|
726
726
|
try {
|
|
727
727
|
const snap = await getWalletSnapshot(ctx.rpcUrl, walletAddress, ctx.historyPath);
|
|
728
728
|
const solscanUrl = `https://solscan.io/account/${walletAddress}`;
|
|
729
|
-
const lines = [`x402-proxy v0.
|
|
729
|
+
const lines = [`x402-proxy v0.9.1`];
|
|
730
730
|
const defaultModel = ctx.allModels[0];
|
|
731
731
|
if (defaultModel) lines.push("", `**Model** - ${defaultModel.name} (${defaultModel.provider})`);
|
|
732
732
|
lines.push("", `**[Wallet](${solscanUrl})**`, `\`${walletAddress}\``);
|
|
@@ -1,15 +1,55 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { d as saveWalletFile, i as getConfigDirShort, n as deriveSolanaKeypair, o as getWalletPath, r as generateMnemonic, s as isConfigured, t as deriveEvmKeypair, u as saveConfig } from "./derive-
|
|
2
|
+
import { d as saveWalletFile, i as getConfigDirShort, l as loadWalletFile, n as deriveSolanaKeypair, o as getWalletPath, r as generateMnemonic, s as isConfigured, t as deriveEvmKeypair, u as saveConfig } from "./derive-CAYmX-Yz.js";
|
|
3
3
|
import { buildCommand } from "@stricli/core";
|
|
4
4
|
import pc from "picocolors";
|
|
5
5
|
import * as prompts from "@clack/prompts";
|
|
6
6
|
|
|
7
7
|
//#region src/commands/setup.ts
|
|
8
8
|
async function runSetup(opts) {
|
|
9
|
+
const nonInteractive = opts?.nonInteractive ?? false;
|
|
10
|
+
if (nonInteractive && isConfigured() && !opts?.force) {
|
|
11
|
+
const walletFile = loadWalletFile();
|
|
12
|
+
if (walletFile) {
|
|
13
|
+
process.stdout.write(`${JSON.stringify({
|
|
14
|
+
base: walletFile.addresses.evm,
|
|
15
|
+
tempo: walletFile.addresses.evm,
|
|
16
|
+
solana: walletFile.addresses.solana
|
|
17
|
+
})}\n`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
9
21
|
if (isConfigured() && !opts?.force) {
|
|
10
22
|
prompts.log.warn(`Already configured. Wallet at ${pc.dim(getWalletPath())}\nTo reconfigure, run:\n ${pc.cyan("$ npx x402-proxy setup --force")}`);
|
|
11
23
|
return;
|
|
12
24
|
}
|
|
25
|
+
let mnemonic;
|
|
26
|
+
if (nonInteractive) {
|
|
27
|
+
if (opts?.importMnemonic) {
|
|
28
|
+
const words = opts.importMnemonic.trim().split(/\s+/);
|
|
29
|
+
if (words.length !== 12 && words.length !== 24) {
|
|
30
|
+
process.stderr.write("Error: mnemonic must be 12 or 24 words\n");
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
mnemonic = opts.importMnemonic.trim();
|
|
34
|
+
} else mnemonic = generateMnemonic();
|
|
35
|
+
const evm = deriveEvmKeypair(mnemonic);
|
|
36
|
+
const sol = deriveSolanaKeypair(mnemonic);
|
|
37
|
+
saveWalletFile({
|
|
38
|
+
version: 1,
|
|
39
|
+
mnemonic,
|
|
40
|
+
addresses: {
|
|
41
|
+
evm: evm.address,
|
|
42
|
+
solana: sol.address
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
saveConfig({ preferredProtocol: "x402" });
|
|
46
|
+
process.stdout.write(`${JSON.stringify({
|
|
47
|
+
base: evm.address,
|
|
48
|
+
tempo: evm.address,
|
|
49
|
+
solana: sol.address
|
|
50
|
+
})}\n`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
13
53
|
prompts.intro(pc.cyan("x402-proxy setup"));
|
|
14
54
|
prompts.log.info("This will generate a single BIP-39 mnemonic that derives wallets for both Solana and EVM chains.");
|
|
15
55
|
const action = await prompts.select({
|
|
@@ -26,7 +66,6 @@ async function runSetup(opts) {
|
|
|
26
66
|
prompts.cancel("Setup cancelled.");
|
|
27
67
|
process.exit(0);
|
|
28
68
|
}
|
|
29
|
-
let mnemonic;
|
|
30
69
|
if (action === "generate") {
|
|
31
70
|
mnemonic = generateMnemonic();
|
|
32
71
|
prompts.log.warn("Write down your mnemonic and store it safely. It will NOT be shown again.");
|
|
@@ -48,6 +87,7 @@ async function runSetup(opts) {
|
|
|
48
87
|
const evm = deriveEvmKeypair(mnemonic);
|
|
49
88
|
const sol = deriveSolanaKeypair(mnemonic);
|
|
50
89
|
prompts.log.success(`Base address: ${pc.green(evm.address)}`);
|
|
90
|
+
prompts.log.success(`Tempo address: ${pc.green(evm.address)}`);
|
|
51
91
|
prompts.log.success(`Solana address: ${pc.green(sol.address)}`);
|
|
52
92
|
saveWalletFile({
|
|
53
93
|
version: 1,
|
|
@@ -64,7 +104,7 @@ async function runSetup(opts) {
|
|
|
64
104
|
label: "x402 - on-chain payments (Base, Solana)"
|
|
65
105
|
}, {
|
|
66
106
|
value: "mpp",
|
|
67
|
-
label: "MPP -
|
|
107
|
+
label: "MPP - machine payments over HTTP 402 (Tempo)"
|
|
68
108
|
}]
|
|
69
109
|
});
|
|
70
110
|
if (prompts.isCancel(protocol)) {
|
|
@@ -108,20 +148,49 @@ async function runSetup(opts) {
|
|
|
108
148
|
prompts.outro(pc.green("Setup complete!"));
|
|
109
149
|
}
|
|
110
150
|
const setupCommand = buildCommand({
|
|
111
|
-
docs: {
|
|
151
|
+
docs: {
|
|
152
|
+
brief: "Set up x402-proxy wallet (generate new or import existing mnemonic)",
|
|
153
|
+
fullDescription: `Set up x402-proxy wallet interactively, or use --non-interactive for automated environments.
|
|
154
|
+
|
|
155
|
+
Non-interactive mode auto-generates a wallet and outputs JSON to stdout:
|
|
156
|
+
$ npx x402-proxy setup --non-interactive
|
|
157
|
+
{"base":"0x...","tempo":"0x...","solana":"..."}
|
|
158
|
+
|
|
159
|
+
Import an existing mnemonic non-interactively:
|
|
160
|
+
$ npx x402-proxy setup --non-interactive --import-mnemonic "word1 word2 ... word24"
|
|
161
|
+
|
|
162
|
+
If a wallet already exists, --non-interactive outputs the existing addresses.`
|
|
163
|
+
},
|
|
112
164
|
parameters: {
|
|
113
|
-
flags: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
165
|
+
flags: {
|
|
166
|
+
force: {
|
|
167
|
+
kind: "boolean",
|
|
168
|
+
brief: "Overwrite existing configuration",
|
|
169
|
+
default: false
|
|
170
|
+
},
|
|
171
|
+
nonInteractive: {
|
|
172
|
+
kind: "boolean",
|
|
173
|
+
brief: "Auto-generate wallet and output addresses as JSON (no prompts)",
|
|
174
|
+
default: false
|
|
175
|
+
},
|
|
176
|
+
importMnemonic: {
|
|
177
|
+
kind: "parsed",
|
|
178
|
+
brief: "Import a BIP-39 mnemonic (use with --non-interactive)",
|
|
179
|
+
parse: String,
|
|
180
|
+
optional: true
|
|
181
|
+
}
|
|
182
|
+
},
|
|
118
183
|
positional: {
|
|
119
184
|
kind: "tuple",
|
|
120
185
|
parameters: []
|
|
121
186
|
}
|
|
122
187
|
},
|
|
123
188
|
async func(flags) {
|
|
124
|
-
await runSetup({
|
|
189
|
+
await runSetup({
|
|
190
|
+
force: flags.force,
|
|
191
|
+
nonInteractive: flags.nonInteractive,
|
|
192
|
+
importMnemonic: flags.importMnemonic
|
|
193
|
+
});
|
|
125
194
|
}
|
|
126
195
|
});
|
|
127
196
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort } from "./derive-
|
|
3
|
-
import { c as resolveWallet, f as formatAmount, g as dim, h as readHistory, m as formatUsdcValue, n as fetchAllBalances, p as formatTxLine, t as balanceLine, u as calcSpend } from "./wallet-
|
|
2
|
+
import { a as getHistoryPath, c as loadConfig, i as getConfigDirShort } from "./derive-CAYmX-Yz.js";
|
|
3
|
+
import { c as resolveWallet, f as formatAmount, g as dim, h as readHistory, m as formatUsdcValue, n as fetchAllBalances, p as formatTxLine, t as balanceLine, u as calcSpend } from "./wallet-DZsXptY7.js";
|
|
4
4
|
import { buildCommand } from "@stricli/core";
|
|
5
5
|
import pc from "picocolors";
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as fetchTempoBalances, i as fetchSolanaBalances, n as fetchAllBalances, o as walletInfoCommand, r as fetchEvmBalances, t as balanceLine } from "./wallet-
|
|
2
|
+
import { a as fetchTempoBalances, i as fetchSolanaBalances, n as fetchAllBalances, o as walletInfoCommand, r as fetchEvmBalances, t as balanceLine } from "./wallet-DZsXptY7.js";
|
|
3
3
|
|
|
4
4
|
export { fetchAllBalances };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as getHistoryPath, l as loadWalletFile, n as deriveSolanaKeypair, t as deriveEvmKeypair } from "./derive-
|
|
2
|
+
import { a as getHistoryPath, l as loadWalletFile, n as deriveSolanaKeypair, t as deriveEvmKeypair } from "./derive-CAYmX-Yz.js";
|
|
3
|
+
import { dirname } from "node:path";
|
|
3
4
|
import { buildCommand } from "@stricli/core";
|
|
4
5
|
import pc from "picocolors";
|
|
5
6
|
import { appendFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
6
|
-
import { dirname } from "node:path";
|
|
7
7
|
import { x402Client } from "@x402/fetch";
|
|
8
8
|
import { ed25519 } from "@noble/curves/ed25519.js";
|
|
9
9
|
import { base58 } from "@scure/base";
|
|
@@ -374,7 +374,7 @@ async function fetchSolanaBalances(ownerAddress) {
|
|
|
374
374
|
const usdcVal = usdcRes.result?.value;
|
|
375
375
|
return {
|
|
376
376
|
sol,
|
|
377
|
-
usdc: usdcVal ? formatUsdcValue(Number(usdcVal.uiAmountString)) :
|
|
377
|
+
usdc: usdcVal ? formatUsdcValue(Number(usdcVal.uiAmountString)) : "0"
|
|
378
378
|
};
|
|
379
379
|
}
|
|
380
380
|
function balanceLine(usdc, native, nativeSymbol) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "x402-proxy",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.1",
|
|
4
4
|
"description": "curl for x402 paid APIs. Auto-pays any endpoint on Base, Solana, and Tempo. Also works as an OpenClaw plugin.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -27,21 +27,22 @@
|
|
|
27
27
|
},
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"@clack/prompts": "^1.1.0",
|
|
30
|
+
"@getmcp/generators": "^0.10.1",
|
|
30
31
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
31
32
|
"@noble/curves": "^2.0.1",
|
|
32
33
|
"@noble/hashes": "^2.0.1",
|
|
33
34
|
"@scure/base": "^2.0.0",
|
|
34
35
|
"@scure/bip32": "^2.0.1",
|
|
35
36
|
"@scure/bip39": "^2.0.1",
|
|
36
|
-
"@solana/kit": "^6.0.0",
|
|
37
37
|
"@sinclair/typebox": "^0.34.48",
|
|
38
|
+
"@solana/kit": "^6.0.0",
|
|
38
39
|
"@stricli/core": "^1.2.6",
|
|
39
40
|
"@x402/evm": "^2.6.0",
|
|
40
41
|
"@x402/fetch": "^2.6.0",
|
|
41
42
|
"@x402/mcp": "^2.6.0",
|
|
42
|
-
"mppx": "^0.4.9",
|
|
43
43
|
"@x402/svm": "^2.6.0",
|
|
44
44
|
"ethers": "^6.0.0",
|
|
45
|
+
"mppx": "^0.4.9",
|
|
45
46
|
"picocolors": "^1.1.1",
|
|
46
47
|
"viem": "^2.0.0",
|
|
47
48
|
"yaml": "^2.8.2"
|
package/skills/SKILL.md
CHANGED
|
@@ -42,6 +42,7 @@ npx x402-proxy https://api.example.com/data > response.json
|
|
|
42
42
|
```
|
|
43
43
|
x402-proxy <url> # paid HTTP request (default)
|
|
44
44
|
x402-proxy mcp <url> # MCP stdio proxy for AI agents
|
|
45
|
+
x402-proxy mcp add <name> <url> # install MCP server into AI client
|
|
45
46
|
x402-proxy setup # wallet onboarding wizard
|
|
46
47
|
x402-proxy setup --force # re-run setup (overwrite existing wallet)
|
|
47
48
|
x402-proxy status # config + wallet + daily spend summary
|
|
@@ -70,23 +71,39 @@ x402-proxy wallet export-key mnemonic # bare mnemonic to stdout
|
|
|
70
71
|
|
|
71
72
|
## MCP proxy for AI agents
|
|
72
73
|
|
|
73
|
-
|
|
74
|
+
Quick setup (auto-detects installed AI clients):
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
x402-proxy mcp add surf https://surf.cascade.fyi/mcp
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or drop into your client config manually:
|
|
74
81
|
|
|
75
82
|
```json
|
|
76
83
|
{
|
|
77
84
|
"mcpServers": {
|
|
78
|
-
"
|
|
85
|
+
"surf": {
|
|
79
86
|
"command": "npx",
|
|
80
|
-
"args": ["x402-proxy", "mcp", "https://
|
|
81
|
-
"env": {
|
|
82
|
-
"X402_PROXY_WALLET_MNEMONIC": "your 24 words here"
|
|
83
|
-
}
|
|
87
|
+
"args": ["-y", "x402-proxy", "mcp", "https://surf.cascade.fyi/mcp"]
|
|
84
88
|
}
|
|
85
89
|
}
|
|
86
90
|
}
|
|
87
91
|
```
|
|
88
92
|
|
|
89
|
-
|
|
93
|
+
For OpenClaw:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
openclaw mcp set surf '{"command":"npx","args":["-y","x402-proxy","mcp","https://surf.cascade.fyi/mcp"]}'
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
The wallet is auto-generated on first run and stored at `~/.config/x402-proxy/wallet.json`. No env vars needed. The proxy intercepts 402 responses, pays automatically, forwards the result. Supports StreamableHTTP and SSE.
|
|
100
|
+
|
|
101
|
+
For non-interactive setup (e.g. automated provisioning):
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
npx x402-proxy setup --non-interactive
|
|
105
|
+
# outputs: {"evm":"0x...","solana":"..."}
|
|
106
|
+
```
|
|
90
107
|
|
|
91
108
|
## Wallet & env vars
|
|
92
109
|
|
package/dist/setup-CH4woul8.js
DELETED