A FastAPI-based banking server that provides account management and transaction operations with PostgreSQL backend
This MCP server exposes 5 banking tools via HTTP FastAPI. Tool naming is clear and verb-based (create_account, deposit, withdraw, get_balance, get_transactions), following Arcade patterns well. However, there are significant gaps in schema documentation, parameter descriptions, and error handling guidance. Input schemas are visible in the submission but lack completeness, notably missing 'required' field declarations and detailed parameter constraints. Descriptions are present but often generic (e.g., 'Deposits funds into a specified account' without explaining when an LLM should use this vs. similar tools or what fields to expect in the response). Output schemas are not documented at all, LLMs cannot determine what fields they will receive. Error handling returns HTTP exceptions but does not provide recovery guidance or classify errors as retryable vs. fatal. No tool annotations (readOnlyHint, destructiveHint, idempotentHint) are present, despite clear read/write semantics. The database implementation is sound, but the MCP contract is weak.
Creates a new bank account with an optional initial balance
Deposits funds into a specified account
Retrieves the current balance and details of a specified account
Retrieves transaction history for a specified account with optional limit
Withdraws funds from a specified account
Output schemas are not documented. LLMs cannot determine what fields they will receive from any tool. For example, create_account returns AccountResponse (with fields account_id, account_holder_name, balance, created_at) but this is never declared in the tool schema. LLMs must guess or infer from tool execution.
Parameter descriptions lack specificity and constraint details. 'amount' is described as 'Amount to deposit, must be positive' but no numeric bounds (min, max, decimal places) are stated. 'initial_balance' similarly lacks precision. LLMs cannot validate inputs against unstated constraints and may pass invalid values (e.g., $999,999,999 or negative due to type confusion).
No tool annotations (readOnlyHint, destructiveHint, idempotentHint). The tools clearly have different semantics: get_balance and get_transactions are read-only; create_account, deposit, and withdraw are destructive and modify state. LLMs benefit from explicit annotations to plan correctly and avoid unintended side effects or retry issues.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | D | 50 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 41 | - | v1 |
Error responses provide no recovery guidance. HTTPExceptions return raw error strings (e.g., 'Insufficient funds', 'Account not found', 'Database connection failed') but do not tell the LLM what to do next. For a 404 error, should the LLM retry, ask the user, or call a different tool? No guidance.
Input schemas are missing 'required' field declarations. Looking at the provided schemas (e.g., deposit expects account_id and amount), there is no explicit indication of which fields are mandatory. JSON Schema should declare required: ["account_id", "amount"]. LLMs may omit required fields, causing silent failures.
Tool descriptions do not explain when to use each tool or dependencies between them. For example, deposit and withdraw both move money, but it's unclear if an LLM should prefer one or if they are truly distinct. What happens if you try to deposit into a non-existent account vs. withdraw? Descriptions should disambiguate.
No pagination support for get_transactions. The tool accepts an optional 'limit' parameter (default 10) but does not support offset/cursor-based pagination. If a user has thousands of transactions, the LLM cannot fetch the full history without multiple calls and no way to page through results efficiently.
No idempotency guarantees documented. Deposit and withdraw modify state and may be retried by LLMs on ambiguous failures. If a withdrawal succeeds but the response times out, an LLM might retry, causing a duplicate debit. No idempotency keys or guarantees are provided.