@aifinpay/mcp 2.11.4 → 2.12.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/README.md CHANGED
@@ -4,61 +4,50 @@ AiFinPay MCP server for persistent agent identity, Agent Passport resolution,
4
4
  route discovery and non-signing settlement invoices. Canonical domain:
5
5
  **aifinpay.io**.
6
6
 
7
- Version **2.11.4** is prepared in this checkout, on the published agent 2.9.0
7
+ Version **2.12.1** is prepared in this checkout, on the published agent 2.9.0
8
8
  and canonical skill 2.10.2 (AiFinPay/skill 48285cf, published 2026-10-19). The separate canonical producer's final immutable
9
9
  source pin is a required handoff, not a moving-branch substitution.
10
10
  The published baseline checked2026-10-04 was MCP2.5.0. Package publication and
11
11
  real registry dependency/lock refresh remain release gates; a source-cohort
12
12
  build does not prove those steps. Owner-enabled v1.4 purchases with `payable_fetch` are
13
13
  released: on Polygon since 2.2.0, on Base (ETH or USDC) since 2.5.0; site-wide
14
- batches with `scope: "merchant"` since 2.4.1. Without payment configuration the server
15
- lists every tool, including `payable_fetch`, but signs nothing: `payable_fetch`
16
- and `payment_setup_status` answer with the setup checklist instead.
14
+ batches with `scope: "merchant"` since 2.4.1. Since 2.12.1 payments are on by
15
+ default: a persistent wallet created with `init` can pay with no payment env at
16
+ all, within a built-in ceiling of $5 per payment and $20 per 24 hours, and only
17
+ to merchants registered with AiFinPay. An ephemeral wallet signs nothing, and
18
+ an unfunded one has nothing to spend. The working limits are the owner's
19
+ dashboard Controls.
17
20
 
18
21
  ## First payment in five steps
19
22
 
20
- Each step is one command or one tool call. Signing happens only in step 5,
21
- and only once the owner has set every limit in step 4.
23
+ Nobody edits the MCP client config to turn payments on. Signing happens only in
24
+ step 5, only with a persistent, funded wallet, and never above the ceiling.
22
25
 
23
26
  1. **Read the price.** `GET` the resource. The `402` names the merchant
24
27
  (`merchant_id`), the price per request and the smallest batch (`$0.10` for
25
28
  200 standard requests).
26
29
  2. **Check the setup.** Call `payment_setup_status`. It returns the wallet
