Critical failures across naming, schemas, and descriptions. While the server tackles a high-risk domain (payment & crypto), the tool definitions lack the rigor required for LLM safety and correctness. Tool names use verb_noun format (good) but descriptions are extremely sparse (4-8 words each). No visible input parameter schemas or type definitions in the provided code, only tool names and descriptions are shown. Output schemas are not documented. Error handling is generic (catches errors but provides no recovery guidance). The server enforces environment variable validation (MCP_MASTER_KEY) and claims encryption, but exposes irreversible operations (confirm-payment, sign-crypto-tx) without confirmation patterns or dry-run capabilities, dangerous for autonomous agents managing financial and crypto assets. STDIO-only transport caps the protocol readiness score, and lack of visible tool schemas prevents verification of input constraints critical for preventing hallucinated values in payment/crypto contexts.
Tools (18)
add-cardwrite33/100
Add a new payment card with encrypted storage
add-walletwrite33/100
Add a new cryptocurrency wallet
card-statusread only33/100
Get status of a payment card
confirm-paymentirreversible35/100
Confirm and process a prepared payment
get-total-balanceread only33/100
Get total balance across all wallets
get-transactionsread only33/100
Get payment card transactions
get-wallet-balanceread only33/100
Get balance for a specific cryptocurrency wallet
list-cardsread only33/100
List all stored payment cards (without sensitive data)
No visible input parameter schemas or type definitions in provided source. All tools show only name and description string; no JSON Schema, parameter types (string/number/boolean), enums, constraints, or descriptions for individual parameters.
Descriptions are critically sparse (4 - 8 words each). Examples: 'Add a new payment card with encrypted storage' (49 chars) does not explain when to use this vs alternatives, what parameters are required, what the output is, or what happens on error. LLMs cannot reliably select the correct tool with such minimal guidance.
Recommendations
Document full input schemas for all 18 tools. Use Zod (already a dependency) to define shape, types, enums, and constraints. Expose schema to the MCP server registration. Example: add-card should require card_number (string, 13-19 digits, pattern constraint), cvv (string, 3-4 digits), expiry_month (number, 1-12), expiry_year (number, ≥2025), cardholder_name (string, required). Each parameter must have a description explaining format and constraints.
Expand descriptions from ~50 chars to 150 - 250 chars per tool. Follow pattern:tool-description baseline: include WHAT the tool does, WHEN to call it (what user intent it serves), any prerequisites (e.g., 'setup-pin must be called before add-card'), and what the output contains. Example for confirm-payment: 'Confirm and process a prepared payment. Call this after prepare-payment returns a transaction_id. Initiates the charge and locks the card until completion. Returns confirmation_id, transaction_id, amount, currency, and status. On failure, returns reason (insufficient_funds, card_declined, rate_limit) and recovery hints.'
Add confirmation/dry-run support to irreversible operations. Pattern: confirmation-request. Implement a confirm_payment tool that takes confirmation_token (from prepare-payment) and optional dry_run=true. Similarly for sign-crypto-tx: require a signing_token from prepare-crypto-tx, accept dry_run flag. This prevents accidental financial loss.
Document output schemas for every tool. Return structured objects with explicit fields. Example: list-cards returns { cards: [ { card_id: string, last_four: string, brand: string, expiry: string, status: 'active'|'locked'|'expired' } ], total_count: number, page: number }. Include all IDs and references downstream tools need to avoid forced lookup calls.
Score history
Overall score trend
First recorded score · v2 rubric
31/100
Scored
Grade
Overall
Spec posture
Rubric
2026-09-23
F
31
2026-07-28+
v2
list-walletsread only33/100
List all cryptocurrency wallets (without sensitive data)
lock-cardswrite33/100
Lock payment cards to prevent use
prepare-crypto-txwrite37/100
Prepare a cryptocurrency transaction (first step of two-step flow)
prepare-paymentwrite37/100
Prepare a payment with a card (first step of two-step flow)
remove-carddestructive35/100
Remove a payment card from storage
remove-walletdestructive33/100
Remove a cryptocurrency wallet
setup-pinwrite33/100
Set up master PIN for card and wallet access control
sign-crypto-txirreversible37/100
Sign and broadcast a prepared cryptocurrency transaction
No confirmation or dry-run pattern on irreversible operations (confirm-payment, sign-crypto-tx, remove-card, remove-wallet). An LLM error could cause real financial loss (double charges, lost wallet access, deleted cards). This is unacceptable for a payment/crypto tool.
Output schemas are not documented. The src/index.ts tool registration uses tool.parameters.shape (Zod schema) but does not expose return type documentation to the LLM. The LLM cannot anticipate what fields are in the response (e.g., does list-cards return card_id, card_number_masked, expiry, etc.?), forcing it to guess or request clarification. Pattern: response-shaper.
Generic error handling in index.ts. All tool errors are caught as 'Unknown error' or error.message, with no recovery guidance. Per pattern:recovery-guide, errors must state what to do next. Example: confirm-payment fails with 'Insufficient funds', should the LLM suggest check-balance first? Reduce amount? Or is this unrecoverable? No guidance.
No pagination pattern visible for list tools. list-cards, list-wallets, list-wallet-transactions, get-transactions: no mention of limit, offset, page, or cursor parameters in descriptions. Per pattern:paginated-result, list tools must support pagination. If a user has 500 cards or transactions, returning all at once could exceed context limits and degrade LLM reasoning.
No permission-gating or audit logging visible in tool definitions. High-risk operations (confirm-payment, sign-crypto-tx, remove-card, remove-wallet) should declare required permissions (e.g., 'write:payments', 'admin:card-management') and log who invoked them, when, with what parameters, and what happened. Pattern: permission-gate + audit-trail.
Naming inconsistency: 'lock-cards' and 'unlock-cards' (hyphenated, verb-noun) vs tool registration in index.ts uses tool.name directly (assumed to match file names). If MCP server is using kebab-case tool names, that's fine; but parameter names are never defined in the provided source, so LLM cannot know whether to pass 'card_id' or 'cardId' or 'card_ids'. Mismatched naming forces the LLM to guess.
No distinction between human-readable identifiers and system IDs. Descriptions do not clarify: does add-card accept card_number and setup-pin take a pin, or do they require opaque IDs? Per pattern:natural-identifiers, users provide email/username/display name, not internal IDs. Tools must accept and resolve natural identifiers.
No tool-chaining support verified. If add-card returns a card_id, does prepare-payment accept card_id? If prepare-payment returns a transaction_id, does confirm-payment accept transaction_id? Output schemas are not visible, so the LLM cannot trace the chain. Pattern: tool-chain.
Tool annotations (readOnlyHint, destructiveHint, idempotentHint) are not declared in tool definitions. Per MCP spec (2026-07-28), current best practice is to mark sensitive tools with annotations. Example: confirm-payment should have destructiveHint=true; list-cards should have readOnlyHint=true. Annotations guide the LLM's caution and enable server-side safeguards.
Implement paginated-result pattern for list tools. Add limit (default 20, max 100) and offset (or cursor) parameters. Return total_count, has_more, and next_cursor. Example: list-cards(limit=20, offset=0) → { cards: [...], total_count: 247, page: 1, has_more: true }.
Replace generic error handling with recovery guidance. Catch errors by type and return actionable messages. Example: confirm-payment fails with 'error_code': 'insufficient_funds', 'suggestion': 'Try prepare-payment with a lower amount or check-balance first.' Pattern: recovery-guide.
Add permission declarations to tool metadata. Each tool should include a 'permissions' field or scope declaration. Example: add-card requires ['write:cards'], confirm-payment requires ['write:payments', 'admin:irreversible']. This enables least-privilege agent configuration.
Implement audit logging. Log every tool invocation with: timestamp, tool_name, agent_id (or caller), parameters (scrubbed of sensitive data), result (success/failure), and any side effects. Store in a tamper-proof log for compliance and incident investigation.
Add tool annotations for MCP spec compliance. Mark remove-card, remove-wallet, confirm-payment, sign-crypto-tx with destructiveHint: true. Mark list-cards, get-balance tools with readOnlyHint: true. Mark prepare-payment with idempotentHint: false (to prevent retries without checking idempotency).
Clarify natural identifier support. For lock-cards and unlock-cards, accept both card_id and card_identifier (last four digits, or masked number). Document which identifiers are supported. For setup-pin, clarify whether the PIN is user-provided text or a system-generated token.
Add rate limiting and timeout configurations. Set explicit timeouts for external API calls (blockchain, payment processors). Implement rate limiting (e.g., max 10 payments per minute per agent) to prevent runaway retries from overwhelming downstream services.
Create a batch variant for high-volume operations. E.g., add_multiple_cards or lock_multiple_cards (accepting an array) to reduce round-trip overhead if an agent needs to manage multiple cards.
Document error classification per tool. For confirm-payment, categorize errors as retryable (rate_limit, network_timeout), user-fixable (insufficient_funds, card_declined), or fatal (card_expired, wallet_compromised). Include recovery guidance for each class.