402-mcp 4.2.1 → 4.3.0

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 (82) hide show
  1. package/README.md +60 -22
  2. package/build/config.d.ts +12 -1
  3. package/build/config.js +53 -12
  4. package/build/config.js.map +1 -1
  5. package/build/fetch/resilient-fetch.d.ts +7 -2
  6. package/build/fetch/resilient-fetch.js +32 -10
  7. package/build/fetch/resilient-fetch.js.map +1 -1
  8. package/build/fetch/socks-proxy.d.ts +25 -0
  9. package/build/fetch/socks-proxy.js +41 -0
  10. package/build/fetch/socks-proxy.js.map +1 -0
  11. package/build/fetch/ssrf-guard.d.ts +10 -0
  12. package/build/fetch/ssrf-guard.js +17 -1
  13. package/build/fetch/ssrf-guard.js.map +1 -1
  14. package/build/fetch/transport.d.ts +1 -0
  15. package/build/fetch/transport.js +37 -14
  16. package/build/fetch/transport.js.map +1 -1
  17. package/build/http-security.d.ts +13 -0
  18. package/build/http-security.js +38 -0
  19. package/build/http-security.js.map +1 -0
  20. package/build/index.js +186 -120
  21. package/build/index.js.map +1 -1
  22. package/build/l402/bolt11.js +3 -2
  23. package/build/l402/bolt11.js.map +1 -1
  24. package/build/spend-tracker.d.ts +31 -4
  25. package/build/spend-tracker.js +102 -17
  26. package/build/spend-tracker.js.map +1 -1
  27. package/build/store/cashu-tokens.d.ts +19 -0
  28. package/build/store/cashu-tokens.js +32 -0
  29. package/build/store/cashu-tokens.js.map +1 -1
  30. package/build/store/credentials.d.ts +5 -0
  31. package/build/store/credentials.js +1 -0
  32. package/build/store/credentials.js.map +1 -1
  33. package/build/store/pending-payments.d.ts +36 -0
  34. package/build/store/pending-payments.js +88 -0
  35. package/build/store/pending-payments.js.map +1 -0
  36. package/build/tools/buy-credits.d.ts +9 -0
  37. package/build/tools/buy-credits.js +40 -3
  38. package/build/tools/buy-credits.js.map +1 -1
  39. package/build/tools/config.d.ts +5 -0
  40. package/build/tools/config.js.map +1 -1
  41. package/build/tools/confirm.d.ts +12 -0
  42. package/build/tools/confirm.js +27 -0
  43. package/build/tools/confirm.js.map +1 -0
  44. package/build/tools/fetch-preview.js +9 -3
  45. package/build/tools/fetch-preview.js.map +1 -1
  46. package/build/tools/fetch.d.ts +7 -1
  47. package/build/tools/fetch.js +281 -140
  48. package/build/tools/fetch.js.map +1 -1
  49. package/build/tools/nostr-subscribe.js.map +1 -1
  50. package/build/tools/pay.d.ts +9 -0
  51. package/build/tools/pay.js +65 -8
  52. package/build/tools/pay.js.map +1 -1
  53. package/build/tools/reconcile.d.ts +33 -0
  54. package/build/tools/reconcile.js +111 -0
  55. package/build/tools/reconcile.js.map +1 -0
  56. package/build/tools/redeem-cashu.js +1 -1
  57. package/build/tools/redeem-cashu.js.map +1 -1
  58. package/build/tools/register-widgets.js +5 -5
  59. package/build/tools/register-widgets.js.map +1 -1
  60. package/build/tools/search.js +17 -3
  61. package/build/tools/search.js.map +1 -1
  62. package/build/tools/untrusted.d.ts +3 -0
  63. package/build/tools/untrusted.js +18 -0
  64. package/build/tools/untrusted.js.map +1 -0
  65. package/build/wallet/cashu.js +101 -21
  66. package/build/wallet/cashu.js.map +1 -1
  67. package/build/wallet/lnurlcash.js +25 -7
  68. package/build/wallet/lnurlcash.js.map +1 -1
  69. package/build/wallet/nwc.js +51 -3
  70. package/build/wallet/nwc.js.map +1 -1
  71. package/build/wallet/types.d.ts +17 -0
  72. package/build/x402/parse.d.ts +15 -3
  73. package/build/x402/parse.js +23 -9
  74. package/build/x402/parse.js.map +1 -1
  75. package/build/x402/payment.js +11 -6
  76. package/build/x402/payment.js.map +1 -1
  77. package/llms-full.txt +73 -34
  78. package/llms.txt +52 -24
  79. package/package.json +6 -5
  80. package/src/widgets/dist/payment-confirmation.html +28 -28
  81. package/src/widgets/dist/service-directory.html +39 -30
  82. package/src/widgets/dist/wallet-dashboard.html +28 -28