27
- (persistent or ephemeral), whether payments are enabled, which owner limits
28
- are set, the balance when the RPC answers, `funding` (what a persistent
29
- wallet needs, priced at today's rate) and `next_step`: the first thing
30
- still missing.
31
- 3. **Persistent wallet.** If `wallet.persistent` is false, run
32
- `npx @aifinpay/mcp init`. Without a terminal it prints one JSON document;
33
- copy its `env` (the passphrase is only there) into the `aifinpay` server
34
- entry of the MCP client config, reconnect the server, then call
35
- `agent_reload`. Never fund an ephemeral address.
36
- 4. **Fund and enable.** Tell the owner `addresses.evm` and the amount from
30
+ (persistent or ephemeral), the ceiling and each limit with its source
31
+ (`default` or the owner's `env`), the balance when the RPC answers,
32
+ `funding` (what to fund, priced at today's rate), the owner's dashboard
33
+ Controls in `dashboard`, and `next_step`: the first thing still missing.
34
+ 3. **Init.** If `wallet.persistent` is false, run `npx @aifinpay/mcp init`.
35
+ Without a terminal it prints one JSON document; copy its `env` (the
36
+ passphrase is only there) into the `aifinpay` server entry of the MCP client
37
+ config, then call `agent_reload` in the same connection. No restart: the
38
+ reload opens the payment journal for the new wallet. Never fund an
39
+ ephemeral address.
40
+ 4. **Fund and link.** Tell the owner `addresses.evm` and the amount from
37
41
  `payment_setup_status`'s `funding`: the smallest batch (`$0.10`) in POL at
38
- today's rate plus the gas cap (the SDK refuses before signing if the
39
- worst-case fee exceeds the cap). The rate moves — `$0.10` was 1.08 POL on
40
- 2026-10-19 — so never quote a remembered number; if `funding` carries a
41
- `rate_error` instead of an `amount`, ask the owner to fund "the batch price
42
- in POL at today's rate plus the gas cap" and name no number. When the owner
43
- confirms funding, they add the payment settings to the same `env` and
44
- restart the aifinpay MCP server in the client (`agent_reload` does not read
45
- env):
46
-
47
- ```json
48
- {
49
- "AIFINPAY_PAYMENTS_ENABLED": "1",
50
- "AIFINPAY_GATEWAY_ORIGINS": "https://dev.ratersapp.com",
51
- "AIFINPAY_GATEWAY_PATH_MODE": "direct",
52
- "AIFINPAY_MAX_USD": "5",
53
- "AIFINPAY_DAILY_USD": "20",
54
- "AIFINPAY_MAX_GAS_POL": "0.3"
55
- }
56
- ```
57
-
58
- The USD values are a ceiling the owner sets once, not the budget: the
59
- working limits live in the dashboard (see "Owner limits" below).
60
- `payment_setup_status` then reports `ready: true`.
61
-
42
+ today's rate plus the gas cap (0.3 POL by default; the SDK refuses before
43
+ signing if the worst-case fee exceeds it). The rate moves — `$0.10` was
44
+ 1.08 POL on 2026-10-19 — so never quote a remembered number; if `funding`
45
+ carries a `rate_error` instead of an `amount`, ask the owner to fund "the
46
+ batch price in POL at today's rate plus the gas cap" and name no number.
47
+ Offer the dashboard link too: the owner generates a one-time URL under
48
+ **My Agents → Claim via MCP** at https://dash.aifinpay.io and the agent
49
+ passes it to `agent_claim_self`; from then on the owner sets the working
50
+ limits in Controls.
62
51
  5. **Pay.** `payable_fetch({"url": "https://dev.ratersapp.com/api/agent/genres/list"})`
63
52
  buys the batch on Polygon (splitter v1.4) and returns the content and the
64
53
  receipt summary. Later requests reuse the batch.
@@ -67,40 +56,65 @@ Polygon and Base are served on v1.4 today; `settlement_routes` lists them
67
56
  first, with `live: true`. Its `legacy_v13` section describes the older
68
57
  splitter v1.3 routes, which `payable_fetch` does not use.
69
58
 
70
- ## Enable native paid GET requests
59
+ ## Optional payment overrides
71
60
 
72
- Use a persistent wallet created with public `npx @aifinpay/mcp init` or an
73
- existing configured identity. Keep its passphrase private. The owner adds these
74
- to the server's `env` (`init` prints the same block):
61
+ None of these is needed for a first payment, and each one only narrows what
62
+ the defaults allow. `init` prints the same reference block:
75
63
 
76
64
  ```json
77
65
  {
78
- "AIFINPAY_PAYMENTS_ENABLED": "1",
79
66
  "AIFINPAY_GATEWAY_ORIGINS": "https://merchant.example",
80
- "AIFINPAY_GATEWAY_PATH_MODE": "direct",
81
- "AIFINPAY_MAX_USD": "5",
82
- "AIFINPAY_DAILY_USD": "20",
83
67
  "AIFINPAY_MAX_GAS_POL": "0.3"
84
68
  }
85
69
  ```
86
70
 
87
- Limits are examples, not authorization. USD limits cover purchases; gas has its
88
- own POL cap. Origins are exact HTTPS origins authorized by the
89
- owner. `direct` uses the full path for self-hosted sites; `gateway` uses the
90
- merchant slug on the hosted gateway. Restart/reconnect the MCP process after
91
- changing its environment.
92
-
93
- ### Owner limits: a ceiling in env, the working limits in the dashboard
94
-
95
- `AIFINPAY_MAX_USD` and `AIFINPAY_DAILY_USD` are the ceiling the SDK requires
96
- before it signs with the owner's key: set them once, high enough that they do
97
- not need revisiting (the example `5` per payment and `20` per day is a ceiling,
98
- not a budget), and leave them. The day-to-day limits belong in the dashboard:
99
- once the agent is linked with `agent_claim_self`, the owner manages the
100
- per-payment cap, the daily cap, pause and the allowed sites under **Controls**
101
- at https://dash.aifinpay.io, and the backend enforces that policy on every
102
- `/v1/quote` and `/v1/pay` for the claimed agent — no env change, no server
103
- restart. The env ceiling still applies underneath; a payment has to pass both.
71
+ - `AIFINPAY_GATEWAY_ORIGINS`: exact HTTPS origins the agent may pay,
72
+ comma-separated, no wildcards. Unset, the agent pays only a merchant whose
73
+ site AiFinPay reports as DNS-verified, on that very site (or through the
74
+ AiFinPay hosted gateway): the payee comes from the backend-signed quote, never
75
+ from the 402, and is refused before anything is signed if its verified site is
76
+ not the host being fetched. Set, an unlisted origin is refused by name and
77
+ only the owner can add it; the list then decides.
78
+ - `AIFINPAY_MAX_GAS_POL`: worst-case network fee of one payment on Polygon,
79
+ checked before signing; default `0.3` POL. At ~280 gwei the worst case is
80
+ ~0.10 POL paying in POL and ~0.21 POL in USDC. Another chain needs
81
+ `AIFINPAY_MAX_GAS` in its own currency.
82
+ - `AIFINPAY_MAX_USD` / `AIFINPAY_DAILY_USD`: lower the built-in ceiling of $5
83
+ per payment / $20 per 24 hours. A higher value is refused at start with a
84
+ message, never silently clipped; raise nothing here, use the dashboard.
85
+ - `AIFINPAY_GATEWAY_PATH_MODE`: unset, inferred per URL (`gateway` for
86
+ `https://gateway.aifinpay.io`, by merchant slug; `direct`, the full path,
87
+ for any other site).
88
+ - `AIFINPAY_PAYMENTS_ENABLED=0`: payments off; the server stays read-only.
89
+
90
+ The env is read when the server starts; restart the aifinpay MCP server after
91
+ changing it (`agent_reload` reads only the keystore).
92
+
93
+ ### Owner limits: a built-in ceiling, the working limits in the dashboard
94
+
95
+ The server never signs more than $5 per payment or $20 over any 24 hours (its
96
+ local journal, checked under the operation lock before any broadcast). That
97
+ ceiling is not a budget and needs no setting; env can only lower it. The
98
+ day-to-day limits belong in the dashboard: once the agent is linked with
99
+ `agent_claim_self`, the owner manages the per-payment cap, the daily cap, pause
100
+ and the allowed merchants under **Controls** at https://dash.aifinpay.io, and
101
+ the backend enforces that policy on every `/v1/quote` and `/v1/pay` for the
102
+ claimed agent — no env change, no server restart. The ceiling still applies
103
+ underneath; a payment has to pass both. More than $5 / $20 on an agent key is
104
+ the Node SDK with its own limits.
105
+
106
+ `payment_setup_status` reads those Controls back for a persistent EVM wallet
107
+ and returns them as `dashboard`: `{ linked: true, policy }` with the per-payment
108
+ cap, daily cap, merchant allowlist, expiry and pause; `{ linked: false }` when
109
+ no owner has claimed the agent yet (its `next_step` then offers the dashboard
110
+ link); `{ linked: "unknown", reason }` when the read fails, which blocks
111
+ nothing because the backend enforces the policy either way. Paused or expired
112
+ Controls stop the checklist with a `next_step` that says so. The read is
113
+ `GET /v1/agents/<address>/policy` on the configured backend, signed by the
114
+ wallet's own key (EIP-191 over `["AiFinPay agent policy read v1", <backend
115
+ origin>, <lowercase address>, <expires_at>]`, valid 60 s); it signs no payment
116
+ and changes nothing. It is not made on `payable_fetch`'s refusal path, for an
117
+ ephemeral wallet or on Solana.
104
118
 
105
119
  ## Indexed wallet derivation
106
120
 
@@ -168,16 +182,16 @@ runtime/signer verification and owner limits. It persists the prepared transacti
168
182
  before sending, verifies the receipt, and reuses the purchased batch. No special
169
183
  merchant script, alternate contract or facilitator fallback is used. GET on the configured chain; EVM receipt payments use live
170
184
  mode only, in its native currency or the configured
171
- stablecoin; Amoy payment receipts are not supported. The smallest batch is $0.10 plus gas; `AIFINPAY_MAX_USD`
172
- only has to be at or above the batch you expect to buy.
185
+ stablecoin; Amoy payment receipts are not supported. The smallest batch is $0.10 plus gas, well inside
186
+ the $5 per-payment ceiling.
173
187
 
174
188
  To buy access to a whole site rather than one endpoint, call
175
189
  `payable_fetch({"url":"https://merchant.example/api/data","scope":"merchant"})`.
176
190
  One batch then covers every path on that merchant, and each request still costs
177
191
  its own listed price, so a premium page drains more of it than a standard API
178
- call. The price, the owner limits and the approved origins do not change. An
179
- origin missing from `AIFINPAY_GATEWAY_ORIGINS` is refused by name; only the
180
- owner can add it.
192
+ call. The price, the owner limits and the approved origins do not change. When
193
+ the owner set `AIFINPAY_GATEWAY_ORIGINS`, an origin missing from it is refused
194
+ by name; only the owner can add it.
181
195
 
182
196
  ### Network access
183
197
 
@@ -219,8 +233,8 @@ origins, signs only the claim challenge for this agent's own address, and moves
219
233
  no funds. The owner-selected payment family must be confirmed successfully;
220
234
  the second wallet is best-effort. Use the selected wallet's Fund panel for
221
235
  available networks and assets; binding does not activate a disabled network.
222
- Offer this to the owner after `init`: from then on the owner manages the
223
- agent's working limits under Controls there (see "Owner limits" above).
236
+ Offer this to the owner after `init` (step 4 above): from then on the owner
237
+ manages the agent's working limits under Controls there (see "Owner limits").
224
238
 
225
239
  Private recovery state for all payment families lives at `AIFINPAY_HOME/payments/<evm-address>/state.json`
226
240
  (default home `~/.aifinpay`). State is mode600 in mode700 directories, atomically
@@ -240,7 +254,7 @@ state file in chat. Unconfirmed payments consume the budget conservatively.
240
254
  | `agent_reload` | Reload local wallet files in the current MCP connection. |
241
255
  | `agent_quota` | Read the agent's quota. |
242
256
  | `agent_passport_resolve` | Resolve the global Agent Passport identity. |
243
- | `payment_setup_status` | Read-only setup checklist with the one `next_step`. |
257
+ | `payment_setup_status` | Setup checklist, owner's dashboard Controls, `next_step`. |
244
258
  | `settlement_routes` | Splitter v1.4 routes (live now) first, then legacy v1.3. |
245
259
  | `settlement_invoice` | Prepare a non-signing settlement invoice. |
246
260
  | `agent_history` | Read indexed settlements or retained receipt batches. |
@@ -248,11 +262,13 @@ state file in chat. Unconfirmed payments consume the budget conservatively.
248
262
  | `settlement_casper` | Build a non-signing Casper settlement invoice. |
249
263
  | `deployment_info` | Read deployments: addresses, assets, settlement status. |
250
264
 
251
- `payable_fetch` is always listed. It signs only with a persistent wallet,
252
- `AIFINPAY_PAYMENTS_ENABLED=1` and every owner limit; before that it returns the
253
- `payment_setup_status` checklist as a tool error and contacts nothing. With
254
- payments enabled and any owner limit missing or invalid, the server refuses to
255
- start rather than hiding the tool. It accepts
265
+ `payable_fetch` is always listed. It signs only with a persistent wallet, and
266
+ not when the owner set `AIFINPAY_PAYMENTS_ENABLED=0`; otherwise it returns the
267
+ `payment_setup_status` checklist as a tool error and contacts nothing. A
268
+ refused override with payments on by default leaves the server read-only and
269
+ `payment_setup_status` names it; with an explicit `AIFINPAY_PAYMENTS_ENABLED=1`
270
+ the server refuses to start, as before. An env limit above the ceiling stops
271
+ the start in both cases. It accepts
256
272
  only `url`, `max_amount_usd`, `scope` and `expected_merchant_id`; `max_amount_usd`
257
273
  can lower the owner's per-payment cap for one call, never raise it.
258
274
 
@@ -355,7 +371,8 @@ passphrase, encrypts the keystore and prints one JSON document:
355
371
  "addresses": { "evm": "0x…", "solana": "…", "casper": "account-hash-…" },
356
372
  "env": { "AIFINPAY_WALLET_PASSPHRASE": "<generated>" },
357
373
  "passphrase_note": "…",
358
- "payment_env_example": { "AIFINPAY_PAYMENTS_ENABLED": "1", "…": "…" },
374
+ "payments": "Payments are on by default within a built-in ceiling of $5 per payment and $20 per 24 hours, …",
375
+ "optional_env_example": { "AIFINPAY_GATEWAY_ORIGINS": "https://merchant.example", "AIFINPAY_MAX_GAS_POL": "0.3" },
359
376
  "next_step": "Put \"env\" into the aifinpay server entry of the MCP client config …"
360
377
  }
361
378
  ```
