MCP server for CardOS — issue and manage virtual cards via the Model Context Protocol. Works with Claude, Cursor, Windsurf and any MCP client.
CardOS MCP demonstrates solid definition quality with 27 well-named tools, comprehensive parameter schemas using Zod, and clear descriptions for most tools. Naming follows verb_noun convention consistently (list_products, issue_card, freeze_card). All tools have descriptions (avg ~120 chars, within 10-1024 baseline). Parameters are typed with Zod validators and include descriptions. However, output schemas are not explicitly documented, responses are inferred from API calls. Error handling is basic (CardOSError wrapper) without recovery guidance. Some parameter descriptions could be more explicit about constraints (e.g., 'idempotency_key' lacks format guidance). Tool composition is strong: issue_card → get_card → freeze_card chains work well. Security-sensitive tools (reveal_card, create_card_session) include warnings about sensitive links in descriptions.
Close a card permanently (irreversible). Idempotent.
[SANDBOX] Simulate confirmation of a pending deposit (test key only). In live, an on-chain watcher credits it.
Mint hosted card screens (manage + transactions) on real data, to open in a webview for the end user — bypassing you. Returns manage_url / transactions_url. ⚠️ These are sensitive short-lived links — deliver to the end user; do not store or log them.
Create a crypto deposit invoice to top up an end-user balance. Money operation — sandbox with a test key. Idempotent: pass the same idempotency_key when retrying.
Delete a webhook by id.
Open a dispute on a transaction.
Output schemas not explicitly documented. Tool descriptions state what is returned (e.g., 'Masked card details (last4, expiry, status)') but formal response schemas are absent. LLMs cannot plan downstream tool calls without knowing exact field names and types.
Error handling lacks recovery guidance. CardOSError wrapper returns status + code + message, but does not tell LLM what to do next (retry? ask user? lookup alternative?). No error classification (retryable vs fatal).
Idempotency keys lack format guidance. 'idempotency_key' parameter description says 'Stable key to make caller-side retries safe' but does not specify format (UUID? string? max length?). LLMs may generate invalid keys.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 69 | 2026-07-28+ | v2 |
Freeze a card (reversible). Idempotent.
Get an end user's available balance.
Masked card details (last4, expiry, status). Raw PAN/CVV are never returned here — use reveal_card.
Get one dispute by id.
Poll KYC status by uuid (returned by start_kyc).
Per-merchant pricing for products (e.g. for github, google).
Spending breakdown by category (from MCC) for an end user.
An end user's statement (summary: spent/received/fees/holds + line items + balance).
💳 Issue a virtual card to an end user. Money operation — a test key runs in sandbox (no real money). Idempotent: pass the same idempotency_key when retrying so a card is never issued twice.
List transactions for a card (amount, currency, commission, FX original amount/currency, merchant, MCC, decline reason, status).
List disputes, optionally filtered by user or status.
List available card products: productCode, currency, issue/topup limits, and whether KYC is required.
List registered webhooks.
Register a webhook URL to receive events (card.issued, card.transaction, etc.). Returns a secret for HMAC verification.
Mint a one-time hosted link that shows full card details (PAN/CVV) to the end user, bypassing you (PCI on CardOS). Short-lived, single-use. ⚠️ The result contains a sensitive one-time link — deliver it to the end user; do not store or log it.
Set soft spend controls (per-transaction / daily / monthly limits, blocked MCC/countries). On breach the card is auto-frozen + an alert is sent (no hard auth-time block).
Set a 4-digit PIN. The PIN is not stored by CardOS.
[SANDBOX] Inject a test card transaction (test key only) to exercise webhooks, analytics, controls and cashback.
Start KYC for an end user. Returns a hosted url_for_user and a uuid to poll.
Unfreeze a frozen card. Idempotent.
Update a dispute (status / note / provider reference).
Pagination not fully specified. list_card_transactions and list_disputes accept 'limit' but no offset/cursor. No 'total' or 'next_cursor' in documented responses. Large result sets may exceed context window.
Irreversible operations (close_card, delete_webhook) lack confirmation/dry-run pattern. Agents can permanently close cards or delete webhooks without a safety gate.