agentic-wallet-mcp 0.10.0 → 0.12.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.
- package/CHANGELOG.md +60 -0
- package/README.md +5 -2
- package/dist/server-bundle.cjs +994 -96
- package/package.json +3 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,66 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
> Entries for 0.5.0 and earlier were reconstructed from commit history when this file was
|
|
9
9
|
> introduced in 0.6.0, so they summarise each release rather than being exhaustive.
|
|
10
10
|
|
|
11
|
+
## [0.12.0] — 22 September 2026
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **Three free policy read tools**: `get_policy_template_schema` (which spending rules a template
|
|
16
|
+
allows), `get_my_policy` (the policies this owner has deployed on chain) and `policy_preflight`
|
|
17
|
+
(is a draft policy valid, and does it MEAN what the user thinks). All read-only: they sign
|
|
18
|
+
nothing, spend nothing and deploy nothing. Each reports a three-state result, so "this network has
|
|
19
|
+
no policy system" is never reported as "you have no policy".
|
|
20
|
+
- **`clear_stuck_payment_receipt`**: the supported way to discard a Verified AI Birthcert payment
|
|
21
|
+
receipt the wallet is holding and refusing to pay past — previously only possible by deleting a
|
|
22
|
+
file on the server, which a hosted subscriber cannot do. Two steps by construction: the first call
|
|
23
|
+
clears nothing and returns the receipt id, and clearing requires echoing that exact id back.
|
|
24
|
+
- **`request_ai_birthcert_verification` gains `discardStuckReceiptAndPayFresh`**: discard a stuck
|
|
25
|
+
receipt and pay again in one call. Takes the receipt id, never a boolean, so a receipt cannot be
|
|
26
|
+
discarded that was not first shown to the user. Refuses a mismatched id, a receipt belonging to a
|
|
27
|
+
live session, and combination with `dryRun` — spending nothing in each case.
|
|
28
|
+
- **`SETTLEMENT_STUCK_AFTER_MS`** (default `86400000`, 24h): how long an unconfirmed settlement may
|
|
29
|
+
stay unresolved before the wallet stops calling it "still settling" and calls it permanently stuck.
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **`check_ai_birthcert_verification` now advances a queued settlement** instead of only reporting
|
|
34
|
+
it. It replays the saved receipt — never a new payment — and returns the live session once it
|
|
35
|
+
settles, so "check back in a few minutes" genuinely progresses the flow.
|
|
36
|
+
- **A queued settlement no longer blocks the tool call for ~20 minutes.** It returns within a bounded
|
|
37
|
+
wall-clock budget (`SETTLEMENT_WAIT_BUDGET_MS`, default 90s) as
|
|
38
|
+
`{ settlementPending: true, paymentReceipt, message }` — the payment succeeded and is in flight,
|
|
39
|
+
which is not an error.
|
|
40
|
+
- **Settlement messages lead with their verdict** (`PAYMENT SENT` / `OUTCOME UNKNOWN` / `RECEIPT VOID`)
|
|
41
|
+
and carry `paymentReceipt` as its own field, so an assistant summarising the result cannot turn
|
|
42
|
+
"we do not know yet" into "it failed".
|
|
43
|
+
- **The three settlement verdicts are now told apart.** A receipt the service declares finished is
|
|
44
|
+
terminal and reported as `status: "receipt_void"`; an unresolved one is judged by the receipt's own
|
|
45
|
+
age — recent means "still settling, check back", older than `SETTLEMENT_STUCK_AFTER_MS` means
|
|
46
|
+
"this is not coming back". None of them claims the fee was refunded: a settlement can expire after
|
|
47
|
+
the money has already moved, so the receipt id is always handed back for support.
|
|
48
|
+
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- A stuck receipt no longer dead-ends. The wallet still refuses to buy a new credential while one is
|
|
52
|
+
held — that refusal is what prevents a second charge — but it now names the way out and states
|
|
53
|
+
plainly that starting over costs the fee a second time.
|
|
54
|
+
|
|
55
|
+
## [0.11.0] — 17 September 2026
|
|
56
|
+
|
|
57
|
+
### Added
|
|
58
|
+
|
|
59
|
+
- **VC pass-design images are now surfaced for basic and verified birthcert issuance.** When the
|
|
60
|
+
issuer returns a pass-design image alongside a credential, the wallet extracts it, writes it to
|
|
61
|
+
disk, and — since a remote MCP client has no filesystem access to read a local path back —
|
|
62
|
+
returns it as an inline image in the tool response too, so the pass is actually visible rather
|
|
63
|
+
than just referenced by path.
|
|
64
|
+
|
|
65
|
+
### Fixed
|
|
66
|
+
|
|
67
|
+
- **The spending-cap blocker now shows human-readable amounts.** It previously showed the raw
|
|
68
|
+
base-unit number with no symbol or decimal conversion, while the balance/fee blocker in the same
|
|
69
|
+
response already showed the correctly formatted amount — the cap blocker now matches it.
|
|
70
|
+
|
|
11
71
|
## [0.10.0] — 14 September 2026
|
|
12
72
|
|
|
13
73
|
### Added
|
package/README.md
CHANGED
|
@@ -28,8 +28,9 @@ VC issuance → identity proof → pay-per-use).
|
|
|
28
28
|
| `create_holder_account` | Onboarding: mint an HSM account (the MCP already auto-creates one at startup if `ZETRIX_ADDRESS` is omitted — see Environment below). Always checks for an existing account first — if one is active for this session, returns `{ alreadyExists: true, existing }` without creating anything; pass `confirmNew: true` (after asking the user) to mint a new one anyway | `{ password, label?, purpose?, confirmNew? }` | `{ created, alreadyExists, existing?, zetrixAddress?, holderDid?, publicKeyHex?, message }` |
|
|
29
29
|
| `get_template_schema` | **Free** read of a VC template's declared attribute schema. Call before `subscribe_and_issue` to learn which attributes it requires | `{ templateId }` | `{ templateId, schema: { required, optional } }` or `{ templateId, error }` |
|
|
30
30
|
| `query_contract` | Read-only query against any Zetrix contract — call an arbitrary method and return its raw result. No signing, no state change | `{ contractAddress, method, params? }` | `{ ok: true, result }` or `{ ok: false, error }` |
|
|
31
|
-
| `request_ai_birthcert_verification` | Start a **Verified** AI Birthcert issuance session with myid (MyDigital ID owner verification) — distinct from `subscribe_and_issue`'s self-declared Basic AI Birthcert. Optional `gasPayer` (`"sponsored"` \| `"self"`) overrides the gas payer for this call only — precedence is per-call `gasPayer` > `GAS_PREFERENCE` config > `sponsored` hardcoded default. If a sponsored quote is refused before any money moved, the wallet automatically falls back to paying gas itself; it never falls back once payment is merely pending/indeterminate. `dryRun: true` quotes instead of paying: it stops after the 402 challenge, pays nothing, creates no session, and returns `{ quote }` — the asset, the amount and which side pays gas. Quote and paid request send byte-identical signed bodies | `{ agentName, agentPurpose?, evidenceAssuranceLevel?, ownerType?, ownerVerified?, gasPayer?, dryRun? }` | `{ sessionId, verificationUrl, expiresAt }
|
|
32
|
-
| `check_ai_birthcert_verification` | **Free
|
|
31
|
+
| `request_ai_birthcert_verification` | Start a **Verified** AI Birthcert issuance session with myid (MyDigital ID owner verification) — distinct from `subscribe_and_issue`'s self-declared Basic AI Birthcert. Optional `gasPayer` (`"sponsored"` \| `"self"`) overrides the gas payer for this call only — precedence is per-call `gasPayer` > `GAS_PREFERENCE` config > `sponsored` hardcoded default. If a sponsored quote is refused before any money moved, the wallet automatically falls back to paying gas itself; it never falls back once payment is merely pending/indeterminate. `dryRun: true` quotes instead of paying: it stops after the 402 challenge, pays nothing, creates no session, and returns `{ quote }` — the asset, the amount and which side pays gas. Quote and paid request send byte-identical signed bodies | `{ agentName, agentPurpose?, evidenceAssuranceLevel?, ownerType?, ownerVerified?, gasPayer?, dryRun?, discardStuckReceiptAndPayFresh? }` | `{ sessionId, verificationUrl, expiresAt }`, `{ quote: { asset, maxAmountRequired, payTo?, gasModel } }`, or — when the sponsored settlement is still clearing after ~90s — `{ settlementPending: true, paymentReceipt, message }`, which means the payment SUCCEEDED and is in progress, not that it failed. While a stuck receipt is held this tool can only REPLAY it — it never buys a new credential, which is what stops a second charge. `discardStuckReceiptAndPayFresh: "<exact receipt id>"` is the way to start over: it throws that payment away and pays the fee again, refuses a mismatched id (discarding and paying nothing), refuses a receipt that belongs to a live session, and returns `discardedPaymentReceipt` so the lost payment stays traceable |
|
|
32
|
+
| `check_ai_birthcert_verification` | **Free** (never pays). Poll the most recently requested Verified AI Birthcert session; on `status: "issued"`, also fetches, verifies, and caches the credential. While the session is still open it replays the stored `verificationUrl` alongside SSIVC's live `expiresAt` — SSIVC issues the link only once, at creation, so this store is the only place it survives. That makes *"where is my link?"* answerable without touching the paid tool. No link is returned once `status` is `"issued"`: the link is spent. If a prior payment is still clearing this tool **advances** it — it replays the saved receipt (never a new payment) and returns the live session once it settles, so "check back in a few minutes" genuinely progresses the flow | (none) | `{ status: "pending" \| "issued" \| "no_session" \| "settlement_pending" | "receipt_void", verificationUrl?, expiresAt?, vcId?, vc?, cacheError?, paymentReceipt?, outcomeUnknown?, message? }` — `settlement_pending` means a payment was made and is being followed: without `outcomeUnknown` it is queued and progressing (check again shortly); with `outcomeUnknown: true` the outcome could not be determined at all and has been unresolved longer than `SETTLEMENT_STUCK_AFTER_MS` (24h default), so it is not coming back on its own — `stuckFor` says how long, the fee was most likely already taken, and quoting `paymentReceipt` to support is the way forward. Starting over via `clear_stuck_payment_receipt` costs a second fee. `receipt_void` is terminal and different: SSIVC has ruled the receipt finished (status_code 67 expired / 68 failed), so checking again cannot help — it does NOT mean the fee was refunded, and buying the credential means paying again |
|
|
33
|
+
| `clear_stuck_payment_receipt` | **Free, last resort, destructive.** Discard a stuck Verified AI Birthcert payment receipt the wallet is holding and refusing to pay past — the supported replacement for deleting `<stateDir>/ssivc-session.json` by hand, which a hosted subscriber cannot do. Two steps by construction: with no argument it clears nothing and returns the receipt id plus a warning; clearing requires echoing that exact id back as `confirmReceiptId`, and a mismatch clears nothing. If the settlement completed in between — which is what happens when you follow the advice to call `check_ai_birthcert_verification` first — the receipt now belongs to a **live, paid-for session**, and the id alone no longer clears it: the tool hands back `sessionId` and `verificationUrl` instead, and only `confirmDiscardLiveSession: true` will discard them. The discarded payment is unrecoverable | `{ confirmReceiptId?, confirmDiscardLiveSession? }` | `{ cleared, paymentReceipt?, requiresConfirmation?, sessionId?, verificationUrl?, message?, error? }` |
|
|
33
34
|
|
|
34
35
|
> **VCs are cached locally**, keyed by `templateId`, under `~/.agentic-wallet-mcp/vc-cache/`
|
|
35
36
|
> (scoped per network + holder — different identities or networks never share a cache).
|
|
@@ -183,6 +184,8 @@ Node ≥ 18 required (built-in `fetch`).
|
|
|
183
184
|
| `AI_BIRTHCERT_VERIFIED_TEMPLATE_ID` | no | The Verified AI Birthcert's on-chain `did:zid:...` template id. Auto-derived per network by default — **the mainnet default is unverified**, so override this explicitly once the mainnet template id is confirmed |
|
|
184
185
|
| `GAS_PREFERENCE` | no | `sponsored` or `self` — the default gas payer for the Verified AI Birthcert flow (`request_ai_birthcert_verification`). **Defaults to `sponsored`; any unrecognised value also falls back to `sponsored`** rather than throwing. Sponsorship only actually engages when the resource server's x402 quote offers a sponsored option (`extra.gasModel: "facilitator"`) — a server that only quotes self-pay behaves unchanged. **Sponsorship is testnet-only today**; override per-call with the tool's `gasPayer` parameter |
|
|
185
186
|
| `MAX_SETTLEMENT_ATTEMPTS` | no | Cap on retry attempts while polling a sponsored payment for settlement after SSIVC returns `202 Accepted` (queued). **Defaults to `20`; a non-positive or unparseable value also falls back to `20`** |
|
|
187
|
+
| `SETTLEMENT_WAIT_BUDGET_MS` | no | Total time `request_ai_birthcert_verification` **and** `check_ai_birthcert_verification` will each wait for a queued settlement before returning `{ settlementPending: true }` / `{ status: "settlement_pending" }` — `check_` advances the settlement too, so it can block for this long. The attempt cap alone cannot bound this, because the delay between attempts is server-supplied. At least one poll always happens, even if the budget is shorter than the first retry delay. Not capped at the top end — raising it *and* `MAX_SETTLEMENT_ATTEMPTS` together can reinstate the long blocking call this budget exists to prevent, so raise it deliberately and temporarily. **Defaults to `90000` (90s); a non-positive or unparseable value also falls back to `90000`** |
|
|
188
|
+
| `SETTLEMENT_STUCK_AFTER_MS` | no | How long a settlement SSIVC cannot confirm may stay unresolved before `check_ai_birthcert_verification` stops calling it "still settling" and calls it permanently stuck. SSIVC returns the same `status_code 69` for a settlement two minutes old and one three weeks old, so the receipt's own age is what separates *"payment sent, check back shortly"* from *"this is not coming back, the fee was most likely already taken, and starting over costs a second fee"*. This changes **only the wording**: either side of the line the wallet never pays again and never discards the receipt by itself. **Defaults to `86400000` (24h); a non-positive or unparseable value also falls back to `86400000`** |
|
|
186
189
|
|
|
187
190
|
\* sensitive — never logged, never returned in a tool result, and never a tool parameter.
|
|
188
191
|
|