Skip to main content
Glama

create_card

The one card tool: get the user a virtual debit card for a purchase. Cards are live and charged for real when used. For a FIRST-TIME user it starts by putting the user's OWN card in their Agentcard vault (any Visa, Mastercard, Amex, or Discover from any country, no identity verification (KYC), no balance funding): the call returns a secure link (vault_started); send it to the user (they type the card once and lock it with their passkey or master password; Agentcard never sees the number). A vaulted card pays through the buy tool, where the user approves each purchase on their device with their passkey or master password; it never becomes a card number you type, so after vault_started (or vault_ready, when a card is already in the vault) use buy for purchases instead of calling create_card again. If the user specifically needs a card NUMBER, that is an Agentcard funded from their cash balance, which requires KYC the first time: only after the user agrees, call create_card with source "issued". Established users: the saved default decides (get_settings default_payment: their chosen added card, or the wallet balance); with no saved default, an active ADDED card wins, otherwise the cash balance. Per-call overrides: connected_card_id issues against a specific added card, source "issued" forces the cash balance, restart_setup mints a fresh vault link. If the balance is short on the issued path, top up with add_funds. Connections through a company OAuth client have NO card count or amount limits; only first-party personal accounts have per-plan caps. Call get_plan for the limits in effect.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
typeNoCard behavior. 'single_use' (default) closes after its first approved charge — right for one-off purchases. 'multi_use' stays open across charges until its total limit is spent — right for subscriptions and recurring merchants. Multi-use cards can be paused (pause_card), resumed (resume_card), and resized (update_card_limit).
presetNoPreset for this card: a template name (ai_labs, weekday_meals, cli_only, daily), comma-separated templates, a saved preset name/id, inline JSON privileges, or { name?, privileges }. Adds restrictions only — omit for a normal unrestricted card.
sourceNoForce the card to be funded from the user's cash balance (the issued path: KYC + wallet funding) even when they have an added or vaulted card or would otherwise be offered the vault. Use it only after the user explicitly picks the balance option. Omit for the default (an active added card wins; first-time users get the vault link).
expires_atNoOptional hard expiry for a multi-use card (ISO-8601 with timezone, e.g. "2027-01-01T00:00:00Z"). Must be in the future, at most 365 days out. The card closes automatically when it passes.
amount_centsYesCard funding amount in CENTS, not dollars (minimum 100). 100 = $1.00 and 2500 = $25.00 — a value like 25 would be $0.25. Company-governed connections have no maximum; personal accounts are capped by their plan — call get_plan for the limits in effect.
funds_sourceNoWhere the card funds come from. OMIT unless instructed: the server applies the right default (company-connected accounts use the company wallet automatically when the company enables it). company_flow = the company's wallet funds the card; onramp_flow = the user's own wallet.
purchase_keyNoThe purchaseKey from the same approval_pending answer as pending_card_id; the pair proves the retry is for that purchase.
scope_presetNoSilent alias for preset 'ai_labs': a multi-use card restricted to AI-lab merchants (OpenAI, Anthropic, Gemini); charges anywhere else are declined at authorization. AI cards earn boosted tokenback on eligible spend. Implies type 'multi_use'. Prefer `preset`.
restart_setupNoSet true ONLY when the user lost or never received a vault link, it expired (about 15 minutes), or they want to add ANOTHER card. Never needed on the first call or for normal retries. amount_cents is still required on this call (the link itself carries no amount).
pending_card_idNoOnly when retrying an approval_pending purchase whose preset has since changed: the cardId from that earlier answer, together with purchase_key. The older approval link is retired once the replacement is minted. Never pass it for a different purchase.
connected_card_idNoMulti-card: issue against a SPECIFIC added card (an id from the user's added cards, see list_added_cards) instead of the newest active one. Omit for the default.

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
last4NoLast four digits of the new card. Present only when status is "created".
cardIdNoThe new card ID. Present only when status is "created".
expiryNoCard expiry (MM/YY). Present only when status is "created".
presetNoPreset summary for the new card, or null when unrestricted. Present when status is "created".
reasonNoOn "issuing_suggested" (legacy servers only; current servers route every first-time user to the vault instead): why the card could not be added. On "kyc_required": why the previous identity-verification attempt failed (e.g. "document_unverified_other"), present only when a prior attempt was rejected.
sourceNo"connected" when the card was created against the user's added card. Absent for wallet-funded cards.
statusNoOutcome discriminator: "created" (card issued), "vault_started" (first-time setup: send vaultUrl to the user; once their card is in the vault, purchases go through buy, not create_card), "vault_ready" (the user's own card is already in their vault: use buy; only source "issued" produces a card number), "attach_started" / "attach_pending" (an older add-card enrollment still in flight: send attachUrl or wait, then call again with the same arguments), "issuing_suggested" (legacy servers only: offer the balance-funded fallback, noting it requires KYC, and only then call again with source "issued"), "approval_required" (human approval needed), "approval_pending" (added-card passkey approval: send approvalUrl to the user, then retry with the same arguments in ~10s), "kyc_required" (issued path only), "user_info_required" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), "beta_capacity_reached", "issuing_balance_insufficient" (issued path only), "payment_method_declined", "limit_reached", "funding_in_progress" (company wallet funding underway: retry with the same arguments in ~10s), "funding_not_approved", "org_wallet_funding_required", "org_wallet_unavailable" (the company wallet backing this account is not active: the company must finish setup; do not retry immediately), "rate_limited" (wait ~1 minute, then retry), "issuer_daily_limit" (the issuing rail's daily card budget is spent: retry in about an hour, never in a loop), "issuer_capacity" / "wallet_balance_unavailable" (the rail is briefly unavailable: retry shortly). A refusal this build does not model relays the backend's own code here with its message.
messageYesHuman-readable result or guidance for the next step.
vaultUrlNoThe secure link the user opens to put their card in their vault. Present only when status is "vault_started".
attachUrlNoThe secure link the user opens to finish an older add-card enrollment. Present only when status is "attach_started".
expiresAtNoWhen the link expires (ISO 8601). Present when status is "vault_started" or "attach_started".
approvalIdNoThe approval request ID to pass to approve_request. Present only when status is "approval_required".
cardStatusNoCard status, e.g. "active". Present only when status is "created".
vaultCardsNoHow many cards the user already holds in their vault. Present only when status is "vault_ready".
approvalUrlNoThe passkey approval link to send to the user. Present only when status is "approval_pending".
purchaseKeyNoThe purchase's key. Present only when status is "approval_pending"; pass it back as purchase_key with pending_card_id.
balanceCentsNoCard balance in cents. Present only when status is "created".
missingFieldsNoWhat is missing when status is "user_info_required" (e.g. "termsAccepted", "consent").
pendingCardIdNoThe parked card awaiting the passkey. Present only when status is "approval_pending"; pass it back as pending_card_id on the retry, with purchaseKey as purchase_key.
balanceDollarsNoCard balance formatted as USD dollars, e.g. "12.50". Present only when status is "created".
maxAmountCentsNoThe issuing rail's per-card ceiling in cents. Present when status is "limit_reached" because the amount exceeded that ceiling; retry with amount_cents at most this value.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • changedInput schema / properties / preset / description
      Previous value: -"Preset for this card: a template name (ai_labs, weekday_meals, cli_only, daily), comma-separated templates, a saved preset name/id, inline JSON privileges, or { name?, privileges }. Adds restrictions only — omit for a normal unrestricted card (or to inherit the account default)."New value: +"Preset for this card: a template name (ai_labs, weekday_meals, cli_only, daily), comma-separated templates, a saved preset name/id, inline JSON privileges, or { name?, privileges }. Adds restrictions only — omit for a normal unrestricted card."
  2. Changed7 schema fields changed
    • addedInput schema / properties / pending_card_id
      Added value: +{
      +  "description": "Only when retrying an approval_pending purchase whose preset has since changed: the cardId from that earlier answer, together with purchase_key. The older approval link is retired once the replacement is minted. Never pass it for a different purchase.",
      +  "type": "string"
      +}
    • addedInput schema / properties / preset
      Added value: +{
      +  "description": "Preset for this card: a template name (ai_labs, weekday_meals, cli_only, daily), comma-separated templates, a saved preset name/id, inline JSON privileges, or { name?, privileges }. Adds restrictions only — omit for a normal unrestricted card (or to inherit the account default).",
      +  "oneOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "properties": {
      +        "name": {
      +          "type": "string"
      +        },
      +        "privileges": {
      +          "items": {},
      +          "type": "array"
      +        }
      +      },
      +      "required": [
      +        "privileges"
      +      ],
      +      "type": "object"
      +    }
      +  ]
      +}
    • addedInput schema / properties / purchase_key
      Added value: +{
      +  "description": "The purchaseKey from the same approval_pending answer as pending_card_id; the pair proves the retry is for that purchase.",
      +  "type": "string"
      +}
    • changedInput schema / properties / scope_preset / description
      Previous value: -"Create an AI card: a multi-use card restricted to AI-lab merchants (OpenAI, Anthropic, Gemini); charges anywhere else are declined at authorization. AI cards earn boosted tokenback on eligible spend. Implies type 'multi_use'."New value: +"Silent alias for preset 'ai_labs': a multi-use card restricted to AI-lab merchants (OpenAI, Anthropic, Gemini); charges anywhere else are declined at authorization. AI cards earn boosted tokenback on eligible spend. Implies type 'multi_use'. Prefer `preset`."
    • addedOutput schema / properties / pendingCardId
      Added value: +{
      +  "description": "The parked card awaiting the passkey. Present only when status is \"approval_pending\"; pass it back as pending_card_id on the retry, with purchaseKey as purchase_key.",
      +  "type": "string"
      +}
    • addedOutput schema / properties / preset
      Added value: +{
      +  "description": "Preset summary for the new card, or null when unrestricted. Present when status is \"created\".",
      +  "properties": {
      +    "id": {
      +      "type": "string"
      +    },
      +    "name": {
      +      "type": [
      +        "string",
      +        "null"
      +      ]
      +    },
      +    "summary": {
      +      "type": "string"
      +    },
      +    "version": {
      +      "type": "number"
      +    }
      +  },
      +  "type": [
      +    "object",
      +    "null"
      +  ]
      +}
    • addedOutput schema / properties / purchaseKey
      Added value: +{
      +  "description": "The purchase's key. Present only when status is \"approval_pending\"; pass it back as purchase_key with pending_card_id.",
      +  "type": "string"
      +}
  3. Changed3 schema fields changed
    • changedInput schema / properties / restart_setup / description
      Previous value: -"Set true ONLY when the user lost or never received a vault link, it expired (about 15 minutes), or they want to add ANOTHER card. Never needed on the first call or for normal retries."New value: +"Set true ONLY when the user lost or never received a vault link, it expired (about 15 minutes), or they want to add ANOTHER card. Never needed on the first call or for normal retries. amount_cents is still required on this call (the link itself carries no amount)."
    • addedOutput schema / properties / maxAmountCents
      Added value: +{
      +  "description": "The issuing rail's per-card ceiling in cents. Present when status is \"limit_reached\" because the amount exceeded that ceiling; retry with amount_cents at most this value.",
      +  "type": "number"
      +}
    • changedOutput schema / properties / status / description
      Previous value: -"Outcome discriminator: \"created\" (card issued), \"vault_started\" (first-time setup: send vaultUrl to the user; once their card is in the vault, purchases go through buy, not create_card), \"vault_ready\" (the user's own card is already in their vault: use buy; only source \"issued\" produces a card number), \"attach_started\" / \"attach_pending\" (an older add-card enrollment still in flight: send attachUrl or wait, then call again with the same arguments), \"issuing_suggested\" (legacy servers only: offer the balance-funded fallback, noting it requires KYC, and only then call again with source \"issued\"), \"approval_required\" (human approval needed), \"approval_pending\" (added-card passkey approval: send approvalUrl to the user, then retry with the same arguments in ~10s), \"kyc_required\" (issued path only), \"user_info_required\" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), \"beta_capacity_reached\", \"issuing_balance_insufficient\" (issued path only), \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway: retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active: the company must finish setup; do not retry immediately), or \"rate_limited\" (wait ~1 minute, then retry)."New value: +"Outcome discriminator: \"created\" (card issued), \"vault_started\" (first-time setup: send vaultUrl to the user; once their card is in the vault, purchases go through buy, not create_card), \"vault_ready\" (the user's own card is already in their vault: use buy; only source \"issued\" produces a card number), \"attach_started\" / \"attach_pending\" (an older add-card enrollment still in flight: send attachUrl or wait, then call again with the same arguments), \"issuing_suggested\" (legacy servers only: offer the balance-funded fallback, noting it requires KYC, and only then call again with source \"issued\"), \"approval_required\" (human approval needed), \"approval_pending\" (added-card passkey approval: send approvalUrl to the user, then retry with the same arguments in ~10s), \"kyc_required\" (issued path only), \"user_info_required\" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), \"beta_capacity_reached\", \"issuing_balance_insufficient\" (issued path only), \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway: retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active: the company must finish setup; do not retry immediately), \"rate_limited\" (wait ~1 minute, then retry), \"issuer_daily_limit\" (the issuing rail's daily card budget is spent: retry in about an hour, never in a loop), \"issuer_capacity\" / \"wallet_balance_unavailable\" (the rail is briefly unavailable: retry shortly). A refusal this build does not model relays the backend's own code here with its message."
  4. Changed8 schema fields changed
    • changedInput schema / properties / restart_setup / description
      Previous value: -"Set true ONLY when the user lost or never received a pending add-card link (mints a fresh one), or wants to add ANOTHER card while one is already active. Never needed on the first call or for normal retries."New value: +"Set true ONLY when the user lost or never received a vault link, it expired (about 15 minutes), or they want to add ANOTHER card. Never needed on the first call or for normal retries."
    • changedInput schema / properties / source / description
      Previous value: -"Force the card to be funded from the user's cash balance (the issued path: KYC + wallet funding) even when they have an added card or would otherwise be offered the add-card flow. Use it only after the user explicitly picks the balance option. Omit for the default (an active added card wins; first-time users get the add-card flow)."New value: +"Force the card to be funded from the user's cash balance (the issued path: KYC + wallet funding) even when they have an added or vaulted card or would otherwise be offered the vault. Use it only after the user explicitly picks the balance option. Omit for the default (an active added card wins; first-time users get the vault link)."
    • changedOutput schema / properties / attachUrl / description
      Previous value: -"The secure link the user opens to add their card. Present only when status is \"attach_started\"."New value: +"The secure link the user opens to finish an older add-card enrollment. Present only when status is \"attach_started\"."
    • changedOutput schema / properties / expiresAt / description
      Previous value: -"When the add-card link expires (ISO 8601). Present only when status is \"attach_started\"."New value: +"When the link expires (ISO 8601). Present when status is \"vault_started\" or \"attach_started\"."
    • changedOutput schema / properties / reason / description
      Previous value: -"On \"issuing_suggested\": why the card could not be added (e.g. \"issuer_excluded\", \"commercial_card\", \"attach_unavailable\"). On \"kyc_required\": why the previous identity-verification attempt failed (e.g. \"document_unverified_other\"), present only when a prior attempt was rejected."New value: +"On \"issuing_suggested\" (legacy servers only; current servers route every first-time user to the vault instead): why the card could not be added. On \"kyc_required\": why the previous identity-verification attempt failed (e.g. \"document_unverified_other\"), present only when a prior attempt was rejected."
    • changedOutput schema / properties / status / description
      Previous value: -"Outcome discriminator: \"created\" (card issued), \"attach_started\" (first-time setup — send attachUrl to the user, then call again with the same arguments once they finish), \"attach_pending\" (user has not finished the add-card link yet), \"issuing_suggested\" (the user's card could not be added — offer the balance-funded fallback, noting it requires KYC, and only then call again with source \"issued\"), \"approval_required\" (human approval needed), \"approval_pending\" (added-card passkey approval — send approvalUrl to the user, then retry with the same arguments in ~10s), \"kyc_required\" (issued path only), \"user_info_required\" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), \"beta_capacity_reached\", \"issuing_balance_insufficient\" (issued path only), \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway — retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active — the company must finish setup; do not retry immediately), or \"rate_limited\" (wait ~1 minute, then retry)."New value: +"Outcome discriminator: \"created\" (card issued), \"vault_started\" (first-time setup: send vaultUrl to the user; once their card is in the vault, purchases go through buy, not create_card), \"vault_ready\" (the user's own card is already in their vault: use buy; only source \"issued\" produces a card number), \"attach_started\" / \"attach_pending\" (an older add-card enrollment still in flight: send attachUrl or wait, then call again with the same arguments), \"issuing_suggested\" (legacy servers only: offer the balance-funded fallback, noting it requires KYC, and only then call again with source \"issued\"), \"approval_required\" (human approval needed), \"approval_pending\" (added-card passkey approval: send approvalUrl to the user, then retry with the same arguments in ~10s), \"kyc_required\" (issued path only), \"user_info_required\" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), \"beta_capacity_reached\", \"issuing_balance_insufficient\" (issued path only), \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway: retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active: the company must finish setup; do not retry immediately), or \"rate_limited\" (wait ~1 minute, then retry)."
    • addedOutput schema / properties / vaultCards
      Added value: +{
      +  "description": "How many cards the user already holds in their vault. Present only when status is \"vault_ready\".",
      +  "type": "number"
      +}
    • addedOutput schema / properties / vaultUrl
      Added value: +{
      +  "description": "The secure link the user opens to put their card in their vault. Present only when status is \"vault_started\".",
      +  "type": "string"
      +}
  5. Changed9 schema fields changed
    • changedInput schema / properties / connected_card_id / description
      Previous value: -"Multi-card BYOC: issue against a SPECIFIC added card (an id from the user's added cards) instead of the newest active one. Omit for the default."New value: +"Multi-card: issue against a SPECIFIC added card (an id from the user's added cards, see list_added_cards) instead of the newest active one. Omit for the default."
    • addedInput schema / properties / restart_setup
      Added value: +{
      +  "description": "Set true ONLY when the user lost or never received a pending add-card link (mints a fresh one), or wants to add ANOTHER card while one is already active. Never needed on the first call or for normal retries.",
      +  "type": "boolean"
      +}
    • changedInput schema / properties / source / description
      Previous value: -"Force the card to be funded from the user's cash balance even when they have an added card. Omit for the default (an active added card wins)."New value: +"Force the card to be funded from the user's cash balance (the issued path: KYC + wallet funding) even when they have an added card or would otherwise be offered the add-card flow. Use it only after the user explicitly picks the balance option. Omit for the default (an active added card wins; first-time users get the add-card flow)."
    • addedOutput schema / properties / attachUrl
      Added value: +{
      +  "description": "The secure link the user opens to add their card. Present only when status is \"attach_started\".",
      +  "type": "string"
      +}
    • addedOutput schema / properties / expiresAt
      Added value: +{
      +  "description": "When the add-card link expires (ISO 8601). Present only when status is \"attach_started\".",
      +  "type": "string"
      +}
    • addedOutput schema / properties / missingFields
      Added value: +{
      +  "description": "What is missing when status is \"user_info_required\" (e.g. \"termsAccepted\", \"consent\").",
      +  "items": {
      +    "type": "string"
      +  },
      +  "type": "array"
      +}
    • changedOutput schema / properties / reason / description
      Previous value: -"Why the previous identity-verification attempt failed (e.g. \"document_unverified_other\"). Present only when status is \"kyc_required\" and a prior attempt was rejected."New value: +"On \"issuing_suggested\": why the card could not be added (e.g. \"issuer_excluded\", \"commercial_card\", \"attach_unavailable\"). On \"kyc_required\": why the previous identity-verification attempt failed (e.g. \"document_unverified_other\"), present only when a prior attempt was rejected."
    • changedOutput schema / properties / source / description
      Previous value: -"\"connected\" when the card was created against the user's added card (see add_card). Absent for wallet-funded cards."New value: +"\"connected\" when the card was created against the user's added card. Absent for wallet-funded cards."
    • changedOutput schema / properties / status / description
      Previous value: -"Outcome discriminator: \"created\" (card issued), \"approval_required\" (human approval needed), \"approval_pending\" (BYOC passkey approval — send approvalUrl to the user, then retry with the same arguments in ~10s), \"payment_method_required\", \"kyc_required\", \"user_info_required\", \"beta_capacity_reached\", \"issuing_balance_insufficient\", \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway — retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active — the company must finish setup; do not retry immediately), or \"rate_limited\" (wait ~1 minute, then retry)."New value: +"Outcome discriminator: \"created\" (card issued), \"attach_started\" (first-time setup — send attachUrl to the user, then call again with the same arguments once they finish), \"attach_pending\" (user has not finished the add-card link yet), \"issuing_suggested\" (the user's card could not be added — offer the balance-funded fallback, noting it requires KYC, and only then call again with source \"issued\"), \"approval_required\" (human approval needed), \"approval_pending\" (added-card passkey approval — send approvalUrl to the user, then retry with the same arguments in ~10s), \"kyc_required\" (issued path only), \"user_info_required\" (check missingFields: phone/terms go through submit_user_info; consent must be recorded by the connecting platform), \"beta_capacity_reached\", \"issuing_balance_insufficient\" (issued path only), \"payment_method_declined\", \"limit_reached\", \"funding_in_progress\" (company wallet funding underway — retry with the same arguments in ~10s), \"funding_not_approved\", \"org_wallet_funding_required\", \"org_wallet_unavailable\" (the company wallet backing this account is not active — the company must finish setup; do not retry immediately), or \"rate_limited\" (wait ~1 minute, then retry)."
  6. Changed3 schema fields changed
    • changedInput schema / properties / connected_card_id / description
      Previous value: -"Multi-card BYOC: mint against a SPECIFIC attached card (an id from the user's attached cards) instead of the newest active one. Omit for the default."New value: +"Multi-card BYOC: issue against a SPECIFIC added card (an id from the user's added cards) instead of the newest active one. Omit for the default."
    • changedInput schema / properties / source / description
      Previous value: -"Force the card to be funded from the user's cash balance even when they have an attached card. Omit for the default (an active attached card wins)."New value: +"Force the card to be funded from the user's cash balance even when they have an added card. Omit for the default (an active added card wins)."
    • changedOutput schema / properties / source / description
      Previous value: -"\"connected\" when the card was minted against the user's attached card (see attach_card). Absent for wallet-funded cards."New value: +"\"connected\" when the card was created against the user's added card (see add_card). Absent for wallet-funded cards."
  7. First observed

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description discloses that cards are live and charged for real, that vaulted cards never become a typed card number, that KYC is required only for issued cards, that users approve purchases with passkey/master password, and that OAuth-connected accounts have no card/amount limits. No statement contradicts the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is dense but front-loaded with the core purpose, and every sentence carries decision-relevant information. It is long because the tool has multiple complex paths, but there is no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 11-parameter tool with two major funding paths, the description covers vault setup, issued cards, defaults, per-call overrides, KYC, balance shortfalls, plan limits, and sibling-tool routing. With an output schema present, return values do not need to be restated.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds cross-parameter and workflow meaning: per-call overrides (connected_card_id, source 'issued', restart_setup), the requirement that amount_cents is still needed on restart_setup, and how source interacts with defaults. These integrations go beyond the individual schema entries.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a crisp statement of the tool's core job: 'get the user a virtual debit card for a purchase,' and then distinguishes the vault path, issued path, and the buy tool. It names the one-card role explicitly and separates it from siblings like buy and add_funds.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives explicit when-to-use guidance: first-time users get the vault link; after vault_started or vault_ready, use buy instead; use source 'issued' only after the user agrees; restart_setup only for lost/expired links; top up with add_funds; call get_plan for limits. Alternatives and exclusions are spelled out.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources