agentic-wallet-mcp 0.14.1 → 0.14.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +2 -2
- package/dist/server-bundle.cjs +37 -16
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [0.14.2] — 13 October 2026
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- **An AI Birthcert request that does not say Basic or Verified is put to the user.** "Get me AI Birth VC" was answered with the Basic credential in one chat and the Verified one in another: the wallet does not read the request, the agent chooses by the tool and credential it names first, and nothing told it which or asked the user. Every AI Birthcert `credential_preflight` result now carries a `choice` note, and the tool text and the plugin skill say the same: check what the wallet already holds, explain the two kinds in plain words, offer only what it does not hold, ask which the user prefers, and, if they want both, issue them one after the other, Basic first. The older sentence in `request_ai_birthcert_verification` that said the user "most likely wants" the Basic one, and to use `subscribe_and_issue`, is replaced by the same rule: if the request does not say which kind, do not start it, check both and ask. Each kind has its own price and needs its own yes, so "both" is not a yes to either payment. Where the Verified kind is not configured (mainnet, by default), the note says to offer Basic only. `prove_identity` now says what to do when several credentials are held: pass one, prefer the Verified one when the request names none, and say which was presented.
|
|
18
|
+
|
|
19
|
+
- **The Basic AI Birthcert's testnet pass design was updated.** The Basic AI Birthcert is now issued on testnet with the new pass-design image id, so the card image that comes back with the credential is the current one. Mainnet and other templates are unchanged.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- **The agent no longer asks again for a name the user has already given.** Asked for `agentUsername`, a user answered "QA Basic VC" twice and the agent kept asking, because the rule "never invent a name" said nothing about a short answer that repeats the question. An answer is now the name: the agent uses it as given and does not ask for it again (unless it was refused), tidying it is optional and the agent waits for a yes before using a tidied form, it never goes ahead on a name or a payment the user has not agreed to, and it treats any example it gives as only an example of the format.
|
|
24
|
+
- **The agent no longer shows the raw `paymentRequired` field name to the user.** QA saw "issuance is currently free (paymentRequired: false)": the wallet's own agent-facing text used the raw MBI field name as vocabulary, and a preflight `notChecked` item that the agent is told to relay contained it. `notChecked` no longer names the field, and the preflight and dry-run descriptions tell the agent to say free or chargeable in plain words and never to quote JSON field names.
|
|
25
|
+
|
|
13
26
|
## [0.14.1] — 12 October 2026
|
|
14
27
|
|
|
15
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ VC issuance → identity proof → pay-per-use).
|
|
|
21
21
|
| Tool | Does | Input | Output (shape) |
|
|
22
22
|
|---|---|---|---|
|
|
23
23
|
| `wallet_status` | Report holder DID/address/network + held VCs (client-supplied, or the local cache); optionally one token balance (`token`) or several in one call (`tokens`). Each balance carries `balance` (raw base units), `decimals` and `display` — the same amount in whole tokens with its symbol. Quote `display`; a raw count beside a ticker is wrong by orders of magnitude. A token may be named by ticker **or** contract address, and a ZTP20 result also carries its contract address as `tokenAddress` — the value a policy needs, so it never has to be asked for | `{ heldCredentials?, token?, tokens? }` | `{ holderDid, zetrixAddress, network, credentials, balances?, tokenBalance?, tokenBalances? }` |
|
|
24
|
-
| `credential_preflight` | **Free.** The first call for any credential — composes the quote, the balances and the spending cap into one answer, before a single application field is collected. Spends nothing, starts nothing. `blockers` lists *every* reason the wallet is not ready, at once; `notChecked` lists what preflight cannot know — agent-name availability is decided by myid at issuance, after payment, so a `ready` result is never a reservation. **It also says when the wallet already holds a valid copy of the credential** (`alreadyHeld`, with `ready: false`): it looks at the credentials the wallet has saved, locally and for free, before pricing anything, so the agent stops with "you already have one" instead of asking for an agent name. Buying another would replace it (one credential per template) and costs the fee; only when the user explicitly wants a replacement is it run again with `replacing: true`. An expired credential does not count, and a lookup that fails is reported in `notChecked`, never as "nothing is held" | `{ credential, agentName?, replacing? }` | `{ credential, ready, fee?, balances, cap?, schema?, alreadyHeld?, blockers, notChecked }` |
|
|
24
|
+
| `credential_preflight` | **Free.** The first call for any credential — composes the quote, the balances and the spending cap into one answer, before a single application field is collected. Spends nothing, starts nothing. `blockers` lists *every* reason the wallet is not ready, at once; `notChecked` lists what preflight cannot know — agent-name availability is decided by myid at issuance, after payment, so a `ready` result is never a reservation. **It also says when the wallet already holds a valid copy of the credential** (`alreadyHeld`, with `ready: false`): it looks at the credentials the wallet has saved, locally and for free, before pricing anything, so the agent stops with "you already have one" instead of asking for an agent name. Buying another would replace it (one credential per template) and costs the fee; only when the user explicitly wants a replacement is it run again with `replacing: true`. An expired credential does not count, and a lookup that fails is reported in `notChecked`, never as "nothing is held". When a user asks for an AI Birthcert without saying Basic or Verified, every result carries a `choice` note: the agent checks both kinds, explains the difference, and asks which they prefer; if they want both, it issues them one after the other, Basic first. | `{ credential, agentName?, replacing? }` | `{ credential, ready, fee?, balances, cap?, schema?, alreadyHeld?, blockers, notChecked, choice? }` |
|
|
25
25
|
| `prove_identity` | Answer an x401 `PROOF-REQUEST` → return the `PROOF-RESPONSE` header to replay | `{ proofRequest, vc?, revealAttribute?, issuerKeys? }` | `{ proofResponseHeader, verified, presentationId }` |
|
|
26
26
|
| `create_verification_qr` | Create a link and a QR code that open this wallet's credential in the MyID app, for a human to verify the agent. Presents the credential to MBI — with no `vc` given, the Verified AI Birthcert if the wallet holds one, otherwise the Basic AI Birthcert, and if it holds neither it answers `created: false` and says to create one first. The link holds only the reference id, but that id grants access to whatever is revealed until it expires (5 minutes by default, up to 60), so by default it reveals only a standard minimal set (Verified: `agentName`, `evidenceProvider`, `ownerVerified`; Basic: `agentUsername`) — name other attributes with `revealAttribute`, and pass `revealAll: true` only when the user explicitly asks to reveal everything; show the link only to the human user. The QR code comes back as an image and as a PNG file (`qrCodePath`) that a chat channel such as WhatsApp can attach; a file is removed when the wallet starts and the next time a QR is made, once its link has expired. The file is on the wallet's own machine, so a client that runs the wallet remotely cannot read the path and gets the image block and the link instead. The agent is told never to send another image as the QR code, and to give the link and say so if it cannot attach one. When the credential has a saved pass design, the result also carries its path (`vcPassImagePaths`), so the agent can show both pictures, each captioned for what it is. A Basic credential does not mean the owner was verified, and the result says so. Needs `MYID_VERIFY_LINK_TEMPLATE`; without it the tool answers `created: false` before anything is created | `{ vc?, revealAttribute?, revealAll?, expiryMinutes? }` | `{ created, link, referenceId, expiresAt, expiresInMinutes, revealed (the attribute paths, or `"all"`), credentialUsed, revealedByDefault, qrCodePngBase64 (sent as an image; absent with a `qrError` if it could not be drawn), message }` or `{ created: false, reason }` |
|
|
27
27
|
| `pay_and_fetch` | Fetch a URL, auto-pay with x402 (self-pay via Wallet BE) on `402` | `{ url, method?, headers?, body? }` | `{ status, body, paymentMade, amountPaid, amountPaidHuman, asset }` |
|
|
@@ -204,7 +204,7 @@ Node ≥ 18 required (built-in `fetch`).
|
|
|
204
204
|
| `ZID_RESOLVER_BASE_URL` | no | ZID resolver override (auto-derived from network: sandbox for testnet, prod for mainnet) |
|
|
205
205
|
| `MAX_PAYMENT_AMOUNT` | no** | Per-asset x402 auto-pay cap — JSON `{ "<asset>": "<maxRawUnits>", "*": "<fallback>" }`. `pay_and_fetch`/`subscribe_and_issue` are asset-agnostic: the resource server's 402 challenge may quote the native ZETRIX token (asset code `ZTX`) **or** a ZTP20 token (e.g. `JMYR`) — cap whichever assets you expect. **Either the ticker or the contract address works** — the challenge identifies a ZTP20 token by its contract address, and the wallet resolves a known ticker (e.g. `JMYR`) to it. If both are written for the same asset, the contract address wins. An unrecognised ticker still matches nothing and falls through to `"*"`. e.g. `{"ZTX":"1000000000","ZTX3WeinXtt28YMyr4vUZ14ddTgEMGeuc1e6b":"5000000","*":"0"}`. **Default when unset:** both networks allow exactly the AI Birthcert fee (1 JMYR), keyed to that network's JMYR contract, and refuse everything else. **The cap is per call, not cumulative** — so an unconfigured wallet, mainnet included, can pay that fee once per call with no overall ceiling. Set this explicitly to lock a wallet down. **A spending policy stands the DEFAULT cap aside for an asset it governs** (an `assetScope` for that asset, a `perTransactionMax`, and no block range), so the owner's own limit applies instead of a 1 JMYR default underneath it; an explicit `MAX_PAYMENT_AMOUNT` is never bypassed, and a failed read of the policy list leaves the cap in force. The policy is only as strong as Wallet BE's enforcement of it, which is off in prod as shipped. **The agent could write such a policy itself**, so `write_policy` pays and writes only with `confirm: true`, which the user must have given after seeing the interpretation and the price; the wallet cannot verify a person said yes, it is the same instruction-level gate `transfer_token` uses. Collecting a write that was paid for elsewhere needs the same confirmation, and `pay_and_fetch` refuses the policy-write service's paid paths. |
|
|
206
206
|
| `ZETRIX_WALLET_STATE_DIR` | no | Where the wallet keeps `account.json` and its VC cache. Defaults to `~/.agentic-wallet-mcp` |
|
|
207
|
-
| `SSIVC_BASE_URL` | no | myid's SSIVC API base URL, for the Verified AI Birthcert flow (`request_ai_birthcert_verification`/`check_ai_birthcert_verification`). **
|
|
207
|
+
| `SSIVC_BASE_URL` | no | myid's SSIVC API base URL, for the Verified AI Birthcert flow (`request_ai_birthcert_verification`/`check_ai_birthcert_verification`). **Testnet: derived** (`https://ssivc-api-uat.myegdev2.com/api`). **There is no default on mainnet**: its candidate host (`https://verifyid-api.zetrix.com/api`) was never confirmed, so it is kept in code but not used and the Verified AI Birthcert check is off there until `SSIVC_BASE_URL` is set. Override on either network if the host changes |
|
|
208
208
|
| `MYID_VERIFY_LINK_TEMPLATE` | no | The link `create_verification_qr` gives the user, with `{referenceId}` where the MBI reference id goes — MyID's universal link, e.g. `https://<MyID link domain>/<path>?referenceId={referenceId}` — must be `https`, with the placeholder in the path or query (not the host); a template that breaks this is warned about at startup and refused by the tool. **Defaults on testnet** to the UAT link the MyID app is registered for, `https://ssivc-api-uat.myegdev2.com/api/agentic-verify?referenceId={referenceId}` (read from that host's `apple-app-site-association`, which claims exactly that path and query). **No default on mainnet** until MyID's production side is verified: MyID has stated `https://myid-verifier.zetrix.com/api/agentic-verify?referenceId={referenceId}`, but it was not deployed when this was written, so the tool refuses before it creates anything rather than hand out a link that may not open. Set this variable to use it (or any other link) there; it also overrides the testnet default |
|
|
209
209
|
| `POLICY_DECISION_URL` | no | Base URL of the policy DECISION service, for `check_policy_decision`. **No default**: the endpoint sits behind an authenticated path this wallet has no credential for, so guessing a host would turn "nobody has wired this up" into a connection error. With none configured the tool answers `undetermined` and says why |
|
|
210
210
|
| `POLICY_DECISION_AUTH` | no* | `Authorization` header value for the policy decision service (e.g. `Bearer …`). Without it the service answers 401 and the tool reports that the wallet is not authorised — not that the request was wrong |
|
package/dist/server-bundle.cjs
CHANGED
|
@@ -31391,7 +31391,7 @@ var import_node_path10 = require("node:path");
|
|
|
31391
31391
|
// package.json
|
|
31392
31392
|
var package_default = {
|
|
31393
31393
|
name: "agentic-wallet-mcp",
|
|
31394
|
-
version: "0.14.
|
|
31394
|
+
version: "0.14.2",
|
|
31395
31395
|
description: "Agent-facing MCP wallet for Zetrix \u2014 orchestrates x401 identity proof, x402 payment, and MBI VC issuance",
|
|
31396
31396
|
keywords: [
|
|
31397
31397
|
"mcp",
|
|
@@ -41305,6 +41305,12 @@ async function resolveIssuerProofKeys(vc, resolver) {
|
|
|
41305
41305
|
return { bbsPublicKey, ed25519PublicKey };
|
|
41306
41306
|
}
|
|
41307
41307
|
|
|
41308
|
+
// src/orchestrator/birthcert-choice.ts
|
|
41309
|
+
function aiBirthcertChoice(kind, opts = {}) {
|
|
41310
|
+
const note = `AI Birthcert comes in two kinds. BASIC: self-declared by the agent, with no check of the owner's identity; it is quick, shows only the agent's username, and does not mean the owner was verified. VERIFIED: the owner's identity is confirmed through MyDigital ID; the fee is paid up front, the owner completes a check in the MyID app, and the agent name must be unique (the name is only checked after payment, so a name that turns out to be taken is refused late, and whether the fee was spent cannot be confirmed). Each kind has its own price, read from the check for that kind: never assume Basic is free. This result is for the ${kind === "basic" ? "BASIC" : "VERIFIED"} one. If the user has not said which kind they want (they did not say "verified" or "basic", and did not mention MyDigital ID or owner verification), do not start either: run this check for both kinds (it is free) to see what the wallet already holds, tell the user the difference in plain words, offer only the kind or kinds they do not already hold, and ask which they prefer. If they want both, issue them one after the other, Basic first, and finish and show the first before starting the second; each has its own price and needs its own yes, so "both" is not a yes to either payment. Holding one kind never blocks the other, and replacing one that is held is its own explicit choice.`;
|
|
41311
|
+
return opts.unavailable ? note + " The Verified kind is not available on this wallet or network: say so, and offer the Basic one only." : note;
|
|
41312
|
+
}
|
|
41313
|
+
|
|
41308
41314
|
// src/mcp-tools.ts
|
|
41309
41315
|
var import_promises4 = require("node:fs/promises");
|
|
41310
41316
|
|
|
@@ -42239,7 +42245,7 @@ var TEMPLATE_ALIASES = [
|
|
|
42239
42245
|
deriveAttributes: { id: "agentUsername" },
|
|
42240
42246
|
validateAttributes: { dob: validateDob, countryOfOrigin: validateCountryOfOrigin },
|
|
42241
42247
|
passDesignId: {
|
|
42242
|
-
testnet: "did:zid:
|
|
42248
|
+
testnet: "did:zid:bb7202482ef6053be6d46ad8e2190b0ba1e3b2024d24ce7f37bc4c3747e2378f",
|
|
42243
42249
|
mainnet: "did:zid:915955cb71c6fd2a256d04344f57381084903cb6a85a1c9ddb71c746f08932ab"
|
|
42244
42250
|
}
|
|
42245
42251
|
}
|
|
@@ -42304,6 +42310,8 @@ async function credentialPreflight(deps, input) {
|
|
|
42304
42310
|
const blockers = [];
|
|
42305
42311
|
const notChecked = [];
|
|
42306
42312
|
const isVerified = input.credential === VERIFIED_AI_BIRTHCERT;
|
|
42313
|
+
const kind = isVerified ? "verified" : deps.isBasicAiBirthcert?.(input.credential) ? "basic" : void 0;
|
|
42314
|
+
const choice = kind ? { choice: aiBirthcertChoice(kind) } : {};
|
|
42307
42315
|
let alreadyHeld;
|
|
42308
42316
|
if (deps.findHeld) {
|
|
42309
42317
|
try {
|
|
@@ -42321,7 +42329,8 @@ async function credentialPreflight(deps, input) {
|
|
|
42321
42329
|
blockers: [
|
|
42322
42330
|
`This wallet already holds a valid ${found.label}${until}${found.vcId ? `, ${found.vcId}` : ""}. Tell the user, and do not start another: a new one would REPLACE it (the wallet keeps one per template) and costs the fee. Only if the user explicitly says they want a replacement, run this check again with replacing: true.`
|
|
42323
42331
|
],
|
|
42324
|
-
notChecked: []
|
|
42332
|
+
notChecked: [],
|
|
42333
|
+
...choice
|
|
42325
42334
|
};
|
|
42326
42335
|
}
|
|
42327
42336
|
} else {
|
|
@@ -42347,7 +42356,8 @@ async function credentialPreflight(deps, input) {
|
|
|
42347
42356
|
...alreadyHeld ? { alreadyHeld } : {},
|
|
42348
42357
|
...schema ? { schema } : {},
|
|
42349
42358
|
blockers: [`Could not price this credential: ${why}`],
|
|
42350
|
-
notChecked: [...notChecked, ...uncheckable(isVerified)]
|
|
42359
|
+
notChecked: [...notChecked, ...uncheckable(isVerified)],
|
|
42360
|
+
...choice
|
|
42351
42361
|
};
|
|
42352
42362
|
}
|
|
42353
42363
|
const asset = String(quote.asset ?? "");
|
|
@@ -42398,7 +42408,8 @@ async function credentialPreflight(deps, input) {
|
|
|
42398
42408
|
...alreadyHeld ? { alreadyHeld } : {},
|
|
42399
42409
|
...schema ? { schema } : {},
|
|
42400
42410
|
blockers,
|
|
42401
|
-
notChecked: [...notChecked, ...gasNotes, ...uncheckable(isVerified, isFree)]
|
|
42411
|
+
notChecked: [...notChecked, ...gasNotes, ...uncheckable(isVerified, isFree)],
|
|
42412
|
+
...choice
|
|
42402
42413
|
};
|
|
42403
42414
|
}
|
|
42404
42415
|
function renderAmount(raw, balance) {
|
|
@@ -42428,7 +42439,7 @@ function uncheckable(isVerified, isFree = false) {
|
|
|
42428
42439
|
}
|
|
42429
42440
|
if (isFree) {
|
|
42430
42441
|
items.unshift(
|
|
42431
|
-
"Whether issuance is still free at apply time \u2014
|
|
42442
|
+
"Whether issuance is still free at apply time \u2014 whether the service charges is a service-wide setting and can change between this quote and issuance."
|
|
42432
42443
|
);
|
|
42433
42444
|
}
|
|
42434
42445
|
return items;
|
|
@@ -46384,7 +46395,14 @@ function createTools(deps) {
|
|
|
46384
46395
|
*/
|
|
46385
46396
|
async credential_preflight(input) {
|
|
46386
46397
|
if (input.credential === VERIFIED_AI_BIRTHCERT && !deps.verifyAiBirthcert) {
|
|
46387
|
-
return {
|
|
46398
|
+
return {
|
|
46399
|
+
credential: input.credential,
|
|
46400
|
+
ready: false,
|
|
46401
|
+
balances: [],
|
|
46402
|
+
blockers: [AI_BIRTHCERT_NOT_CONFIGURED_ERROR],
|
|
46403
|
+
notChecked: [],
|
|
46404
|
+
choice: aiBirthcertChoice("verified", { unavailable: true })
|
|
46405
|
+
};
|
|
46388
46406
|
}
|
|
46389
46407
|
if (!deps.queryTokenBalance) {
|
|
46390
46408
|
return {
|
|
@@ -46395,8 +46413,11 @@ function createTools(deps) {
|
|
|
46395
46413
|
notChecked: []
|
|
46396
46414
|
};
|
|
46397
46415
|
}
|
|
46416
|
+
const basicId = resolveTemplateAlias("ai birthcert", deps.config.network);
|
|
46417
|
+
const isBasicAiBirthcert = (credential) => basicId !== void 0 && (credential === basicId || resolveTemplateAlias(credential, deps.config.network) === basicId);
|
|
46398
46418
|
return credentialPreflight(
|
|
46399
46419
|
{
|
|
46420
|
+
isBasicAiBirthcert,
|
|
46400
46421
|
quoteVerified: (q) => deps.verifyAiBirthcert.request(q),
|
|
46401
46422
|
quoteTemplate: async (templateId) => {
|
|
46402
46423
|
const resolved = resolveTemplateAlias(templateId, deps.config.network) ?? templateId;
|
|
@@ -49506,12 +49527,12 @@ function buildToolList() {
|
|
|
49506
49527
|
},
|
|
49507
49528
|
{
|
|
49508
49529
|
name: "prove_identity",
|
|
49509
|
-
description: "Answer an x401 PROOF-REQUEST and return the PROOF-RESPONSE header to replay to the resource server.",
|
|
49530
|
+
description: "Answer an x401 PROOF-REQUEST and return the PROOF-RESPONSE header to replay to the resource server. If the wallet holds several credentials, pass vc: use the one the request or the verifier's challenge names, and if it names none, prefer the Verified AI Birthcert over the Basic one and say which one you presented.",
|
|
49510
49531
|
inputSchema: {
|
|
49511
49532
|
type: "object",
|
|
49512
49533
|
properties: {
|
|
49513
49534
|
proofRequest: { type: "string", description: "The PROOF-REQUEST header value from the 401 challenge." },
|
|
49514
|
-
vc: { type: "object", description: "The VerifiableCredential to present. Omit to use the wallet's single locally-cached credential, if there is exactly one \u2014 the call fails with a clear error if none or several are cached." },
|
|
49535
|
+
vc: { type: "object", description: "The VerifiableCredential to present. Omit to use the wallet's single locally-cached credential, if there is exactly one \u2014 the call fails with a clear error if none or several are cached, so with several, pass it." },
|
|
49515
49536
|
revealAttribute: { type: "array", items: { type: "string" }, description: "Dotted disclosure paths to reveal. Omit to reveal exactly the claims the challenge (DCQL) requests; a challenge naming no claims reveals all." },
|
|
49516
49537
|
issuerKeys: {
|
|
49517
49538
|
type: "object",
|
|
@@ -49877,7 +49898,7 @@ function buildToolList() {
|
|
|
49877
49898
|
},
|
|
49878
49899
|
{
|
|
49879
49900
|
name: "subscribe_and_issue",
|
|
49880
|
-
description: "Obtain a VC from MBI: build the signed payload, pay x402, and return the issued credential. If a spending policy refuses the fee, the result has `policyDenied: true` (a decision: do not retry) or `policyCheckUnavailable: true` (transient: trying again shortly is right); either way nothing was paid and no credential was issued. If a still-valid credential for this templateId is already cached locally, it is returned directly with no payment (fromCache: true). Setting forceReissue:true alone does NOT pay again \u2014 it only asks to be shown that existing credential first: you get back { issued: false, vcId, vc, fromCache: true, reason } instead, and nothing is paid. Show that existing credential to the user and ask whether they actually want to replace it; only call this tool again, with BOTH forceReissue:true and confirmReplaceExistingVc set to exactly the vcId you were shown, if they explicitly say yes. Never pass confirmReplaceExistingVc on your own judgement. When nothing valid is cached, forceReissue has no effect either way \u2014 that case has always paid and issued fresh. When a call DOES render a full credential to the user (a fresh issuance, a plain cache hit, or a confirmed replace), show every claim under vc.credentialSubject as a table \u2014 not a cherry-picked subset \u2014 labelling each key by title-casing it (the exact claim set varies by template; use schema.required/optional to know what to expect), plus vcId and validUntil if present. If vcPassImagePaths is also present, the credential's own pass-design image(s) came back attached to this result \u2014 tell the user their credential's official pass design is shown below and display the image(s); do not silently drop them from your summary just because they are not text. Payment is asset-agnostic \u2014 MBI's 402 challenge may quote the native ZETRIX token or a ZTP20 token (e.g. JMYR); pass dryRun:true first to see the quoted asset/amount for free before committing to pay. What a call actually cost is reported precisely: paidAsset/amountPaid are set ONLY when this call paid, a cache hit reports the earlier charge under originalPayment instead (never as amountPaid, so summing spend cannot double-count), and any failure after the payment has settled on chain reports paymentAttempted: { asset, amount, paymentId }. Two such failures exist and mean different things: MBI 4006 is a definitive facilitator rejection, while 4012 (HTTP 502) means the outcome is INDETERMINATE \u2014 the payment may well have landed. On 4012 the wallet automatically polls MBI's recovery endpoint and reports recovery: { status, txHash?, vcId?, polls }, where status is ISSUED (the credential exists after all \u2014 fetch it by vcId, since recovery returns no VC body), FAILED, or REQUIRED/SETTLED (still unresolved) / UNKNOWN (recovery itself unreachable). NEVER retry a payment after either failure: the funds may already be gone, and a retry charges the full amount again \u2014 look the paymentId up instead. Every response also includes { schema: { required, optional } } whenever the template schema could be read from chain \u2014 the template's full declared attribute list, so you see the complete field list, not just what went wrong. For the AI Birthcert specifically: this issues the BASIC one \u2014 self-declared by the agent, agent-paid via x402, owner identity NOT identity-verified. If the user asked for a \"verified\" AI birthcert (owner identity confirmed via MyDigital ID), use request_ai_birthcert_verification instead \u2014 this tool cannot produce that credential.",
|
|
49901
|
+
description: "Obtain a VC from MBI: build the signed payload, pay x402, and return the issued credential. If a spending policy refuses the fee, the result has `policyDenied: true` (a decision: do not retry) or `policyCheckUnavailable: true` (transient: trying again shortly is right); either way nothing was paid and no credential was issued. If a still-valid credential for this templateId is already cached locally, it is returned directly with no payment (fromCache: true). Setting forceReissue:true alone does NOT pay again \u2014 it only asks to be shown that existing credential first: you get back { issued: false, vcId, vc, fromCache: true, reason } instead, and nothing is paid. Show that existing credential to the user and ask whether they actually want to replace it; only call this tool again, with BOTH forceReissue:true and confirmReplaceExistingVc set to exactly the vcId you were shown, if they explicitly say yes. Never pass confirmReplaceExistingVc on your own judgement. When nothing valid is cached, forceReissue has no effect either way \u2014 that case has always paid and issued fresh. When a call DOES render a full credential to the user (a fresh issuance, a plain cache hit, or a confirmed replace), show every claim under vc.credentialSubject as a table \u2014 not a cherry-picked subset \u2014 labelling each key by title-casing it (the exact claim set varies by template; use schema.required/optional to know what to expect), plus vcId and validUntil if present. If vcPassImagePaths is also present, the credential's own pass-design image(s) came back attached to this result \u2014 tell the user their credential's official pass design is shown below and display the image(s); do not silently drop them from your summary just because they are not text. Payment is asset-agnostic \u2014 MBI's 402 challenge may quote the native ZETRIX token or a ZTP20 token (e.g. JMYR); pass dryRun:true first to see the quoted asset/amount for free before committing to pay. What a call actually cost is reported precisely: paidAsset/amountPaid are set ONLY when this call paid, a cache hit reports the earlier charge under originalPayment instead (never as amountPaid, so summing spend cannot double-count), and any failure after the payment has settled on chain reports paymentAttempted: { asset, amount, paymentId }. Two such failures exist and mean different things: MBI 4006 is a definitive facilitator rejection, while 4012 (HTTP 502) means the outcome is INDETERMINATE \u2014 the payment may well have landed. On 4012 the wallet automatically polls MBI's recovery endpoint and reports recovery: { status, txHash?, vcId?, polls }, where status is ISSUED (the credential exists after all \u2014 fetch it by vcId, since recovery returns no VC body), FAILED, or REQUIRED/SETTLED (still unresolved) / UNKNOWN (recovery itself unreachable). NEVER retry a payment after either failure: the funds may already be gone, and a retry charges the full amount again \u2014 look the paymentId up instead. Every response also includes { schema: { required, optional } } whenever the template schema could be read from chain \u2014 the template's full declared attribute list, so you see the complete field list, not just what went wrong. For the AI Birthcert specifically: this issues the BASIC one \u2014 self-declared by the agent, agent-paid via x402, owner identity NOT identity-verified. If the user asked for a \"verified\" AI birthcert (owner identity confirmed via MyDigital ID), use request_ai_birthcert_verification instead \u2014 this tool cannot produce that credential. If the user did not say which kind, ask first: see the `choice` note in credential_preflight.",
|
|
49881
49902
|
inputSchema: {
|
|
49882
49903
|
type: "object",
|
|
49883
49904
|
properties: {
|
|
@@ -49887,12 +49908,12 @@ function buildToolList() {
|
|
|
49887
49908
|
},
|
|
49888
49909
|
attributes: {
|
|
49889
49910
|
type: "object",
|
|
49890
|
-
description: `Claim values for the credential (schema varies by template \u2014 check what the issuer requires before guessing). ALWAYS ask the human owner directly for any name/identifier-type value (e.g. an agentUsername or similar field) \u2014 NEVER invent, guess, or silently reuse one of your own choosing; if the template requires one, get it from the user first. "agentDid" is the one exception: it does not need to be supplied, since it is auto-filled with this wallet's own holder DID (the credential's self-referential subject) unless you explicitly override it.`
|
|
49911
|
+
description: `Claim values for the credential (schema varies by template \u2014 check what the issuer requires before guessing). ALWAYS ask the human owner directly for any name/identifier-type value (e.g. an agentUsername or similar field) \u2014 NEVER invent, guess, or silently reuse one of your own choosing; if the template requires one, get it from the user first. When the user answers with a name \u2014 even a short phrase, even one that repeats words from your question \u2014 that IS the name: use it as given and do not ask for it again, unless it was refused (for example already in use). Tidying it (spaces or capitals, say) is optional and never needed; if you do want to suggest a tidier form, ask and WAIT for their answer, and use the tidied form only after a yes. Never go ahead on a name, or on a payment, that the user has not agreed to. Any example you give is only an example of the format, not a suggestion to use. "agentDid" is the one exception: it does not need to be supplied, since it is auto-filled with this wallet's own holder DID (the credential's self-referential subject) unless you explicitly override it.`
|
|
49891
49912
|
},
|
|
49892
49913
|
expirationDate: { type: "string" },
|
|
49893
49914
|
dryRun: {
|
|
49894
49915
|
type: "boolean",
|
|
49895
|
-
description: "Price the credential without paying, signing, or issuing anything. Returns { quote: { asset, maxAmountRequired, payTo, gasModel, paymentRequired? }, schema: { required, optional } }. Priced via MBI's /quote endpoint, which cannot issue \u2014 so this is safe even on a template that issues for free (such a template mints synchronously on the real path, which is why pricing never goes through it). Never writes the VC cache, so it cannot displace a credential you already hold. `quote.paymentRequired` is the authoritative free-vs-paid answer: false means issuance is currently free and `maxAmountRequired` will not be charged. When the field is ABSENT the MBI predates it and the amount is unconfirmed \u2014 report it as a possible charge, never as certainly free. Still validates required attributes locally first \u2014 a missing one blocks before any MBI call."
|
|
49916
|
+
description: "Price the credential without paying, signing, or issuing anything. Returns { quote: { asset, maxAmountRequired, payTo, gasModel, paymentRequired? }, schema: { required, optional } }. Priced via MBI's /quote endpoint, which cannot issue \u2014 so this is safe even on a template that issues for free (such a template mints synchronously on the real path, which is why pricing never goes through it). Never writes the VC cache, so it cannot displace a credential you already hold. `quote.paymentRequired` is the authoritative free-vs-paid answer: false means issuance is currently free and `maxAmountRequired` will not be charged. When the field is ABSENT the MBI predates it and the amount is unconfirmed \u2014 report it as a possible charge, never as certainly free. Tell the user in plain words that it is free or chargeable; never quote JSON field names such as paymentRequired to them. Still validates required attributes locally first \u2014 a missing one blocks before any MBI call."
|
|
49896
49917
|
},
|
|
49897
49918
|
forceReissue: {
|
|
49898
49919
|
type: "boolean",
|
|
@@ -49908,13 +49929,13 @@ function buildToolList() {
|
|
|
49908
49929
|
},
|
|
49909
49930
|
{
|
|
49910
49931
|
name: "request_ai_birthcert_verification",
|
|
49911
|
-
description: 'Start a Verified AI Birthcert issuance session with myid (MyDigital ID owner verification). ALWAYS run credential_preflight for "verified_ai_birthcert" immediately before calling this, even if you checked earlier in the conversation \u2014 preflight is free, this tool spends real funds, and a balance the user topped up a minute ago is not the balance you read before that. If a spending policy refuses the session fee, the result is { error } with `policyDenied: true` (a decision: do not retry) or `policyCheckUnavailable: true` (transient: trying again shortly is right); either way nothing was paid and no session was created. Returns { sessionId, verificationUrl, expiresAt, expiresIn, expiresInSeconds, message } \u2014 show verificationUrl to the human owner and ask them to open it and complete MyDigital ID verification (typically finishes in seconds). Tell them how long the link is good for by quoting `expiresIn` exactly as given: the wallet works it out from its own clock, so never calculate the time remaining yourself from `expiresAt` \u2014 your clock and timezone may differ from the server\'s. `message` here contains a "Tell the user:" sentence about following up \u2014 relay it rather than composing your own reassurance. Once they confirm they are done, call check_ai_birthcert_verification to see whether the credential was issued. Nothing keeps running after this call returns \u2014 there is no background polling, webhook, or timer, so you can only check status when the user sends you a new message. NEVER tell the user you have "set up an automation" or that you will "alert them" when it completes \u2014 you cannot act on your own between messages, and promising that leaves them waiting for a notification that will never come. Instead, tell them how long the link is good for and ask them to message you back once done (or after a few minutes) so you can check_ai_birthcert_verification again. ALWAYS ask the human owner directly what agentName they want to use for a NEW session \u2014 NEVER invent, guess, or silently choose one yourself. (Calling again with the SAME name to resume an already-pending session, as described below, is not "inventing" one \u2014 that is reusing the exact name the owner already gave.) IMPORTANT: agentName must be unique \u2014 if this exact name has already been used to request a Verified AI Birthcert, issuance will fail. Before calling, ask the human owner whether they want to supply any of the optional fields \u2014 agentPurpose, evidenceAssuranceLevel, ownerType, ownerVerified \u2014 do not silently omit them; they only need to say no. Calling this again with the SAME agentName while a prior session is still pending returns that same session unchanged \u2014 no new session is started and nothing is paid again. This tool spends real funds: it self-pays an x402 challenge, subject to the same credential-issuance payment cap as subscribe_and_issue, which by default allows exactly 1 JMYR per call. Set MAX_PAYMENT_AMOUNT to override it; a spending policy that governs the asset replaces the default cap. It can return { error: "..." } instead of a session. Read `message` before deciding what to tell the user or whether retrying is safe \u2014 it does NOT always mean nothing was paid. For insufficient funds or a payment-cap block specifically, nothing is created and nothing was paid, so once the underlying problem is fixed (e.g. the user tops up), calling this tool again is the right next step. Several OTHER { error } shapes mean the opposite: a payment may already have been sent on a prior or even this call (blob_already_settled, a receipt that could not be saved locally, RECEIPT VOID, OUTCOME UNKNOWN) \u2014 for any of those, calling this tool again pays the fee AGAIN, so do NOT retry without explicit agreement from the user, exactly as `message` itself will say. It can also return { settlementPending: true, paymentReceipt, message } instead \u2014 a payment WAS SENT and no session exists yet. That is NOT a failure and NOT an error, but do NOT pay again and do NOT call this tool again to retry it \u2014 call check_ai_birthcert_verification to follow it through instead. It covers three different situations, told apart by the `issuerRejected` and `paymentInvalid` fields. With neither set, do NOT assume the payment is known to have succeeded \u2014 this shape covers TWO different states that look identical from these fields alone: usually the settlement is genuinely still clearing (the message says "still being processed"), but sometimes the outcome could not be determined at all yet (the message says "has not been confirmed yet" and does not say "still being processed") \u2014 an indeterminate state, not a confirmed one, even though neither flag is set. Either way the receipt is saved and you must not pay again, so report it as "payment sent, still settling" without promising the user it definitely succeeded. When the message contains a "Tell the user:" sentence, relay that sentence rather than composing your own reassurance, and if asked what the service said, quote only what the message says it answered. With issuerRejected: true the credential service was reached and refused the request \u2014 the settlement is NOT what failed, but do NOT describe this as the payment having succeeded either: `message` quotes its reason, and you must relay that reason rather than describing it as still settling or as a success. With paymentInvalid: true the service has specifically ruled the payment or receipt invalid \u2014 do NOT say "the settlement is not what failed" for this one, since this verdict IS about the payment; relay what it said instead, and do NOT describe it as a success either. Neither this case nor issuerRejected tells you whether the fee was taken, in either direction \u2014 never tell the user they were not charged, and just as much, never tell them they WERE charged either. That no-claim rule covers issuerRejected and paymentInvalid specifically. The plain no-flag case above is different again, and NOT simply "known to have succeeded" either \u2014 see the note on it above: it is two states, only one of which is confirmed, so read `message` there too rather than assuming success from the shape alone. If the user
|
|
49932
|
+
description: 'Start a Verified AI Birthcert issuance session with myid (MyDigital ID owner verification). ALWAYS run credential_preflight for "verified_ai_birthcert" immediately before calling this, even if you checked earlier in the conversation \u2014 preflight is free, this tool spends real funds, and a balance the user topped up a minute ago is not the balance you read before that. If a spending policy refuses the session fee, the result is { error } with `policyDenied: true` (a decision: do not retry) or `policyCheckUnavailable: true` (transient: trying again shortly is right); either way nothing was paid and no session was created. Returns { sessionId, verificationUrl, expiresAt, expiresIn, expiresInSeconds, message } \u2014 show verificationUrl to the human owner and ask them to open it and complete MyDigital ID verification (typically finishes in seconds). Tell them how long the link is good for by quoting `expiresIn` exactly as given: the wallet works it out from its own clock, so never calculate the time remaining yourself from `expiresAt` \u2014 your clock and timezone may differ from the server\'s. `message` here contains a "Tell the user:" sentence about following up \u2014 relay it rather than composing your own reassurance. Once they confirm they are done, call check_ai_birthcert_verification to see whether the credential was issued. Nothing keeps running after this call returns \u2014 there is no background polling, webhook, or timer, so you can only check status when the user sends you a new message. NEVER tell the user you have "set up an automation" or that you will "alert them" when it completes \u2014 you cannot act on your own between messages, and promising that leaves them waiting for a notification that will never come. Instead, tell them how long the link is good for and ask them to message you back once done (or after a few minutes) so you can check_ai_birthcert_verification again. ALWAYS ask the human owner directly what agentName they want to use for a NEW session \u2014 NEVER invent, guess, or silently choose one yourself. (Calling again with the SAME name to resume an already-pending session, as described below, is not "inventing" one \u2014 that is reusing the exact name the owner already gave.) IMPORTANT: agentName must be unique \u2014 if this exact name has already been used to request a Verified AI Birthcert, issuance will fail. Before calling, ask the human owner whether they want to supply any of the optional fields \u2014 agentPurpose, evidenceAssuranceLevel, ownerType, ownerVerified \u2014 do not silently omit them; they only need to say no. Calling this again with the SAME agentName while a prior session is still pending returns that same session unchanged \u2014 no new session is started and nothing is paid again. This tool spends real funds: it self-pays an x402 challenge, subject to the same credential-issuance payment cap as subscribe_and_issue, which by default allows exactly 1 JMYR per call. Set MAX_PAYMENT_AMOUNT to override it; a spending policy that governs the asset replaces the default cap. It can return { error: "..." } instead of a session. Read `message` before deciding what to tell the user or whether retrying is safe \u2014 it does NOT always mean nothing was paid. For insufficient funds or a payment-cap block specifically, nothing is created and nothing was paid, so once the underlying problem is fixed (e.g. the user tops up), calling this tool again is the right next step. Several OTHER { error } shapes mean the opposite: a payment may already have been sent on a prior or even this call (blob_already_settled, a receipt that could not be saved locally, RECEIPT VOID, OUTCOME UNKNOWN) \u2014 for any of those, calling this tool again pays the fee AGAIN, so do NOT retry without explicit agreement from the user, exactly as `message` itself will say. It can also return { settlementPending: true, paymentReceipt, message } instead \u2014 a payment WAS SENT and no session exists yet. That is NOT a failure and NOT an error, but do NOT pay again and do NOT call this tool again to retry it \u2014 call check_ai_birthcert_verification to follow it through instead. It covers three different situations, told apart by the `issuerRejected` and `paymentInvalid` fields. With neither set, do NOT assume the payment is known to have succeeded \u2014 this shape covers TWO different states that look identical from these fields alone: usually the settlement is genuinely still clearing (the message says "still being processed"), but sometimes the outcome could not be determined at all yet (the message says "has not been confirmed yet" and does not say "still being processed") \u2014 an indeterminate state, not a confirmed one, even though neither flag is set. Either way the receipt is saved and you must not pay again, so report it as "payment sent, still settling" without promising the user it definitely succeeded. When the message contains a "Tell the user:" sentence, relay that sentence rather than composing your own reassurance, and if asked what the service said, quote only what the message says it answered. With issuerRejected: true the credential service was reached and refused the request \u2014 the settlement is NOT what failed, but do NOT describe this as the payment having succeeded either: `message` quotes its reason, and you must relay that reason rather than describing it as still settling or as a success. With paymentInvalid: true the service has specifically ruled the payment or receipt invalid \u2014 do NOT say "the settlement is not what failed" for this one, since this verdict IS about the payment; relay what it said instead, and do NOT describe it as a success either. Neither this case nor issuerRejected tells you whether the fee was taken, in either direction \u2014 never tell the user they were not charged, and just as much, never tell them they WERE charged either. That no-claim rule covers issuerRejected and paymentInvalid specifically. The plain no-flag case above is different again, and NOT simply "known to have succeeded" either \u2014 see the note on it above: it is two states, only one of which is confirmed, so read `message` there too rather than assuming success from the shape alone. If the request does not say which kind of AI Birthcert the user wants, do not start this: run credential_preflight for both kinds and ask which they prefer (see its `choice` note), and use this tool only for the Verified kind; if they want the self-declared, non-verified Basic one, use subscribe_and_issue for that. BEFORE this pays or starts a session, it checks whether this holder already has a Verified AI Birthcert \u2014 found in the local cache, or (if the cache has not seen it yet) resolved from a previously-issued session. If one exists and is STILL VALID, nothing is paid and no session is started \u2014 you get back { existingVerifiedVc: { vcId, validUntil }, message } instead. Show that existing credential to the user and ask whether they actually want to replace it; only call this tool again, with confirmReplaceExistingVc set to exactly existingVerifiedVc.vcId, if they explicitly say yes. Never pass confirmReplaceExistingVc on your own judgement. If the existing VC has already EXPIRED, this proceeds automatically \u2014 no confirmation needed \u2014 and the result carries replacedExpiredVc: { vcId, validUntil } naming the one it replaced. That field can appear on a settled session, on a payment still settling, or on an EARLIER call\'s still-pending session simply being returned unchanged \u2014 so treat it only as "the holder\'s old VC had expired", never as proof that THIS call itself just spent money; read the rest of the result (an error, a settled session, or settlementPending) to know what this call actually did. It can also return { error } specifically because an already-issued VC exists but could not be confirmed as valid or expired (a resolution problem, not a payment problem) \u2014 nothing is paid on that path either; relay `error` as given, since it names the concrete next step (retry check_ai_birthcert_verification, or as a last resort clear_stuck_payment_receipt with the user\'s explicit agreement).',
|
|
49912
49933
|
inputSchema: {
|
|
49913
49934
|
type: "object",
|
|
49914
49935
|
properties: {
|
|
49915
49936
|
agentName: {
|
|
49916
49937
|
type: "string",
|
|
49917
|
-
description: "A unique, human-readable name for this agent. Must not already be in use for a Verified AI Birthcert, or issuance will fail. ALWAYS ask the human owner directly which name to use for a new session \u2014 NEVER invent, guess, or silently choose one yourself."
|
|
49938
|
+
description: "A unique, human-readable name for this agent. Must not already be in use for a Verified AI Birthcert, or issuance will fail. ALWAYS ask the human owner directly which name to use for a new session \u2014 NEVER invent, guess, or silently choose one yourself. When the user answers with a name \u2014 even a short phrase, even one that repeats words from your question \u2014 that IS the name: use it as given and do not ask for it again, unless it was refused (for example already in use). Tidying it (spaces or capitals, say) is optional and never needed; if you do want to suggest a tidier form, ask and WAIT for their answer, and use the tidied form only after a yes. Never go ahead on a name, or on a payment, that the user has not agreed to. Any example you give is only an example of the format, not a suggestion to use."
|
|
49918
49939
|
},
|
|
49919
49940
|
agentPurpose: { type: "string", description: 'Optional \u2014 what this agent does, e.g. "Negotiate and settle supplier invoices".' },
|
|
49920
49941
|
evidenceAssuranceLevel: { type: "string", description: 'Optional \u2014 assurance level of the identity evidence, e.g. "high".' },
|
|
@@ -49943,13 +49964,13 @@ function buildToolList() {
|
|
|
49943
49964
|
},
|
|
49944
49965
|
{
|
|
49945
49966
|
name: "credential_preflight",
|
|
49946
|
-
description: "FREE readiness check \u2014 call this FIRST, before collecting ANY application detail from the user, whenever they ask for a credential. Spends nothing, signs no transaction, creates no session. Returns { ready, fee, balances, cap, schema?, alreadyHeld?, blockers, notChecked }: the live fee and which side pays gas, the balances that matter, whether the spending limit permits it, and \u2014 for a template credential \u2014 the attributes it requires. `blockers` lists EVERY reason it is not ready at once (a low balance and a too-low spending limit are different problems and both appear together), so one round of fixes is enough rather than discovering them one failed payment at a time. ALWAYS relay `notChecked` too: a clean result is not a guarantee. In particular it does NOT check whether an agent name is free \u2014 myid decides that at issuance, after payment. Report `fee.display` and each balance's `display` to the user, never the raw base-unit numbers. `fee.paymentRequired: false` means issuance is currently FREE \u2014 `fee.display` is then only what it WOULD cost if payment were switched back on, so do not ask the user to fund it and do not present that amount as a charge. A free credential sends no transaction, so no gas is spent and a missing ZTX balance is not a blocker on it: never ask the user to fund ZTX for a free credential, and if notChecked mentions ZTX, pass it on as a note only. When the field is ABSENT the cost is unknown (an older MBI), and it is treated as chargeable \u2014 never report absent as free. If the result has `alreadyHeld`, this wallet already holds a valid copy of that credential: tell the user so, name it, and stop \u2014 do not ask for an agent name or any other detail, and do not begin an issuance. A new one would replace it. Only when the user has explicitly said they want a replacement, run this check with replacing: true.",
|
|
49967
|
+
description: "FREE readiness check \u2014 call this FIRST, before collecting ANY application detail from the user, whenever they ask for a credential. Spends nothing, signs no transaction, creates no session. Returns { ready, fee, balances, cap, schema?, alreadyHeld?, blockers, notChecked }: the live fee and which side pays gas, the balances that matter, whether the spending limit permits it, and \u2014 for a template credential \u2014 the attributes it requires. `blockers` lists EVERY reason it is not ready at once (a low balance and a too-low spending limit are different problems and both appear together), so one round of fixes is enough rather than discovering them one failed payment at a time. ALWAYS relay `notChecked` too: a clean result is not a guarantee. In particular it does NOT check whether an agent name is free \u2014 myid decides that at issuance, after payment. Report `fee.display` and each balance's `display` to the user, never the raw base-unit numbers. `fee.paymentRequired: false` means issuance is currently FREE \u2014 `fee.display` is then only what it WOULD cost if payment were switched back on, so do not ask the user to fund it and do not present that amount as a charge. Tell the user in plain words that it is free or chargeable; never quote JSON field names such as paymentRequired to them. A free credential sends no transaction, so no gas is spent and a missing ZTX balance is not a blocker on it: never ask the user to fund ZTX for a free credential, and if notChecked mentions ZTX, pass it on as a note only. When the field is ABSENT the cost is unknown (an older MBI), and it is treated as chargeable \u2014 never report absent as free. If the result has `alreadyHeld`, this wallet already holds a valid copy of that credential: tell the user so, name it, and stop \u2014 do not ask for an agent name or any other detail, and do not begin an issuance. A new one would replace it. That stop applies to that credential only: the `choice` note still applies to the other kind. Only when the user has explicitly said they want a replacement, run this check with replacing: true. When a user asks for an AI Birthcert and the request does not say which kind they want (Basic, which is self-declared, or Verified, through MyDigital ID), do not pick one: follow the `choice` note in the result, which is to run this check for both kinds, tell the user the difference in plain words, and ask which they prefer.",
|
|
49947
49968
|
inputSchema: {
|
|
49948
49969
|
type: "object",
|
|
49949
49970
|
properties: {
|
|
49950
49971
|
credential: {
|
|
49951
49972
|
type: "string",
|
|
49952
|
-
description: 'Which credential to price: "verified_ai_birthcert" for the MyDigital-ID-verified AI Birthcert, or a template id (did:zid:...) / known template name
|
|
49973
|
+
description: 'Which credential to price: "verified_ai_birthcert" for the VERIFIED (MyDigital-ID-verified) AI Birthcert, or a template id (did:zid:...) / known template name for a template-issued one \u2014 "AI Birthcert" is the BASIC, self-declared one. For the Verified one use exactly "verified_ai_birthcert": any name containing "birthcert" is priced as the Basic one.'
|
|
49953
49974
|
},
|
|
49954
49975
|
agentName: {
|
|
49955
49976
|
type: "string",
|