package/README.md CHANGED
@@ -9,7 +9,7 @@
9
9
  [![Nostr](https://img.shields.io/badge/Nostr-Zap%20me-purple)](https://primal.net/p/npub1mgvlrnf5hm9yf0n5mf9nqmvarhvxkc6remu5ec3vf8r0txqkuk7su0e7q2)
10
10
  [![GitHub Sponsors](https://img.shields.io/github/sponsors/TheCryptoDonkey?logo=githubsponsors&color=ea4aaa&label=Sponsor)](https://github.com/sponsors/TheCryptoDonkey)
11
11
 
12
- L402 + x402 client MCP that gives AI agents economic agency. Discover, pay for, and consume any payment-gated API — no human registration, no API keys, no middlemen.
12
+ L402 client MCP that gives AI agents economic agency. Discover, pay for, and consume Lightning and ecash payment-gated APIs within limits you set: no human registration, no API keys, no middlemen.
13
13
 
14
14
  - **Discover** paid APIs on Nostr — no URLs needed upfront
15
15
  - **Auto-pay** with Lightning (NWC), Cashu ecash, LNURLcash bearer notes, or human QR fallback
@@ -52,12 +52,12 @@ graph LR
52
52
  **Example session:**
53
53
 
54
54
  ```
55
- Agent: "I need routing data from routing.trotters.cc"
55
+ Agent: "I need routing data from routing.example.com"
56
56
 
57
57
  1. l402-config()
58
58
  -> nwcConfigured: true, maxAutoPaySats: 1000
59
59
 
60
- 2. l402-discover("https://routing.trotters.cc/api/route")
60
+ 2. l402-discover("https://routing.example.com/api/route")
61
61
  -> 10 sats/request, toll-booth detected, tiers available
62
62
 
63
63
  3. Agent reasons: "I need ~20 requests. The 500-sat tier
@@ -66,7 +66,7 @@ Agent: "I need routing data from routing.trotters.cc"
66
66
  4. l402-buy-credits(url, amountSats=500)
67
67
  -> Paid 500 sats, received 555 credits
68
68
 
69
- 5. l402-fetch("https://routing.trotters.cc/api/route?from=...&to=...")
69
+ 5. l402-fetch("https://routing.example.com/api/route?from=...&to=...")
70
70
  -> 200 OK, route data, 545 credits remaining
71
71
  ```
72
72
 
@@ -79,25 +79,39 @@ For detailed architecture and payment flow diagrams, see [docs/architecture.md](
79
79
  | `NWC_URI_FILE` | - | Path to a private `0600` file containing the NWC bearer URI |
80
80
  | `CASHU_TOKENS` | - | Path to Cashu token store file |
81
81
  | `LNURLCASH_NOTES` | - | Path to LNURLcash bearer note store file (LUD-25) |
82
- | `MAX_AUTO_PAY_SATS` | 1000 | Safety cap; payments above this require human confirmation |
82
+ | `MAX_AUTO_PAY_SATS` | 1000 | Most a single automatic payment may cost. Anything dearer is not paid; the challenge goes back to the agent |
83
+ | `MAX_SPEND_PER_MINUTE_SATS` | 10000 | Automatic spend allowed in any rolling 60 seconds. `0` blocks all auto-pay |
84
+ | `MAX_SPEND_PER_DAY_SATS` | 5000 | Automatic spend allowed in any rolling 24 hours, kept in `~/.402-mcp/spend-ledger.json` so a restart does not reset it. `0` blocks all auto-pay |
83
85
  | `CREDENTIAL_STORE` | `~/.402-mcp/credentials.json` | Persistent macaroon/credential storage |
84
86
  | `TRANSPORT` | `stdio` | Transport mode: `stdio` or `http` |
85
87
  | `PORT` | 3402 | HTTP server port (when `TRANSPORT=http`) |
88
+ | `BIND_ADDRESS` | `127.0.0.1` | HTTP bind address |
89
+ | `HTTP_AUTH_TOKEN_FILE` | - | Private `0600` file holding the bearer token HTTP clients must send. Required when `TRANSPORT=http` |
90
+ | `HTTP_ALLOWED_HOSTS` | - | Extra `Host` header values the HTTP transport accepts (comma-separated), such as a reverse proxy's name |
86
91
  | `TRANSPORT_PREFERENCE` | `onion,hns,https,http` | Preferred transport order for multi-URL services (comma-separated) |
87
- | `TOR_PROXY` | - | SOCKS5 proxy for `.onion` addresses (e.g. `socks5h://127.0.0.1:9050`) |
88
- | `SOCKS_PROXY` | - | Generic SOCKS5 proxy for all requests when set |
89
- | `HNS_GATEWAY_URL` | - | HTTP gateway for Handshake (`.hns`) domains (e.g. `https://hns.to`) |
92
+ | `TOR_PROXY` | - | SOCKS5 proxy for `.onion` addresses only (e.g. `socks5h://127.0.0.1:9050`) |
93
+ | `SOCKS_PROXY` | - | SOCKS5 proxy for every paid-API request (e.g. Tor at `socks5h://127.0.0.1:9050`). Set this or `TOR_PROXY`, not both |
94
+ | `HNS_GATEWAY_URL` | `https://query.hdns.io/` | DNS-over-HTTPS resolver used for Handshake names. Any host name that ordinary DNS cannot find is looked up here |
90
95
 
91
96
  ### Transport selection and fallback
92
97
 
93
98
  When a kind 31402 event advertises multiple URLs (one per transport), 402-mcp selects the best one based on your configuration:
94
99
 
95
- 1. **Preference first** — if `TRANSPORT_PREFERENCE=tor` and a `.onion` URL is available, it is tried first.
96
- 2. **Availability fallback** — if the preferred transport is unreachable (proxy not configured, timeout), the client falls back to the next URL in the list.
97
- 3. **Clearnet default** — if no preference is set, clearnet URLs are tried before `.onion` or HNS entries.
100
+ 1. **Preference first**: URLs are tried in `TRANSPORT_PREFERENCE` order, `onion,hns,https,http` by default. Use `onion`, `hns`, `https` and `http` as the values. A URL counts as `hns` when its TLD is `.hns`. One whose TLD is merely unfamiliar (`.pub`, `.fyi`) is more likely an ICANN name, so it is tried just after `https`.
101
+ 2. **Capability filter**: `.onion` URLs are skipped unless `TOR_PROXY` or `SOCKS_PROXY` is set, so without a proxy the default order starts at HNS and clearnet.
102
+ 3. **Availability fallback**: if a transport is unreachable (connection refused, timeout), the next URL is tried.
98
103
 
99
104
  Services can announce multiple endpoints for the **same service** (same pricing, same macaroon key) on different transports. This is purely for censorship resistance; you do not need to re-authenticate when switching transports. To reach Tor or HNS endpoints you must configure the corresponding proxy/gateway env vars above.
100
105
 
106
+ ### Tor and SOCKS5
107
+
108
+ - **`TOR_PROXY`** sends `.onion` requests through the proxy. Everything else connects directly.
109
+ - **`SOCKS_PROXY`** sends every request to a paid API through the proxy, including redirects. Host names are resolved by the proxy, never by this machine, so a Tor proxy hides both your IP and the names you look up. The SSRF guard still refuses private IP literals and local names such as `localhost`; it cannot see what a name resolves to on the far side, which Tor exits refuse for private ranges anyway.
110
+
111
+ Neither setting covers wallet or discovery traffic: NWC relays, Cashu and LNURLcash mints, and the Nostr relays `l402-search` queries still connect directly. Handshake lookups are switched off under `SOCKS_PROXY`, because the DNS-over-HTTPS query would go around the proxy.
112
+
113
+ SOCKS5 support comes from undici's `Socks5ProxyAgent`, which Node marks experimental; expect one `ExperimentalWarning` on stderr when a proxy is configured.
114
+
101
115
  ## Tools
102
116
 
103
117
  ### Core L402 (any server)
@@ -106,13 +120,24 @@ Services can announce multiple endpoints for the **same service** (same pricing,
106
120
  |------|-------------|
107
121
  | `l402-config` | Introspect payment capabilities (wallets, limits, credential count) |
108
122
  | `l402-discover` | Probe an endpoint to discover pricing without paying |
109
- | `l402-fetch` | HTTP request with L402 support; auto-pays if within budget |
110
- | `l402-pay` | Pay a specific invoice (NWC, Cashu, or human-in-the-loop) |
123
+ | `l402-fetch-preview` | Show what an endpoint costs without paying; drives the payment confirmation widget |
124
+ | `l402-fetch` | HTTP request that pays a 402 challenge when `autoPay` is set and the price is within the limits |
125
+ | `l402-pay` | Pay a challenge returned by `l402-fetch` or `l402-discover`, by its payment hash. Any other invoice needs the human's approval |
126
+ | `l402-reconcile` | List or resolve payments whose outcome is unknown; auto-pay to that service is paused until they are resolved |
111
127
  | `l402-credentials` | List stored credentials and cached balances |
112
128
  | `l402-balance` | Check cached credit balance for a server |
113
129
  | `l402-search` | Discover L402 services on Nostr relays (kind 31402 announcements) |
114
130
  | `l402-store-token` | Store an L402 token obtained from a payment page |
115
131
 
132
+ ### Widgets (MCP Apps hosts)
133
+
134
+ | Tool | Description |
135
+ |------|-------------|
136
+ | `l402-service-directory` | Interactive, searchable directory of services found by `l402-search` |
137
+ | `l402-wallet-dashboard` | Interactive view of wallet status, limits and stored credentials |
138
+
139
+ `l402-fetch-preview` also has a payment confirmation widget.
140
+
116
141
  ### toll-booth extensions
117
142
 
118
143
  | Tool | Description |
@@ -131,7 +156,7 @@ Four payer methods, tried in priority order:
131
156
 
132
157
  The agent can override the method per-call, or you can configure only the methods you want.
133
158
 
134
- `l402-fetch` handles five HTTP 402 challenge variants transparently:
159
+ `l402-fetch` handles four HTTP 402 challenge variants, plus an experimental x402 format:
135
160
 
136
161
  | Protocol | Challenge header | Payment |
137
162
  |----------|-----------------|---------|
@@ -139,7 +164,7 @@ The agent can override the method per-call, or you can configure only the method
139
164
  | **IETF Payment** (`draft-ryan-httpauth-payment-01`) | `WWW-Authenticate: Payment` | Lightning invoice via wallet stack |
140
165
  | **LNURLcash** (LUD-25) | `X-LNURLcash: lnurlcashreq1…` | Bearer note handed over directly (requires a note store) |
141
166
  | **xCashu** (NUT-18) | `X-Cashu: creqA…` | Ecash token sent directly (requires Cashu wallet) |
142
- | **x402** | `X-Payment-Required: x402` | On-chain EVM transfer; surfaced to human with EIP-681 deeplink |
167
+ | **x402** (experimental, custom format) | `X-Payment-Required: x402` + JSON body | A custom format, not the x402 specification (whose servers send a base64 `PAYMENT-REQUIRED` header), so real x402 services are not supported. Payment details are shown to the human, who pays from their own wallet |
143
168
 
144
169
  An LNURLcash challenge is tried first. A bearer note is already money in hand,
145
170
  so paying one costs no Lightning hop and no swap at the mint: the note goes
@@ -147,13 +172,26 @@ straight into the retry header and the server settles it. When the price does
147
172
  not match a note exactly, one is split at the mint and the change stays in the
148
173
  store. If no note covers it, the other rails are tried as usual.
149
174
 
150
- ## Safety
175
+ ## Spending limits
176
+
177
+ 402-mcp checks every automatic payment against these, and the agent can read them with `l402-config`:
151
178
 
152
- `MAX_AUTO_PAY_SATS` caps any single autonomous payment. Above this limit, the agent must ask the human for approval. The agent can read this limit via `l402-config` and factor it into purchasing decisions.
179
+ - `MAX_AUTO_PAY_SATS` caps each payment. A dearer challenge is returned to the agent unpaid.
180
+ - `maxCostSats` on `l402-fetch` lowers that cap for one call, so the price shown by `l402-fetch-preview` is binding. It can never raise it.
181
+ - `MAX_SPEND_PER_MINUTE_SATS` and `MAX_SPEND_PER_DAY_SATS` cap total automatic spend over rolling windows. The daily window is persisted, so restarting the server does not reset it. `0` in either blocks auto-pay entirely.
182
+ - A payment whose outcome is unknown pauses auto-pay to that service until `l402-reconcile` resolves it, so the same thing is not bought twice.
183
+
184
+ **The real hard limit is the budget on your NWC connection.** Everything above is enforced in software by this process, on the machine it runs on. Most NWC wallets let you set a spending budget when you create the connection; set one, because that is the limit a bug or a misbehaving agent cannot raise. For Cashu and LNURLcash, the hard limit is what you put in the token or note store.
153
185
 
154
186
  ## Privacy
155
187
 
156
- 402-mcp stores credentials locally on your machine only (`~/.402-mcp/credentials.json`, encrypted at rest). No data is sent to any third party. No accounts, no tracking, no analytics. Payments use Lightning or Cashu — pseudonymous by design.
188
+ 402-mcp stores credentials locally on your machine only (`~/.402-mcp/credentials.json`, encrypted at rest). There are no accounts, no tracking and no analytics, and 402-mcp has no server of its own. It does talk to parties other than the APIs you call:
189
+
190
+ - **Nostr relays.** `l402-search` subscribes to public relays (by default relay.damus.io, relay.primal.net and nos.lol) for service announcements, sending any topic or payment-method filter you give it. The query text itself is matched locally.
191
+ - **A Handshake resolver.** When ordinary DNS cannot find a host name, it is looked up at `HNS_GATEWAY_URL` (`https://query.hdns.io/` by default), which therefore sees that name. This is off under `SOCKS_PROXY`.
192
+ - **Your wallet's services.** NWC relays, Cashu mints and LNURLcash mints see the payments you make through them.
193
+
194
+ Payments use Lightning or ecash, which are pseudonymous rather than anonymous.
157
195
 
158
196
  ## Ecosystem
159
197
 
@@ -163,20 +201,20 @@ Browse live L402 services at [402.pub](https://402.pub) — the decentralised ma
163
201
  |---------|------|
164
202
  | [toll-booth](https://github.com/forgesworn/toll-booth) | Payment-backend agnostic HTTP 402 middleware |
165
203
  | [satgate](https://github.com/forgesworn/satgate) | Pay-per-token AI inference proxy (built on toll-booth) |
166
- | **[402-mcp](https://github.com/forgesworn/402-mcp)** | **MCP client — AI agents discover, pay, and consume L402 + x402 APIs** |
204
+ | **[402-mcp](https://github.com/forgesworn/402-mcp)** | **MCP client: AI agents discover, pay for and consume L402 APIs** |
167
205
  | [402-announce](https://github.com/forgesworn/402-announce) | Publish L402 services on Nostr for decentralised discovery |
168
206
 
169
- 402-mcp is the **wallet-provider agnostic** alternative to Lightning Labs' [lightning-agent-tools](https://github.com/lightninglabs/lightning-agent-tools) and Coinbase's x402 — no Lightning node required, multiple wallets, encrypted credentials.
207
+ 402-mcp is the **wallet-provider agnostic** alternative to Lightning Labs' [lightning-agent-tools](https://github.com/lightninglabs/lightning-agent-tools): no Lightning node required, multiple wallets, encrypted credentials.
170
208
 
171
209
  <details>
172
210
  <summary>Full comparison</summary>
173
211
 
174
212
  | | 402-mcp | Lightning Labs agent tools |
175
213
  |---|---|---|
176
- | **Payer methods** | NWC + Cashu + human fallback | Lightning only |
214
+ | **Payer methods** | NWC + Cashu + LNURLcash + human fallback | Lightning only |
177
215
  | **Node required?** | No — connects to any NWC wallet | Yes — runs LND |
178
216
  | **Server compatibility** | Any L402 server | Aperture-focused |
179
- | **Spend safety** | Per-payment cap + rolling 60s window | Per-call max-cost |
217
+ | **Spend safety** | Per-payment cap, per-call max cost, rolling 60s and persisted 24h windows | Per-call max-cost |
180
218
  | **Credential storage** | Encrypted at rest (AES-256-GCM) | File permissions |
181
219
  | **Privacy** | No PII, SSRF protection, error sanitisation | Standard |
182
220
 
package/build/config.d.ts CHANGED
@@ -1,9 +1,12 @@
1
+ import { type ProxyScope } from './fetch/socks-proxy.js';
1
2
  export interface L402Config {
2
3
  nwcUri: string | undefined;
3
4
  cashuTokensPath: string | undefined;
4
5
  lnurlcashNotesPath: string | undefined;
5
6
  maxAutoPaySats: number;
6
7
  maxSpendPerMinuteSats: number;
8
+ /** Auto-pay cap over any rolling 24 hours, persisted across restarts. 0 blocks auto-pay. */
9
+ maxSpendPerDaySats: number;
7
10
  credentialStorePath: string;
8
11
  transport: 'stdio' | 'http';
9
12
  port: number;
@@ -16,8 +19,16 @@ export interface L402Config {
16
19
  corsOrigin: string | false;
17
20
  bindAddress: string;
18
21
  transportPreference: string[];
19
- torProxy: string | undefined;
22
+ /** SOCKS5 proxy: `onion` scope from TOR_PROXY, `all` scope from SOCKS_PROXY */
23
+ proxy: {
24
+ url: string;
25
+ scope: ProxyScope;
26
+ } | undefined;
20
27
  hnsGatewayUrl: string;
28
+ /** Bearer token the HTTP transport requires. Always set when transport is http. */
29
+ httpAuthToken: string | undefined;
30
+ /** Extra Host header values the HTTP transport accepts (HTTP_ALLOWED_HOSTS). */
31
+ httpAllowedHosts: string[];
21
32
  }
22
33
  /** Loads and validates configuration from environment variables, applying defaults. */
23
34
  export declare function loadConfig(): L402Config;
package/build/config.js CHANGED
@@ -2,6 +2,7 @@ import { resolve } from 'node:path';
2
2
  import { homedir } from 'node:os';
3
3
  import { closeSync, fstatSync, openSync, readSync } from 'node:fs';
4
4
  import { inspectNwcConnection } from '@forgesworn/nwc-kit';
5
+ import { parseSocksProxyUrl } from './fetch/socks-proxy.js';
5
6
  function assertNonNegativeInt(name, value) {
6
7
  if (!Number.isFinite(value) || value < 0 || !Number.isInteger(value)) {
7
8
  throw new Error(`${name} must be a positive integer or zero; got ${value}`);
@@ -17,44 +18,58 @@ function assertRange(name, value, min, max) {
17
18
  throw new Error(`${name} must be an integer between ${min} and ${max}; got ${value}`);
18
19
  }
19
20
  }
20
- function readNwcUriFile(filePath) {
21
+ /**
22
+ * Reads a bearer secret from a private file: a regular file, owner-only on
23
+ * POSIX, bounded in size, read in full exactly once.
24
+ */
25
+ function readSecretFile(name, filePath) {
21
26
  const resolvedPath = resolve(filePath);
22
27
  const descriptor = openSync(resolvedPath, 'r');
23
28
  let bytes;
24
29
  try {
25
30
  const stats = fstatSync(descriptor);
26
31
  if (!stats.isFile() || stats.size === 0 || stats.size > 8192) {
27
- throw new Error('NWC_URI_FILE must be a non-empty regular file no larger than 8192 bytes');
32
+ throw new Error(`${name} must be a non-empty regular file no larger than 8192 bytes`);
28
33
  }
29
34
  if (process.platform !== 'win32' && (stats.mode & 0o077) !== 0) {
30
- throw new Error('NWC_URI_FILE permissions are too broad; run chmod 600 on the file');
35
+ throw new Error(`${name} permissions are too broad; run chmod 600 on the file`);
31
36
  }
32
37
  bytes = Buffer.allocUnsafe(stats.size);
33
38
  let offset = 0;
34
39
  while (offset < bytes.length) {
35
40
  const count = readSync(descriptor, bytes, offset, bytes.length - offset, null);
36
41
  if (count === 0)
37
- throw new Error('NWC_URI_FILE changed while it was being read');
42
+ throw new Error(`${name} changed while it was being read`);
38
43
  offset += count;
39
44
  }
40
45
  const extra = Buffer.allocUnsafe(1);
41
46
  try {
42
47
  if (readSync(descriptor, extra, 0, 1, null) !== 0) {
43
- throw new Error('NWC_URI_FILE changed while it was being read');
48
+ throw new Error(`${name} changed while it was being read`);
44
49
  }
45
50
  }
46
51
  finally {
47
52
  extra.fill(0);
48
53
  }
49
- const uri = bytes.toString('utf-8').trim();
50
- inspectNwcConnection(uri);
51
- return uri;
54
+ return bytes.toString('utf-8').trim();
52
55
  }
53
56
  finally {
54
57
  bytes?.fill(0);
55
58
  closeSync(descriptor);
56
59
  }
57
60
  }
61
+ function readNwcUriFile(filePath) {
62
+ const uri = readSecretFile('NWC_URI_FILE', filePath);
63
+ inspectNwcConnection(uri);
64
+ return uri;
65
+ }
66
+ function readHttpAuthTokenFile(filePath) {
67
+ const token = readSecretFile('HTTP_AUTH_TOKEN_FILE', filePath);
68
+ if (token.length < 32 || /\s/.test(token)) {
69
+ throw new Error('HTTP_AUTH_TOKEN_FILE must hold a single token of at least 32 characters, e.g. from: openssl rand -hex 32');
70
+ }
71
+ return token;
72
+ }
58
73
  /** Loads and validates configuration from environment variables, applying defaults. */
59
74
  export function loadConfig() {
60
75
  const defaultCredentialStore = resolve(homedir(), '.402-mcp', 'credentials.json');
@@ -70,11 +85,33 @@ export function loadConfig() {
70
85
  if (transport !== 'stdio' && transport !== 'http') {
71
86
  throw new Error(`TRANSPORT must be 'stdio' or 'http'; got '${transport}'`);
72
87
  }
88
+ const rawHttpToken = process.env.HTTP_AUTH_TOKEN;
89
+ const httpTokenFile = process.env.HTTP_AUTH_TOKEN_FILE;
90
+ delete process.env.HTTP_AUTH_TOKEN;
91
+ delete process.env.HTTP_AUTH_TOKEN_FILE;
92
+ if (rawHttpToken !== undefined) {
93
+ throw new Error('HTTP_AUTH_TOKEN is disabled because bearer secrets must not be stored in environment variables; use HTTP_AUTH_TOKEN_FILE');
94
+ }
95
+ // The HTTP transport can spend from the wallet, so it never runs open.
96
+ if (transport === 'http' && !httpTokenFile) {
97
+ throw new Error('TRANSPORT=http requires HTTP_AUTH_TOKEN_FILE: a private 0600 file holding the bearer token clients must send');
98
+ }
99
+ const httpAuthToken = transport === 'http' && httpTokenFile ? readHttpAuthTokenFile(httpTokenFile) : undefined;
100
+ const httpAllowedHosts = (process.env.HTTP_ALLOWED_HOSTS ?? '').split(',').map(h => h.trim()).filter(Boolean);
73
101
  const transportPref = process.env.TRANSPORT_PREFERENCE;
74
102
  const transportPreference = transportPref
75
103
  ? transportPref.split(',').map(s => s.trim()).filter(Boolean)
76
104
  : ['onion', 'hns', 'https', 'http'];
77
- const torProxy = process.env.TOR_PROXY || process.env.SOCKS_PROXY || undefined;
105
+ const torProxy = process.env.TOR_PROXY || undefined;
106
+ const socksProxy = process.env.SOCKS_PROXY || undefined;
107
+ if (torProxy && socksProxy) {
108
+ throw new Error('Set TOR_PROXY (only .onion through the proxy) or SOCKS_PROXY (everything through the proxy), not both');
109
+ }
110
+ const proxy = socksProxy
111
+ ? { url: parseSocksProxyUrl('SOCKS_PROXY', socksProxy), scope: 'all' }
112
+ : torProxy
113
+ ? { url: parseSocksProxyUrl('TOR_PROXY', torProxy), scope: 'onion' }
114
+ : undefined;
78
115
  const hnsGatewayUrl = process.env.HNS_GATEWAY_URL || 'https://query.hdns.io/';
79
116
  const config = {
80
117
  nwcUri,
@@ -82,6 +119,7 @@ export function loadConfig() {
82
119
  lnurlcashNotesPath: process.env.LNURLCASH_NOTES,
83
120
  maxAutoPaySats: parseInt(process.env.MAX_AUTO_PAY_SATS ?? '1000', 10),
84
121
  maxSpendPerMinuteSats: parseInt(process.env.MAX_SPEND_PER_MINUTE_SATS ?? '10000', 10),
122
+ maxSpendPerDaySats: parseInt(process.env.MAX_SPEND_PER_DAY_SATS ?? '5000', 10),
85
123
  credentialStorePath: process.env.CREDENTIAL_STORE ?? defaultCredentialStore,
86
124
  transport,
87
125
  port: parseInt(process.env.PORT ?? '3402', 10),
@@ -94,11 +132,14 @@ export function loadConfig() {
94
132
  corsOrigin: process.env.CORS_ORIGIN || false,
95
133
  bindAddress: process.env.BIND_ADDRESS ?? '127.0.0.1',
96
134
  transportPreference,
97
- torProxy,
135
+ proxy,
98
136
  hnsGatewayUrl,
137
+ httpAuthToken,
138
+ httpAllowedHosts,
99
139
  };
100
140
  assertNonNegativeInt('MAX_AUTO_PAY_SATS', config.maxAutoPaySats);
101
141
  assertNonNegativeInt('MAX_SPEND_PER_MINUTE_SATS', config.maxSpendPerMinuteSats);
142
+ assertNonNegativeInt('MAX_SPEND_PER_DAY_SATS', config.maxSpendPerDaySats);
102
143
  assertRange('PORT', config.port, 1, 65535);
103
144
  assertPositiveInt('FETCH_TIMEOUT_MS', config.fetchTimeoutMs);
104
145
  assertNonNegativeInt('FETCH_MAX_RETRIES', config.fetchMaxRetries);
@@ -127,9 +168,9 @@ export function loadConfig() {
127
168
  throw new Error(`LNURLCASH_NOTES must be within the home directory (got: ${config.lnurlcashNotesPath})`);
128
169
  }
129
170
  }
130
- // Warn if BIND_ADDRESS is non-loopback (server will be network-accessible without auth)
171
+ // Warn if BIND_ADDRESS is non-loopback: the bearer token then crosses the network
131
172
  if (config.transport === 'http' && config.bindAddress !== '127.0.0.1' && config.bindAddress !== '::1') {
132
- console.error(`Warning: BIND_ADDRESS is ${config.bindAddress} — server will be network-accessible without authentication. Use a reverse proxy with TLS and auth for production.`);
173
+ console.error(`Warning: BIND_ADDRESS is ${config.bindAddress}, so the server is reachable from the network and its bearer token travels in cleartext. Put it behind a TLS reverse proxy and list the proxy's host in HTTP_ALLOWED_HOSTS.`);
133
174
  }
134
175
  // Warn if CORS allows all origins (potential CSRF risk on HTTP transport)
135
176
  if (config.corsOrigin === '*') {
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,5 @@
1
1
  import { type ValidateUrlOptions } from './ssrf-guard.js';
2
+ import { type ProxyRoute } from './socks-proxy.js';
2
3
  export interface ResilientFetchOptions {
3
4
  timeoutMs?: number;
4
5
  retries?: number;
@@ -14,8 +15,12 @@ export interface ResilientFetchConfig {
14
15
  ssrfAllowPrivate?: boolean;
15
16
  /** HNS (Handshake) resolver — called on NXDOMAIN to resolve alternative TLDs */
16
17
  resolveHns?: ValidateUrlOptions['resolveHns'];
17
- /** Whether a Tor SOCKS proxy is configured — enables .onion URL routing */
18
- hasTorProxy?: boolean;
18
+ /**
19
+ * SOCKS5 route. `.onion` hosts (and, with scope `all`, every host) are
20
+ * fetched through `proxy.fetchFn`; the rest use `fetchFn`. Without a
21
+ * route, `.onion` URLs are refused rather than leaked to the local resolver.
22
+ */
23
+ proxy?: ProxyRoute;
19
24
  }
20
25
  /**
21
26
  * Create a resilient fetch function with SSRF protection, timeout, and retry.
@@ -1,5 +1,11 @@
1
1
  import { validateUrl } from './ssrf-guard.js';
2
+ import { usesProxy } from './socks-proxy.js';
2
3
  import { SsrfError, TimeoutError, RetryExhaustedError, DowngradeError, ResponseTooLargeError, TransportUnavailableError } from './errors.js';
4
+ /** Request headers that may follow a redirect to another origin. */
5
+ const CROSS_ORIGIN_SAFE_HEADERS = new Set([
6
+ 'accept', 'accept-language', 'content-language', 'content-type',
7
+ 'user-agent', 'cache-control', 'pragma',
8
+ ]);
3
9
  const MAX_REDIRECTS = 5;
4
10
  const DEFAULT_TIMEOUT_MS = 30_000;
5
11
  const DEFAULT_RETRIES = 2;
@@ -57,9 +63,12 @@ export function createResilientFetch(fetchFn, config = {}) {
57
63
  const globalBackoff = config.backoffMs ?? DEFAULT_BACKOFF_MS;
58
64
  const globalMaxResponseBytes = config.maxResponseBytes ?? 0;
59
65
  const allowPrivate = config.ssrfAllowPrivate ?? false;
66
+ const proxy = config.proxy;
60
67
  const ssrfOptions = {
61
- resolveHns: config.resolveHns,
62
- hasTorProxy: config.hasTorProxy ?? false,
68
+ // Resolving an HNS name would go around a proxy that carries everything.
69
+ resolveHns: proxy?.scope === 'all' ? undefined : config.resolveHns,
70
+ hasTorProxy: proxy !== undefined,
71
+ remoteDns: proxy?.scope === 'all',
63
72
  };
64
73
  return async function resilientFetch(url, init, options) {
65
74
  const timeoutMs = options?.timeoutMs ?? globalTimeout;
@@ -79,7 +88,7 @@ export function createResilientFetch(fetchFn, config = {}) {
79
88
  await sleep(delay);
80
89
  }
81
90
  try {
82
- let response = await fetchWithTimeoutAndRedirects(fetchFn, urlStr, init, timeoutMs, allowPrivate, urlStr, resolved, ssrfOptions);
91
+ let response = await fetchWithTimeoutAndRedirects(fetchFn, urlStr, init, timeoutMs, allowPrivate, urlStr, resolved, ssrfOptions, proxy);
83
92
  // If retryable status and we have retries left, drain body and continue
84
93
  if (retryOn(response.status) && attempt < totalAttempts - 1) {
85
94
  try {
@@ -143,7 +152,7 @@ export function createResilientFetch(fetchFn, config = {}) {
143
152
  throw new RetryExhaustedError(totalAttempts, urlStr, lastError);
144
153
  };
145
154
  }
146
- async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allowPrivate, originalUrl, resolved, ssrfOptions = {}) {
155
+ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allowPrivate, originalUrl, resolved, ssrfOptions = {}, proxy) {
147
156
  let currentUrl = url;
148
157
  let currentInit = init ? { ...init } : {};
149
158
  let redirectCount = 0;
@@ -152,8 +161,15 @@ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allow
152
161
  // a malicious server from stalling each hop for the full timeout.
153
162
  const chainStart = Date.now();
154
163
  while (true) {
164
+ // Choose per hop: a redirect can move between clearnet and .onion.
165
+ // A proxied hop is never pinned: the proxy resolves the name, and
166
+ // rewriting it to a local lookup's IP would defeat the point.
167
+ const proxied = usesProxy(proxy, new URL(currentUrl).hostname);
168
+ const hopFetch = proxied ? proxy.fetchFn : fetchFn;
155
169
  // Pin HTTP URLs to the validated IP to prevent DNS rebinding
156
- const { pinnedUrl, hostHeader } = pinUrlToResolvedIp(currentUrl, currentResolved);
170
+ const { pinnedUrl, hostHeader } = proxied
171
+ ? { pinnedUrl: currentUrl, hostHeader: undefined }
172
+ : pinUrlToResolvedIp(currentUrl, currentResolved);
157
173
  const elapsed = Date.now() - chainStart;
158
174
  const remainingMs = Math.max(0, timeoutMs - elapsed);
159
175
  if (remainingMs === 0) {
@@ -175,7 +191,7 @@ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allow
175
191
  }
176
192
  let response;
177
193
  try {
178
- response = await fetchFn(pinnedUrl, fetchInit);
194
+ response = await hopFetch(pinnedUrl, fetchInit);
179
195
  }
180
196
  catch (err) {
181
197
  clearTimeout(timeoutId);
@@ -204,13 +220,19 @@ async function fetchWithTimeoutAndRedirects(fetchFn, url, init, timeoutMs, allow
204
220
  }
205
221
  // SSRF check on redirect target; capture the resolved address for pinning
206
222
  currentResolved = await validateUrl(currentUrl, allowPrivate, ssrfOptions);
207
- // Strip Authorization header on cross-origin redirects to prevent credential leakage.
208
- // Per Fetch spec, credentials should not follow cross-origin redirects.
223
+ // On a cross-origin redirect keep only headers that carry no secret.
224
+ // Authorization is not the only one: X-Cashu and X-LNURLcash carry
225
+ // bearer money, and a caller may have supplied its own API key or cookie
226
+ // under any name. Per Fetch spec, credentials do not follow cross-origin
227
+ // redirects; neither does anything else we cannot vouch for.
209
228
  const redirectOrigin = new URL(currentUrl).origin;
210
229
  const originalOrigin = new URL(originalUrl).origin;
211
230
  if (redirectOrigin !== originalOrigin && currentInit.headers) {
212
- const headers = new Headers(currentInit.headers);
213
- headers.delete('Authorization');
231
+ const headers = new Headers();
232
+ for (const [name, value] of new Headers(currentInit.headers)) {
233
+ if (CROSS_ORIGIN_SAFE_HEADERS.has(name))
234
+ headers.set(name, value);
235
+ }
214
236
  currentInit = { ...currentInit, headers };
215
237
  }
216
238
  // 301/302/303 change POST to GET and drop body
@@ -1 +1 @@
1
- {"version":3,"file":"resilient-fetch.js","sourceRoot":"","sources":["../../src/fetch/resilient-fetch.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resilient-fetch.js","sourceRoot":"","sources":["../../src/fetch/resilient-fetch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Where outbound requests go through a SOCKS5 proxy.
3
+ *
4
+ * - `onion`: only `.onion` hosts use the proxy (TOR_PROXY).
5
+ * - `all`: every request uses the proxy (SOCKS_PROXY), and this process never
6
+ * resolves a target host name itself.
7
+ */
8
+ export type ProxyScope = 'onion' | 'all';
9
+ export interface ProxyRoute {
10
+ scope: ProxyScope;
11
+ fetchFn: typeof fetch;
12
+ }
13
+ /**
14
+ * Parse and normalise a SOCKS5 proxy URL from configuration.
15
+ *
16
+ * Accepts `socks5://`, `socks5h://` and `socks://`. All three mean the same
17
+ * thing here: host names are always sent to the proxy to resolve, never looked
18
+ * up locally, so `socks5h` needs no special handling. Anything else is refused
19
+ * at startup rather than silently sending traffic around the proxy.
20
+ */
21
+ export declare function parseSocksProxyUrl(name: string, raw: string): string;
22
+ /** A fetch that tunnels every request through the given SOCKS5 proxy. */
23
+ export declare function createSocksFetch(proxyUrl: string): typeof fetch;
24
+ /** Whether a request to this host goes through the proxy. */
25
+ export declare function usesProxy(route: ProxyRoute | undefined, hostname: string): boolean;
@@ -0,0 +1,41 @@
1
+ import { fetch as undiciFetch, Socks5ProxyAgent } from 'undici';
2
+ /**
3
+ * Parse and normalise a SOCKS5 proxy URL from configuration.
4
+ *
5
+ * Accepts `socks5://`, `socks5h://` and `socks://`. All three mean the same
6
+ * thing here: host names are always sent to the proxy to resolve, never looked
7
+ * up locally, so `socks5h` needs no special handling. Anything else is refused
8
+ * at startup rather than silently sending traffic around the proxy.
9
+ */
10
+ export function parseSocksProxyUrl(name, raw) {
11
+ let url;
12
+ try {
13
+ url = new URL(raw);
14
+ }
15
+ catch {
16
+ throw new Error(`${name} must be a SOCKS5 URL such as socks5h://127.0.0.1:9050; got an unparseable value`);
17
+ }
18
+ if (!['socks5:', 'socks5h:', 'socks:'].includes(url.protocol)) {
19
+ throw new Error(`${name} must use socks5://, socks5h:// or socks://; got ${url.protocol}//`);
20
+ }
21
+ if (!url.hostname || !url.port) {
22
+ throw new Error(`${name} must include a host and port, e.g. socks5h://127.0.0.1:9050`);
23
+ }
24
+ if (url.pathname.replace(/\/$/, '') || url.search || url.hash) {
25
+ throw new Error(`${name} must not include a path, query or fragment`);
26
+ }
27
+ const auth = url.username ? `${url.username}${url.password ? `:${url.password}` : ''}@` : '';
28
+ return `socks5://${auth}${url.host}`;
29
+ }
30
+ /** A fetch that tunnels every request through the given SOCKS5 proxy. */
31
+ export function createSocksFetch(proxyUrl) {
32
+ const dispatcher = new Socks5ProxyAgent(proxyUrl);
33
+ return ((input, init) => undiciFetch(input, { ...init, dispatcher }));
34
+ }
35
+ /** Whether a request to this host goes through the proxy. */
36
+ export function usesProxy(route, hostname) {
37
+ if (!route)
38
+ return false;
39
+ return route.scope === 'all' || hostname.toLowerCase().replace(/\.$/, '').endsWith('.onion');
40
+ }
41
+ //# sourceMappingURL=socks-proxy.js.map