@@ -431,9 +448,12 @@ snapshot. Verify `agent_address` against the wallet you intend to use.
431
448
  | ---------------------------- | --------------------- | ------------------------------------------------------------------------------------- |
432
449
  | `AIFINPAY_BASE_URL` | `https://aifinpay.io` | Backend URL. Unset, `payable_fetch` quotes and verifies at `https://api.aifinpay.io`. |
433
450
  | `AIFINPAY_TIMEOUT_MS` | `30000` | Request timeout. |
434
- | `AIFINPAY_MAX_USD` | — | Per-payment USD cap for `payable_fetch`; required when payments are enabled. |
435
- | `AIFINPAY_GATEWAY_ORIGINS` | — | Comma-separated exact HTTPS origins the agent may pay; required with payments. |
436
- | `AIFINPAY_GATEWAY_PATH_MODE` | `gateway` | Use `gateway` for merchant-slug identity or `direct` for full request-path identity. |
451
+ | `AIFINPAY_PAYMENTS_ENABLED` | on | Optional override: `0` turns payments off. |
452
+ | `AIFINPAY_MAX_USD` | `5` | Optional override: lowers the per-payment ceiling; a higher value is refused. |
453
+ | `AIFINPAY_DAILY_USD` | `20` | Optional override: lowers the 24-hour ceiling; a higher value is refused. |
454
+ | `AIFINPAY_GATEWAY_ORIGINS` | verified merchant sites | Optional allowlist: comma-separated exact HTTPS origins the agent may pay. |
455
+ | `AIFINPAY_GATEWAY_PATH_MODE` | inferred per URL | `gateway` (merchant slug) or `direct` (full path); unset: the hosted gateway by slug. |
456
+ | `AIFINPAY_MAX_GAS_POL` | `0.3` | Optional override: gas cap per payment on Polygon, in POL. |
437
457
  | `AIFINPAY_PAY_CHAIN` | `polygon` | Owner-selected payment chain; see the2.8.1 source capability list. |
438
458
  | `AIFINPAY_MAX_GAS` | — | Gas cap per payment in the pay chain's native currency (POL, ETH, AVAX, BNB, XRP). |
439
459
  | `AIFINPAY_RPC_URL` | chain's public RPC | HTTPS RPC for the pay chain. |
@@ -465,16 +485,17 @@ The programmatic equivalents of identity environment options are `seedHash`,
465
485
  - AIFINPAY_MODE=dev: expose dev_payment_quote; requires a separate dev base URL.
466
486
 
467
487
  - AIFINPAY_TIMEOUT_MS: SDK request timeout.
468
- - AIFINPAY_MAX_USD: per-payment USD cap for payable_fetch; required with payments.
488
+ - AIFINPAY_MAX_USD: lowers the $5 per-payment ceiling of payable_fetch (optional).
469
489
  - AIFINPAY_TRUSTED_HOSTS: exact hosts allowed to bypass the DNS pre-check.
470
490
  - AIFINPAY_ALLOW_PRIVATE_FETCH=1: explicit local-development network access.
471
491
  Never enable this on the public hosted MCP.
472
492
 
473
- For a self-hosted AIFP-1 gateway, set `AIFINPAY_GATEWAY_ORIGINS` to exact HTTPS
474
- origins. `AIFINPAY_GATEWAY_PATH_MODE=direct` makes the process use each request's
475
- full pathname as its AIFP-1 resource identity; `gateway` uses the merchant slug.
476
- The mode is process-wide, does not broaden the trusted-origin allowlist, and
477
- does not enable the retired signing tools in the production RC.
493
+ A self-hosted AIFP-1 gateway needs no setting: unset, the path mode is
494
+ `direct` (each request's full pathname is its AIFP-1 resource identity) for any
495
+ origin other than `https://gateway.aifinpay.io`, which uses the merchant slug.
496
+ `AIFINPAY_GATEWAY_PATH_MODE` forces one mode for every origin; it does not
497
+ broaden an owner's `AIFINPAY_GATEWAY_ORIGINS` allowlist and does not enable the
498
+ retired signing tools in the production RC.
478
499
 
479
500
  Dev quoting does not bypass wallet signatures, issuer verification or
480
501
  receipt metering. See the bundled skill for backend prerequisites. The low-level SDK has an Amoy
@@ -27,7 +27,7 @@
27
27
  * AIFINPAY_AGENT_SECRET legacy base58 secret — overrides the legacy keystore
28
28
  * AIFINPAY_BASE_URL default https://aifinpay.io
29
29
  * AIFINPAY_TIMEOUT_MS default 30000
30
- * AIFINPAY_MAX_USD hard cap per single payment (no default)
30
+ * AIFINPAY_MAX_USD lowers the built-in $5-per-payment ceiling (never raises it)
31
31
  */
32
32
  import {
33
33
  readFileSync,
@@ -91,10 +91,16 @@ Env (all optional):
91
91
  AIFINPAY_TIMEOUT_MS default 30000
92
92
  AIFINPAY_HOME default ~/.aifinpay
93
93
 
94
- Payments (payable_fetch) sign nothing until the owner sets all of
95
- AIFINPAY_PAYMENTS_ENABLED=1, AIFINPAY_GATEWAY_ORIGINS, AIFINPAY_MAX_USD,
96
- AIFINPAY_DAILY_USD and AIFINPAY_MAX_GAS_POL. init prints an example block;
97
- the payment_setup_status tool says which of them is still missing.
94
+ Payments (payable_fetch) are on by default, within a built-in ceiling of $5 per
95
+ payment and $20 per 24 hours, only from a persistent wallet (init), and only to
96
+ merchants registered with AiFinPay; an unfunded wallet spends nothing. The
97
+ working limits are the dashboard Controls (https://dash.aifinpay.io) once the
98
+ agent is claimed. Optional overrides, all narrowing:
99
+ AIFINPAY_PAYMENTS_ENABLED=0 turn payments off
100
+ AIFINPAY_MAX_USD, AIFINPAY_DAILY_USD lower the ceiling (higher is refused)
101
+ AIFINPAY_GATEWAY_ORIGINS exact https origins it may pay; unset, any https site
102
+ AIFINPAY_MAX_GAS_POL gas cap per payment on Polygon (default 0.3)
103
+ The payment_setup_status tool says what is still missing before a first payment.
98
104
  `);
99
105
  process.exit(0);
100
106
  }
@@ -178,7 +184,8 @@ if (arg === "init") {
178
184
 
179
185
  const { loadConfigFromEnv } = await import("../dist/config.js");
180
186
  const { loadWalletIdentity } = await import("../dist/identity.js");
181
- const { PAYMENT_ENV, lockedKeystoreStep } = await import("../dist/tools/payment-setup-status.js");
187
+ const { PAYMENT_OVERRIDES, PAYMENTS_DEFAULT_NOTE, lockedKeystoreStep } =
188
+ await import("../dist/tools/payment-setup-status.js");
182
189
  const config = loadConfigFromEnv();
183
190
  // A keystore that cannot be opened is reported in one line that names the
184
191
  // variable, never as a stack trace — and never replaced. An agent cannot ask
@@ -225,7 +232,7 @@ if (arg === "init") {
225
232
  // caller can parse it. The same facts, as prose, go to a terminal.
226
233
  const emit = (json, text) => process.stdout.write(NONINTERACTIVE ? JSON.stringify(json, null, 2) + "\n" : text);
227
234
  const nextStep =
228
- 'Put "env" into the aifinpay server entry of the MCP client config and reconnect the server (or call agent_reload in an already connected one), then call payment_setup_status: it names the next step up to the first payment.';
235
+ 'Put "env" into the aifinpay server entry of the MCP client config and reconnect the server (or call agent_reload in an already connected one: payments then work without a restart), then call payment_setup_status: it names the next step up to the first payment.';
229
236
 
230
237
  if (selected && selected.source !== "legacy-keystore") {
231
238
  const agent = selected.seedHash
@@ -239,7 +246,8 @@ if (arg === "init") {
239
246
  source: selected.source,
240
247
  addresses: addressesOf(agent),
241
248
  env: { ...homeEnv, ...indexEnv },
242
- payment_env_example: PAYMENT_ENV,
249
+ payments: PAYMENTS_DEFAULT_NOTE,
250
+ optional_env_example: PAYMENT_OVERRIDES,
243
251
  next_step: nextStep,
244
252
  },
245
253
  `Using ${selected.source}${selected.derivationIndex === undefined ? "" : ` (index ${selected.derivationIndex})`}; no replacement wallet created.\n` +
@@ -347,7 +355,8 @@ if (arg === "init") {
347
355
  passphrase_note: `${PASSPHRASE_ENV} was generated for this wallet and appears only here, inside env. The wallet cannot be opened or recovered without it.`,
348
356
  }
349
357
  : {}),
350
- payment_env_example: PAYMENT_ENV,
358
+ payments: PAYMENTS_DEFAULT_NOTE,
359
+ optional_env_example: PAYMENT_OVERRIDES,
351
360
  next_step: nextStep,
352
361
  },
353
362
  ""
@@ -389,10 +398,8 @@ if (arg === "init") {
389
398
  ` EVM ${agent.evmAddress}\n` +
390
399
  ` Solana ${agent.solanaAddress}\n` +
391
400
  ` Casper ${agent.casperAddress}\n\n` +
392
- `Add this to your MCP client config and connect/reconnect this MCP server.\n` +
393
- `As printed it cannot pay: payable_fetch is listed but signs nothing until\n` +
394
- `you add the payment settings further down (payment_setup_status says what\n` +
395
- `is still missing):\n\n` +
401
+ `Add this to your MCP client config and connect/reconnect this MCP server\n` +
402
+ `(or call agent_reload in one that is already connected):\n\n` +
396
403
  JSON.stringify(
397
404
  {
398
405
  mcpServers: {
@@ -420,31 +427,32 @@ if (arg === "init") {
420
427
  `keystore. If this server is already connected, call agent_reload after init.\nA new conversation is not required by this server.\n\n` +
421
428
  `Back up ${KEYSTORE}. It is the only copy. The derivation is not\n` +
422
429
  `BIP-39, so no standard wallet can recover this from a phrase.\n\n` +
423
- `To let it pay, add these to "env" above, then reconnect the server:\n\n` +
424
- JSON.stringify(PAYMENT_ENV, null, 2) +
425
- `\n\n` +
426
- ` AIFINPAY_GATEWAY_ORIGINS exact HTTPS origins it may pay, comma-separated;\n` +
427
- ` replace the example. No wildcards.\n` +
428
- ` AIFINPAY_GATEWAY_PATH_MODE "direct" for a site that runs its own AiFinPay\n` +
429
- ` paywall, "gateway" for gateway.aifinpay.io.\n` +
430
- ` AIFINPAY_MAX_USD per payment, a ceiling set once (the smallest\n` +
431
- ` batch is $0.10; the example is not a budget).\n` +
432
- ` AIFINPAY_DAILY_USD total over any 24 hours, the same kind of ceiling.\n` +
433
- ` Day-to-day limits: dashboard Controls, once the\n` +
434
- ` agent is claimed (see below).\n` +
435
- ` AIFINPAY_MAX_GAS_POL worst-case network fee of one payment, checked\n` +
436
- ` before signing. It follows Polygon's gas price:\n` +
437
- ` at ~280 gwei it is ~0.10 POL paying in POL and\n` +
438
- ` ~0.21 POL paying in USDC. A lower cap refuses\n` +
439
- ` the payment; raise it when gas is higher.\n\n` +
440
- `Fund the EVM address on Polygon with the batch price at today's rate plus the\n` +
441
- `gas cap, in POL; payment_setup_status prices it.\n` +
442
- `To pay in USDC, also set "AIFINPAY_PAY_ASSET": "USDC" and hold USDC for the\n` +
443
- `batch plus POL up to the gas cap. Check the balance before funding or paying.\n\n` +
444
- `See its balance, payments and receipts in your dashboard:\n` +
430
+ `Payments are on: payable_fetch pays at most $5 per payment and $20 per 24\n` +
431
+ `hours (a built-in ceiling, not a budget), only to merchants registered with\n` +
432
+ `AiFinPay. It holds nothing yet, so it can spend nothing. To let it pay, fund\n` +
433
+ `the EVM address on Polygon with the batch price at today's rate plus the gas\n` +
434
+ `cap, in POL; payment_setup_status prices it (the smallest batch is $0.10).\n` +
435
+ `To pay in USDC, set "AIFINPAY_PAY_ASSET": "USDC" and hold USDC for the batch\n` +
436
+ `plus POL up to the gas cap. Check the balance before funding or paying.\n\n` +
437
+ `Set the working limits in your dashboard:\n` +
445
438
  ` https://dash.aifinpay.io → My Agents → Claim via MCP, then give the\n` +
446
439
  ` one-time URL to the agent (tool agent_claim_self). Controls there set the\n` +
447
- ` working limits; the env values above stay as the ceiling.\n`
440
+ ` per-payment cap, daily cap, pause and allowed merchants, enforced on every\n` +
441
+ ` quote and payment; the ceiling above still applies underneath.\n\n` +
442
+ `Optional env, for reference (none of it is needed for a first payment):\n\n` +
443
+ JSON.stringify(PAYMENT_OVERRIDES, null, 2) +
444
+ `\n\n` +
445
+ ` AIFINPAY_GATEWAY_ORIGINS exact HTTPS origins it may pay, comma-separated,\n` +
446
+ ` no wildcards. Unset, any https site: the money\n` +
447
+ ` still goes only where AiFinPay's signed quote says.\n` +
448
+ ` AIFINPAY_MAX_GAS_POL worst-case network fee of one payment, checked\n` +
449
+ ` before signing; default 0.3 POL. It follows\n` +
450
+ ` Polygon's gas price: at ~280 gwei it is ~0.10 POL\n` +
451
+ ` paying in POL and ~0.21 POL paying in USDC.\n` +
452
+ ` AIFINPAY_MAX_USD, AIFINPAY_DAILY_USD lower the ceiling; a higher value\n` +
453
+ ` is refused. Raise nothing here: use Controls.\n` +
454
+ ` AIFINPAY_PAYMENTS_ENABLED "0" turns payments off.\n` +
455
+ `Env is read when the server starts; after changing it, restart the server.\n`
448
456
  );
449
457
  process.exit(0);
450
458
  }
package/dist/config.d.ts CHANGED
@@ -19,8 +19,16 @@ export interface McpConfig {
19
19
  baseUrl?: string;
20
20
  /** Request timeout in ms. */
21
21
  timeoutMs?: number;
22
- /** Owner opt-in; never accepted from tool arguments. */
22
+ /** On unless the owner sets AIFINPAY_PAYMENTS_ENABLED=0; never accepted from tool arguments.
23
+ * An unfunded wallet spends nothing, and the built-in ceiling below bounds a funded one. */
23
24
  paymentsEnabled?: boolean;
25
+ /** Payments are on because AIFINPAY_PAYMENTS_ENABLED is unset. A refused payment setting
26
+ * then leaves the server running read-only, with payment_setup_status naming the refusal;
27
+ * an explicit =1 (or a programmatic paymentsEnabled) stops the server, as it always did. */
28
+ paymentsByDefault?: boolean;
29
+ /** Names of the limit variables the owner set in env to lower the built-in ceiling;
30
+ * payment_setup_status reports each limit's source from this. */
31
+ ownerOverrides?: string[];
24
32
  dailyAmountUsd?: number;
25
33
  /** Chain payable_fetch settles on: "polygon" (default), another supported EVM chain, or "solana". Set by
26
34
  * the owner only; never inferred from a quote or a tool argument. */
@@ -40,20 +48,24 @@ export interface McpConfig {
40
48
  payAsset?: string;
41
49
  /** Hard cap on a single payment to prevent runaway agents. */
42
50
  maxAmountUsd?: number;
43
- /** Gateway origins this agent may settle against.
51
+ /** Optional allowlist of gateway origins this agent may settle against.
44
52
  *
45
- * The SDK has always supported this (parseGatewayUrl in @aifinpay/agent) and
46
- * this wrapper never exposed it, so a self-hosted merchant was unreachable:
47
- * payable_fetch reached the 402 and then refused with "dev.ratersapp.com is
48
- * not a known AiFinPay gateway; allowed: https://gateway.aifinpay.io".
49
- * Observed in an external E2E run on 2026-08-27.
53
+ * Unset (the default since 2.12.1), payable_fetch accepts the https origin
54
+ * of the URL it is given, and pays only if the merchant in the backend-signed
55
+ * quote has a DNS-verified site that is that origin's host (any verified
56
+ * merchant on the AiFinPay hosted gateway) — see ../merchant-site.ts. The
57
+ * 402 never decides who is paid; the ceiling below and the owner's dashboard
58
+ * Controls still apply.
59
+ * Before 2.12.1 this variable was required, and an unlisted origin was
60
+ * refused by name (observed in an external E2E run on 2026-08-27).
50
61
  *
51
- * Set by the OPERATOR, exact origins only, never a wildcard. The refusal it
52
- * relaxes is not paranoia: a 402 is unauthenticated, so paying an
53
- * unrecognised host means paying whoever answered. Naming a host here is a
54
- * statement that you know who that is. */
62
+ * Set by the OPERATOR, exact https origins only, never a wildcard, it
63
+ * narrows that default: an origin not listed is refused before any quote.
64
+ * Naming a host here is a statement that you know who that is. */
55
65
  gatewayOrigins?: string[];
56
- /** AIFP-1 resource identity: merchant slug or full direct request path. */
66
+ /** AIFP-1 resource identity: merchant slug or full direct request path.
67
+ * Unset, payable_fetch infers it per URL: the hosted gateway
68
+ * (https://gateway.aifinpay.io) uses the slug, any other origin the path. */
57
69
  gatewayPathMode?: "gateway" | "direct";
58
70
  /** Hosts whose DNS pre-check is skipped, exact names only.
59
71
  *
@@ -70,6 +82,19 @@ export interface McpConfig {
70
82
  logFn?: (level: "info" | "warn" | "error", msg: string) => void;
71
83
  }
72
84
  export declare function loadConfigFromEnv(): McpConfig;
73
- /** Signing is available only after the owner configures all spending boundaries. */
85
+ /** Built-in spending ceiling (owner decision 2026-10-20): $5 per payment, $20 per
86
+ * 24 h. The env values can only lower it; a higher value is refused so a
87
+ * pasted config cannot raise the ceiling above what the dashboard Controls
88
+ * are meant to manage. */
89
+ export declare const DEFAULT_MAX_USD = 5;
90
+ export declare const DEFAULT_DAILY_USD = 20;
91
+ /** Gas cap per payment on Polygon when the owner sets none: the worst case at
92
+ * ~280 gwei is ~0.10 POL paying in POL and ~0.21 POL in USDC, so 0.3 POL
93
+ * (~$0.06) leaves room without being a budget. Another chain still needs
94
+ * AIFINPAY_MAX_GAS in its own currency: choosing the chain is explicit anyway. */
95
+ export declare const DEFAULT_MAX_GAS_POL = "0.3";
96
+ /** Signing is available only while payments are on and every spending boundary is set:
97
+ * the per-payment and daily USD ceiling, a gas cap, and an exact https allowlist when
98
+ * the owner chose to set one. */
74
99
  export declare function validatePaymentConfig(config: McpConfig): bigint;
75
100
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,wDAAwD;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;0EACsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACrC,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;yFACqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;+CAW2C;IAC3C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B,2EAA2E;IAC3E,eAAe,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAEvC;;;;;;;;;8CAS0C;IAC1C,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,wBAAgB,iBAAiB,IAAI,SAAS,CAgC7C;AA4ED,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAkF/D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAGvD,6CAA6C;AAC7C,MAAM,WAAW,SAAS;IACxB,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,qFAAqF;IACrF,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;iGAC6F;IAC7F,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;iGAE6F;IAC7F,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B;sEACkE;IAClE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;0EACsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4EAA4E;IAC5E,aAAa,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IACrC,uEAAuE;IACvE,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;yFACqF;IACrF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;;;;;;;;uEAamE;IACnE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAE1B;;kFAE8E;IAC9E,eAAe,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAEvC;;;;;;;;;8CAS0C;IAC1C,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;IAExB,qDAAqD;IACrD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjE;AAED,wBAAgB,iBAAiB,IAAI,SAAS,CAqC7C;AA4ED;;;2BAG2B;AAC3B,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC;;;mFAGmF;AACnF,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAUzC;;kCAEkC;AAClC,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAsF/D"}