plaid-mcp
The plaid-mcp server is a read-only MCP adapter that connects LLMs (like Claude or ChatGPT) to personal financial data via Plaid or Teller, enabling natural language analysis of bank accounts, transactions, investments, liabilities, and debt.
Account Management
Link new bank accounts, list all linked institutions (with status), and remove/unlink institutions
Accounts & Balances
List all accounts across linked institutions and fetch live balances (optionally filtered by account)
Transactions
Sync, force-refresh, query (by date, category, merchant, account, amount), and fuzzy-search transactions
Summarize spending grouped by category, subcategory, merchant, or account
Investments
View current holdings (tickers, quantities, market value, cost basis)
Retrieve brokerage transaction history (buys, sells, dividends, fees)
Liabilities
Access credit card APRs, balances, and due dates; student loan and mortgage details
Identity & Income
Retrieve account holder names, emails, phones, and addresses
Detect bank-verified income streams (requires Plaid Income product)
Debt Analysis
Set/clear custom APR overrides for linked accounts
Add, update, remove, and list external debts (BNPL, medical bills, 401k loans)
Project debt payoff using avalanche (highest APR first) or snowball (lowest balance first) strategies, with amortization timelines and promo expiration warnings
Other
Data is stored locally (SQLite) with file-permission security; can run locally or remotely with TLS/auth
Supports a terminal UI for direct browsing of accounts and transactions
Compatible with MCP clients (Claude Desktop, ChatGPT, etc.) and optionally configurable with payment rails (MPP/x402)
Can be exposed via Caddy for secure HTTPS access when running in HTTP mode, allowing remote MCP clients to connect to the Plaid financial data server with TLS encryption.
Provides read-only access to Chase bank accounts through Plaid integration, allowing users to analyze transactions, balances, investments, liabilities, and financial data from their Chase accounts.
Can be exposed via Cloudflare Tunnel for secure remote access when running in HTTP mode, enabling MCP clients to connect to the Plaid financial data server through Cloudflare's infrastructure.
Supports configuration through .env files for Plaid API credentials and server settings, allowing users to securely manage authentication and environment variables for the financial data integration.
Hosts the plaid-mcp server source code and documentation, enabling users to clone, install, and run the server from the GitHub repository for accessing financial data through Plaid.
Can be exposed via ngrok for secure tunneling when running in HTTP mode, allowing remote MCP clients to connect to the Plaid financial data server through ngrok's tunneling service.
Provides installation method for the plaid-mcp server, enabling isolated installation and execution of the financial data integration tool for accessing bank accounts through Plaid.
Server implementation language for the plaid-mcp integration, enabling execution of the financial data server that connects to Plaid API for accessing bank accounts and transactions.
Stores access tokens and cached financial data in SQLite database, providing local persistence for Plaid authentication tokens and transaction data from linked bank accounts.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@plaid-mcpshow me my spending on dining out last month"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
plaid-mcp
A read-only Model Context Protocol server that lets Claude, ChatGPT, or any MCP-compatible client analyze your real bank, credit card, loan, and brokerage data through Plaid or Teller.
Bring your own credentials, run the server locally (or behind TLS on a small VPS), link your accounts, and then just ask:
"What did I spend on groceries in March?" "Show me my credit card APRs sorted by balance." "Which of my holdings are down more than 10% this year?" "I have a 0% promo on my AA card — given that, which debt should I attack first?"
Everything runs locally. Access tokens stay in a chmod-600 SQLite file on your machine. The server never makes outbound calls except to Plaid's API.
Table of contents
Related MCP server: plaid-mcp
Why this exists
Consumer financial data is locked inside whichever app happens to be connected to your bank. If you want to ask questions of it — "compare my March spending YoY," "what's my real effective APR across all cards," "project when I pay off this debt if I add $200/month" — you end up either exporting CSVs or trusting a SaaS aggregator with your credentials.
This project is a thin, read-only adapter: Plaid on one side, the LLM of your choice on the other. The LLM gets a small set of well-documented tools (transactions, balances, holdings, liabilities, identity, income, debt analysis). You keep your tokens.
Features
Read-only tools grouped by Plaid product area:
Accounts & balances —
list_accounts,get_balancesTransactions —
sync_transactions,refresh_transactions,get_transactions,search_transactions,spending_summaryInvestments —
get_holdings,get_investment_transactionsLiabilities —
get_liabilities(credit cards, student loans, mortgages with APRs and due dates)Identity & income —
get_identity,get_incomeDebt analysis —
set_account_override,add_external_debt,summarize_debt(avalanche/snowball with amortized payoff projections)Account management —
link_account,complete_linking,list_linked_institutions,remove_institution
All access tokens and cached transactions live in SQLite at ~/.plaid-mcp/plaid.db by default. Nothing leaves your machine except Plaid API calls.
Quick start
The easiest install is pipx or uv tool — both put plaid-mcp on your PATH in an isolated venv.
# 1. Install (pick one)
pipx install plaid-mcp # or: uv tool install plaid-mcp
# or: pip install plaid-mcp
# 2. Configure — any of these work:
# a) ~/.plaid-mcp/.env
# b) project-local .env (if you're running from a clone)
# c) inline env vars in your MCP client config (see "Claude Desktop" below)
mkdir -p ~/.plaid-mcp && cat > ~/.plaid-mcp/.env <<EOF
PLAID_CLIENT_ID=your_client_id
PLAID_SECRET=your_secret
PLAID_ENV=production
EOF
# 3. Link your first bank in the browser
plaid-mcp link
# 4. Wire it into Claude Desktop (see below) and ask:
# "list my accounts"
# "sync my transactions then summarize spending last month"Prefer to run from source? See Development.
Total setup time if you already have Plaid credentials: ~5 minutes.
Setup (detailed)
1. Get Plaid credentials
You need your own Plaid developer account — don't share a client_id or reuse someone else's credentials. Plaid's terms tie each account to the person who signed up, and the Production trial tier is intended for you to link your own accounts.
Sign up at dashboard.plaid.com. It's free.
In Developers → Keys, note your
client_idand one of two secrets:Sandbox secret — fake test data.
user_good/pass_goodlogs intoins_109508("First Platypus Bank"). Great for smoke-testing without real data.Production secret — real banks. New accounts get a Production trial (~10 linked items) without going through billing review. No time limit on the trial; it caps at 10 items.
Under Team Settings → Products, request access to Transactions, Investments, Liabilities, and Identity. Most approve instantly. Income requires a brief review.
Plaid retired the separate Development environment in late 2024. New accounts get Sandbox + a Production trial instead.
PLAID_ENV=developmentstill works here for backward compatibility; it's silently routed to Production.
2. Install
Choose whichever you prefer — all three drop a plaid-mcp executable on your PATH:
pipx install plaid-mcp # isolated venv, recommended
uv tool install plaid-mcp # same idea, uv-native
pip install plaid-mcp # into your current envOr from source (for development or running unreleased changes):
git clone https://github.com/t-rhex/plaid-mcp
cd plaid-mcp
uv sync # or: pip install -e .Requires Python 3.10+.
3. Configure
cp .env.example .env
$EDITOR .envRequired fields:
PLAID_CLIENT_ID=your_client_id_here
PLAID_SECRET=your_secret_here
PLAID_ENV=production # or: sandboxCommon optional overrides:
# What Plaid products to request during linking.
# PLAID_PRODUCTS — the bank MUST support these (link fails otherwise).
# PLAID_OPTIONAL_PRODUCTS — requested if supported; link doesn't fail if not.
PLAID_PRODUCTS=transactions
PLAID_OPTIONAL_PRODUCTS=investments,liabilities,identity
PLAID_COUNTRY_CODES=US # or: US,CA,GB,ES,FR,IE,NL,DE,IT
PLAID_MCP_DB=~/.plaid-mcp/plaid.db # tilde gets expanded; file is chmod 600
PLAID_CLIENT_NAME=plaid-mcp # shown to the user inside Plaid Link
# For remote deployment only:
# MCP_AUTH_TOKEN=<random 32-byte token> # required for HTTP mode
# PLAID_WEBHOOK_URL=https://yourhost/webhook # if using webhook-driven link completionWhy the two product lists? Plaid requires every product you list under PLAID_PRODUCTS to be supported by the bank at link time. Citi doesn't have brokerage, Fidelity doesn't have liabilities, etc. PLAID_OPTIONAL_PRODUCTS are requested "if the bank supports them" via Plaid's required_if_supported_products — so one .env works across banks and brokers.
4. Link your first account
uv run python -m plaid_mcp link
# => Open this URL in your browser: https://cdn.plaid.com/link/v2/stable/link.html?...
# => After completing, press Enter.Open the URL, pick your bank, complete the OAuth flow (for most banks this redirects to your bank's site and back), and return to the terminal.
You can also link new accounts directly from inside Claude/ChatGPT after the server is wired up — just say "link a new account" and follow the link it returns.
Choosing a provider
plaid-mcp speaks to two bank-data providers behind a shared adapter. Pick the one that matches what you want to analyze:
Plaid (default) | Teller | |
Environment variable |
|
|
Checking / savings / credit | ✓ | ✓ |
Balances | ✓ | ✓ |
Transactions (categorized) | ✓ (cursor sync) | ✓ (live date range) |
Identity | ✓ | ✓ |
Investment holdings + trades | ✓ | ✗ |
Liabilities (APRs, due dates) | ✓ | ✗ |
Student loans / mortgages | ✓ | ✗ |
Income detection | ✓ | ✗ |
Debt avalanche/snowball tools | ✓ | ✗ (needs APRs) |
Free personal-use tier | 10 linked items | 100 live connections |
Transparent per-call pricing | Contact sales | Published rate card |
Generic tools (list_accounts, get_balances, get_transactions, search_transactions, get_identity) work on either provider. Plaid-only tools (everything else) return a clean capability error when PROVIDER=teller, so Teller users aren't left with confusing tracebacks.
You can freely switch by changing PROVIDER in your .env — each provider stores its enrollments independently (Plaid in SQLite, Teller in ~/.plaid-mcp/teller/enrollment.json), so nothing is lost.
Teller setup
# 1. Register at dashboard.teller.io (free), grab your Application ID
# 2. Download certificate.zip; move to ~/.plaid-mcp/teller/ (0600)
# 3. Add to .env:
PROVIDER=teller
TELLER_APPLICATION_ID=app_xxxxxxxxxxxxxxxxxxxxx
TELLER_ENV=sandbox # sandbox needs no cert; dev/prod do
TELLER_CERT_PATH=~/.plaid-mcp/teller/certificate.pem
TELLER_KEY_PATH=~/.plaid-mcp/teller/private_key.pem
# 4. Link your first bank (either in your terminal or from the TUI)
plaid-mcp teller connect
# 5. Smoke-test
plaid-mcp teller probeSandbox credentials in Teller Connect: username / password against any bank. That returns a real sandbox access_token you can actually query.
Connecting it to an MCP client
Claude Desktop (local, stdio)
Edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS or %APPDATA%\Claude\claude_desktop_config.json on Windows.
If you installed via pipx / uv tool / pip (recommended):
{
"mcpServers": {
"plaid": {
"command": "plaid-mcp",
"env": {
"PLAID_CLIENT_ID": "<your client_id>",
"PLAID_SECRET": "<your secret>",
"PLAID_ENV": "production",
"PLAID_PRODUCTS": "transactions",
"PLAID_OPTIONAL_PRODUCTS": "investments,liabilities,identity"
}
}
}
}If plaid-mcp isn't found on Claude Desktop's PATH, use the absolute path that which plaid-mcp prints.
If you're running from a clone:
{
"mcpServers": {
"plaid": {
"command": "uv",
"args": [
"--directory", "/absolute/path/to/plaid-mcp",
"run", "python", "-m", "plaid_mcp"
],
"env": {
"PLAID_CLIENT_ID": "...",
"PLAID_SECRET": "...",
"PLAID_ENV": "production"
}
}
}
}Restart Claude Desktop. You should see "plaid" appear in the tools menu.
Claude.ai web or ChatGPT (remote, HTTPS)
Run in HTTP mode:
MCP_AUTH_TOKEN=$(python -c 'import secrets; print(secrets.token_urlsafe(32))') \
uv run python -m plaid_mcp serve --host 0.0.0.0 --port 8080Expose it with TLS (Caddy, Cloudflare Tunnel, ngrok). In Claude.ai or ChatGPT add it as a Custom Connector / MCP Connector and paste the bearer token. Never expose this server without TLS and MCP_AUTH_TOKEN set.
Other clients
Anything that speaks MCP will work. The server is built on FastMCP, which supports both stdio and HTTP transports.
Terminal UI
If you prefer browsing your accounts directly rather than asking an LLM, run:
plaid-mcp tuiOpens a Textual app with Accounts + Transactions screens, works with either provider, zero-friction navigation (q to quit, r to refresh, a/t to switch screens, c to link a new bank through Teller Connect without leaving the terminal).
Tool reference
All dates are ISO strings (
YYYY-MM-DD). Amounts follow Plaid's convention: positive for outflows (spending), negative for inflows (deposits).
Account management
link_account()— Start a new Plaid Link session. Returns ahosted_link_urlthe user opens in their browser to authenticate with their bank.complete_linking(link_token, timeout_seconds=180)— Finalize a Link session once the user has completed it in the browser.list_linked_institutions()— Every institution currently linked, with account counts and any errors.remove_institution(item_id)— Unlink an institution and purge its cached data.
Accounts & balances
list_accounts()— All accounts across all linked institutions, from the local cache. Fast.get_balances(account_id=None)— Live balance lookup (hits Plaid, not the cache). Optionally filter to one account.
Transactions
sync_transactions(wait_for_ready=True, wait_timeout_seconds=60)— Pull the latest transactions into the local cache using Plaid's cursor-based/transactions/sync. Incremental and idempotent. On first call after linking, Plaid runs the historical pull asynchronously; this tool blocks briefly untilHISTORICAL_UPDATE_COMPLETE.refresh_transactions(item_id=None)— Ask Plaid to re-pull from the bank right now. Use when a user just made a purchase and wants to see it, or when data looks stale. Asynchronous — wait 30–60s then callsync_transactions. Some smaller banks don't support on-demand refresh.get_transactions(start_date, end_date, account_id=?, category=?, merchant=?, min_amount=?, max_amount=?, limit=500)— Query the cache. Filter by any combination of the above.search_transactions(query, start_date=?, end_date=?, limit=100)— Fuzzy search across transaction description + merchant name.spending_summary(start_date, end_date, group_by="category")— Aggregate spending.group_bycan becategory,subcategory,merchant, oraccount.
Investments
get_holdings(account_id=None)— Current positions: tickers, quantities, market value, cost basis.get_investment_transactions(start_date, end_date, account_id=None, limit=250)— Buys, sells, dividends, fees.
Liabilities
get_liabilities()— Credit cards (statement balance, minimum payment, due dates, APRs), student loans (balance, interest rate, payoff date, servicer), mortgages (principal, rate, maturity, next payment).
Identity & income
get_identity(account_id=None)— Account-holder names, emails, phones, addresses as reported by each institution.get_income()— Bank-detected income streams. Requires Plaid's Income product enabled in your dashboard.
Debt analysis
Plaid's liabilities data covers the basics but misses things — notably promotional APRs on credit cards (0% intro offers, balance-transfer promos). This layer lets you annotate what Plaid missed and run honest payoff math.
Not financial advice. These tools do straightforward amortization math and rank debts by APR or balance — nothing more. For decisions that meaningfully affect your finances (debt consolidation, refinancing, tax implications of early payoff, etc.), talk to a CFP, CPA, or attorney. The outputs here are a starting point for a conversation with a professional, not a substitute for one.
set_account_override(account_id, effective_apr=?, promo_expires=?, note=?)— Record the true APR for a linked card. Afterpromo_expires, analysis reverts to Plaid's reported purchase APR.clear_account_override(account_id)— Remove an override.list_overrides()— List all overrides.add_external_debt(name, balance, apr, minimum_payment=0.0, next_payment_due_date=?, promo_expires=?, note=?)— Track a debt that isn't behind a linked Plaid account (BNPL, medical, 401(k) loans, small lenders). APR is a percentage (e.g.18.5, not0.185).update_external_debt(debt_id, ...)— Partial update to any field.remove_external_debt(debt_id)list_external_debts()summarize_debt(strategy="avalanche", extra_monthly_payment=0.0, today=?)— Merges Plaid credit cards + overrides + external debts, ranks them, and projects payoff:avalanche(default) — highest effective APR first, minimizes interest paid.snowball— lowest balance first, fastest sense of progress.Returns total balance, monthly interest accrual at current rates, priority debt, amortized payoff timelines (minimum-only vs. with the extra payment), and warnings for promos expiring within 60 days. Flags debts whose minimum payment can't even cover monthly interest.
Example workflows
"Summarize my spending last month"
You: sync my transactions then show me top 10 merchants by spend in March 2026
LLM: [calls sync_transactions_tool, then spending_summary_tool with group_by=merchant]
Top merchants in March 2026:
Whole Foods $412.80 (14 transactions)
Amazon $287.43 (9 transactions)
..."Which debt should I pay first?" — with a 0% promo
Plaid says your AA card is 26.49%, but it's actually on a 0% promo until 2027. By default, an LLM would tell you to attack the AA card first (because it sees 26.49%) — which is exactly wrong. Fix it:
You: my AA card is actually at 0% promo APR until 2027-01-01. set that override,
then run an avalanche summary.
LLM: [set_account_override_tool(account_id="...", effective_apr=0.0,
promo_expires="2027-01-01")]
[summarize_debt_tool(strategy="avalanche")]
Priority: Costco Anywhere Visa, balance $1,204, effective APR 18.74%
(was going to recommend the AA card at 26.49%, but you have a 0% override
until 2027-01-01 — AA is now ranked last.)
At minimum-only payments, the Costco card pays off in 78 months with
$1,142 in interest. Add $200/mo and you're done in 7 months paying $96
total — saves you ~$1,046 in interest."Track a BNPL I opened outside the linked banks"
You: I just took out a $1,500 Affirm loan for a mattress, 0% APR for 12 months,
$125/mo minimum. Add it.
LLM: [add_external_debt_tool(name="Affirm Mattress", balance=1500, apr=0,
minimum_payment=125, promo_expires=<in 12mo>)]
Added (ext_a1b2c3d4e5f6). Included in summarize_debt going forward."Show me stale data or link errors"
You: are any of my linked accounts broken?
LLM: [calls list_linked_institutions_tool]
Chase — 5 accounts, last sync 3h ago, no errors.
Citi — 4 accounts, last_error: "ITEM_LOGIN_REQUIRED" (your password likely
changed; re-link via `link a new account`)."I just made a purchase and want to see it"
You: I just paid at Whole Foods 10 minutes ago, refresh and show it.
LLM: [refresh_transactions_tool()]
[waits ~45 seconds]
[sync_transactions_tool()]
[search_transactions_tool(query="whole foods", start_date=<today>)]
Found it: $84.12 at WHOLE FOODS MARKET today.How linking works under the hood
This server uses Plaid's Hosted Link flow so you never need to embed a web widget. The tool sequence an LLM follows to add a bank:
link_account— creates alink_tokenwith ahosted_linkobject, returns thehosted_link_urland the rawlink_token.User opens that URL in a browser, completes the OAuth flow with their bank.
complete_linking(link_token)— polls/link/token/getuntil it sees apublic_tokeninlink_sessions[].results.item_add_results[], exchanges it for a permanentaccess_token, and caches the account list.
Per Plaid's docs, webhooks (SESSION_FINISHED event) are the recommended production mechanism for retrieving the public_token. This server uses polling instead because it requires no public endpoint — fine for personal CLI / stdio use. If you deploy remotely and want webhook-driven completion, set PLAID_WEBHOOK_URL in .env and add a webhook handler (not included yet — PRs welcome).
Paid hosted mode
plaid-mcp ships three payment rails; operators pick one via PAYWALL=<rail>. Tool discovery (tools/list, initialize) stays free across all of them — only tools/call is metered.
MPP (recommended) — Tempo stablecoin + Stripe cards
The Machine Payments Protocol via pympp. Use this if you want either:
Pure crypto — USDC on Tempo L2, no Stripe account required, wallet-to-wallet.
Traditional cards — any Stripe-supported method (requires a Stripe account).
Both, advertised in the same 402 — clients pick based on what they have.
uv sync --extra mpp
# or: pip install 'plaid-mcp[mpp]'PAYWALL=mpp
MPP_METHODS=tempo,stripe # tempo | stripe | tempo,stripe
# Tempo rail (only needed when 'tempo' is in MPP_METHODS):
MPP_DESTINATION_ADDRESS=0x... # Your Tempo wallet that receives USDC
MPP_NETWORK=tempo-testnet # tempo-testnet | tempo-mainnet
# MPP_ALLOW_MAINNET=1 # required to accept real USDC on Tempo
# Stripe rail (only needed when 'stripe' is in MPP_METHODS):
STRIPE_SECRET_KEY=sk_live_... # your Stripe API secret
STRIPE_CURRENCY=usd
# STRIPE_PAYMENT_METHOD_TYPES=card,apple_payHow the 402 works: on an unpaid tools/call, the server returns 402 Payment Required with one WWW-Authenticate: Payment ... header per configured method. A well-behaved MPP client picks the method it can satisfy (Tempo if it has a USDC wallet, Stripe if it has a card), signs a credential, and replays with Authorization: Payment <credential>. The server routes the incoming credential back to the matching rail based on the challenge method field. On success, a Payment-Receipt header carries the settlement receipt.
x402 (alternative) — Coinbase CDP or x402.org facilitator
Trustless HTTP 402 on Base. Use this for agents speaking Coinbase Agentic Wallets, CDP Agent Kit, or Cloudflare Agents — those clients have mature x402 support today. Base mainnet needs Coinbase CDP facilitator auth; Base Sepolia works against x402.org's hosted facilitator out of the box.
uv sync --extra cdp # only required for Base mainnetPAYWALL=x402
X402_RECEIVING_ADDRESS=0x... # Base address that receives USDC
X402_NETWORK=base-sepolia # base-sepolia (testnet) | base (mainnet)
# X402_ALLOW_MAINNET=1 # required to actually open mainnet
# X402_FACILITATOR_URL= # optional (defaults to https://x402.org/facilitator)None (default)
PAYWALL=noneNo paywall. Suitable for personal stdio use via Claude Desktop and for self-hosted HTTP deployments where you gate access with MCP_AUTH_TOKEN instead.
Client-side support
MPP clients — pympp ships with a Python client; Stripe-side, any SDK that can create a PaymentIntent with the challenge amount and return the confirmation token works.
Claude Desktop / Claude Code / Cursor (x402) — install Coinbase's x402 MCP bridge alongside
plaid-mcp. The bridge holds the Base wallet and does the signing;plaid-mcpstays crypto-naive.OpenAI Agents SDK / LangChain (x402) —
pip install "x402[httpx]", wrap the tool's HTTP client with the x402 client middleware.CDP Agent Kit (x402) — native x402 actions; nothing extra to install.
ChatGPT Custom Connectors — no wallet primitive today; use an API-key fallback if you need this audience (not implemented yet).
Default prices
Default prices live in src/plaid_mcp/payments/prices.py (10¢ for most tools, 50¢ for summarize_debt_tool). Override per-tool by forking or by building your own PriceTable if you embed this as a library. The price table is shared across all rails — an MPP-tempo caller and an x402-Base caller pay the same cents for the same tool.
Verified end-to-end
Live facilitator round-trips ship under pytest markers. Set the relevant private key env var and run:
# x402 on Base Sepolia (needs ~cent of testnet USDC)
X402_TESTNET_PRIVATE_KEY=0x... \
X402_RECEIVING_ADDRESS=0x<your-wallet-or-throwaway> \
uv run pytest -v -m x402_testnet
# MPP on Tempo testnet (xfail today; see test docstring)
MPP_TESTNET_PRIVATE_KEY=0x... uv run pytest -v -m mpp_testnetGet x402 testnet USDC from Circle's faucet (pick Base Sepolia).
Deploying with Docker / Fly.io
A reference Dockerfile, docker-compose.yml, and Fly.io config live at the repo root + deploy/. See deploy/README.md for the step-by-step.
# Local hosted-mode smoke test
docker compose up --build
# Fly.io one-shot
fly apps create plaid-mcp
fly volumes create plaid_mcp_data --region iad --size 1
fly secrets set $(grep -v '^#' .env | xargs)
fly deploy --config deploy/fly.tomlThe container runs plaid-mcp serve --host 0.0.0.0 --port 8080 as a non-root user, persists ~/.plaid-mcp/ on a named volume, and survives restarts with all Plaid items + Teller enrollment intact. Fly terminates TLS at the edge; self-hosting behind Caddy/Traefik/nginx works the same way.
Security notes
Access tokens are stored in SQLite at
PLAID_MCP_DB(default~/.plaid-mcp/plaid.db). On macOS and Linux the file is chmod'd to0600.Read-only, by design. There are no tools that move money, create transfers, or modify anything upstream. Plaid's
/transfer/*endpoints are not exposed. The worst a prompt-injected LLM can do is read your data — not move it.If you run it remotely, put it behind TLS and set
MCP_AUTH_TOKENto a random string. Never expose it over plain HTTP or without auth.If you deploy this for anyone other than yourself, you need to complete Plaid's Production Enablement review first. The Production trial tier covers personal use; hosting a multi-user instance on your
client_idwithout review violates Plaid's terms. Every user running their own copy with their own Plaid credentials is fine — that's the intended open-source usage.Plaid's terms prohibit storing bank credentials — and this server never sees them. Plaid Link handles credentials directly with the institution; this server only gets a per-user access token.
The LLM sees your financial data while it's answering questions. Choose a provider you trust, and consider running against the Sandbox environment first to get a feel for what flows through context.
Troubleshooting
INVALID_PRODUCT: Your account is not enabled for <product>
You requested a product in PLAID_PRODUCTS that your Plaid dashboard isn't approved for. Go to Team Settings → Products, request access, and wait for approval. Or drop the product from PLAID_PRODUCTS (and put it in PLAID_OPTIONAL_PRODUCTS instead if you still want it when available).
"No investment accounts" when linking a non-brokerage bank (e.g. Citi)
You had investments in PLAID_PRODUCTS, which makes Plaid reject banks without brokerage. Move investments from PLAID_PRODUCTS to PLAID_OPTIONAL_PRODUCTS and re-link.
sync_transactions returns 0 transactions right after linking
Plaid's historical pull is async. The server blocks up to 60s for HISTORICAL_UPDATE_COMPLETE — but some banks (notoriously Citi) can take hours to backfill. Check list_linked_institutions for last_error. If there's no error, just wait and try again; the status field in the sync response tells you what Plaid is up to.
refresh_transactions returns PRODUCT_NOT_READY
Some smaller institutions don't support on-demand refresh. Plaid will still refresh them on its normal schedule (every few hours). This is an institution limitation, not a bug in the server.
Tokens got lost / I want to start over
Remove the SQLite DB: rm ~/.plaid-mcp/plaid.db. All your cached transactions and tokens go with it. You'll need to re-link every institution.
The LLM hallucinates numbers
Ask it to call the tools explicitly: "call sync_transactions_tool, then call spending_summary_tool with...". Also: instruct the LLM to always cite the tool output it's reasoning from. Model choice matters; the default instructions in the MCP server nudge toward tool use.
Claude Desktop doesn't see the tools
Confirm uv is on your PATH (which uv). Claude Desktop's launchd-style environment often doesn't inherit your shell PATH. You may need the absolute path (e.g. "command": "/Users/you/.cargo/bin/uv"). Restart Claude Desktop after config changes.
Development
uv sync --extra dev # or: pip install -e ".[dev]"
ruff check .
pytest # unit + MCP smoke tests (no credentials needed)
pytest -m sandbox # end-to-end tests against Plaid SandboxSandbox tests read credentials from .env.test at the repo root (git-ignored). Create it when you want to run them:
PLAID_CLIENT_ID=your_sandbox_client_id
PLAID_SECRET=your_sandbox_secretSandbox tests use /sandbox/public_token/create to skip Plaid Link entirely, so no browser needed.
CI (GitHub Actions) runs on every push:
Unit + MCP smoke tests on Python 3.10 / 3.11 / 3.12.
Sandbox integration tests, if
PLAID_CLIENT_ID_SANDBOXandPLAID_SECRET_SANDBOXare set as repository secrets.
Contributions
Welcome — particularly:
Additional Plaid product coverage (Assets, Statements, Signal).
Webhook handling for real-time transaction sync.
Export tools (write summaries to CSV / Markdown / Google Sheets).
Better LLM prompting for the debt workflows.
Please keep all tools read-only. No PR that introduces write endpoints (transfers, bill pay, account modification) will be merged.
License
MIT. See LICENSE.
Available Tools
24 toolsadd_external_debt_toolA
Track a debt that isn't behind a linked Plaid account.
Use for BNPL (Affirm, Klarna), medical bills, 401(k) loans, or debts at
non-linkable lenders. apr is a percentage (e.g. 18.5 for 18.5%, not
0.185). Returns the assigned debt_id.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| balance | Yes | ||
| apr | Yes | ||
| minimum_payment | No | ||
| next_payment_due_date | No | ||
| promo_expires | No | ||
| note | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses that the tool creates/returns a 'debt_id', indicating a write operation, but lacks details on permissions, error handling, or side effects. It adds some behavioral context (e.g., APR format), but doesn't cover critical aspects like whether this is idempotent or has rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, followed by usage guidelines and a key parameter note. Every sentence adds value without redundancy, and the structure efficiently conveys essential information in three concise lines.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a write tool with 7 parameters, 0% schema coverage, and no output schema, the description is incomplete. It covers purpose, usage, and one parameter well, but misses details on other parameters, return values beyond 'debt_id', and behavioral traits like error conditions. Given the complexity, more context is needed for full adequacy.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clarifies the 'apr' parameter semantics ('percentage, e.g., 18.5 for 18.5%'), which is crucial beyond the schema's type. However, it doesn't explain other parameters like 'balance' units or 'next_payment_due_date' format, leaving gaps for the remaining 6 parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Track a debt') and resource ('that isn't behind a linked Plaid account'), distinguishing it from sibling tools like 'list_external_debts_tool' and 'update_external_debt_tool'. It provides concrete examples of use cases (BNPL, medical bills, 401(k) loans), making the purpose highly specific and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool ('Use for BNPL, medical bills, 401(k) loans, or debts at non-linkable lenders'), providing clear context for its application. It distinguishes this from tools that handle linked accounts (implied by the sibling list), though it doesn't name specific alternatives, the guidance is comprehensive for the given context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
clear_account_override_toolC
Remove any APR override for an account.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool removes an APR override, implying a destructive mutation, but doesn't clarify permissions needed, whether the action is reversible, or what happens on success/failure (e.g., confirmation message or error). This leaves significant gaps for a mutation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with zero wasted words, directly stating the tool's function. It is appropriately sized and front-loaded, making it easy for an agent to parse quickly without unnecessary detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity as a mutation operation with no annotations, no output schema, and low schema coverage, the description is incomplete. It doesn't cover behavioral aspects like error handling or return values, nor does it fully explain parameter usage, leaving the agent under-informed for safe and effective invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 1 parameter with 0% description coverage, so the description must compensate. It implies 'account_id' is used to identify the target account, which adds basic meaning, but doesn't specify format (e.g., numeric ID, string) or validation rules. This provides marginal value, aligning with the baseline for partial compensation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('Remove') and target ('APR override for an account'), making the purpose specific and understandable. However, it doesn't explicitly differentiate from sibling tools like 'set_account_override_tool' or 'list_overrides_tool', which would require mentioning those alternatives to achieve a perfect score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'set_account_override_tool' (for adding/updating overrides) or 'list_overrides_tool' (for viewing them). It also lacks prerequisites, such as whether an override must exist to be removed, leaving the agent with insufficient context for optimal selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
complete_linkingA
Finalize a Link session once the user has completed it in their browser. Exchanges the public_token for a permanent access_token and caches accounts.
| Name | Required | Description | Default |
|---|---|---|---|
| link_token | Yes | ||
| timeout_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden but lacks critical behavioral details. It mentions exchanging tokens and caching accounts but doesn't disclose authentication requirements, rate limits, error conditions, or what 'caches accounts' entails operationally. The description provides basic intent but insufficient behavioral transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is perfectly concise with two focused sentences that front-load the main purpose. Every word earns its place—no redundancy or unnecessary elaboration while clearly communicating the tool's role in a workflow.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, 0% schema coverage, no output schema, and 2 parameters, the description provides adequate basic context but lacks completeness. It explains the tool's role in a Link session workflow but misses details about authentication, error handling, return values, and parameter specifics needed for reliable use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
With 0% schema description coverage for 2 parameters, the description adds minimal semantic value. It mentions 'link_token' indirectly via 'public_token' but doesn't explain parameter purposes, relationships, or the 'timeout_seconds' default behavior. The description partially compensates but leaves significant gaps in parameter understanding.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('Finalize', 'Exchanges', 'caches') and resources ('Link session', 'public_token', 'access_token', 'accounts'). It distinguishes itself from siblings like 'link_account' by focusing on completion rather than initiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool ('once the user has completed [a Link session] in their browser'), implying it should follow an initial linking process. However, it doesn't explicitly state when not to use it or name specific alternatives among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_balances_toolA
Live balance lookup (hits Plaid, not cached). Filter by account_id if given.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses key behavioral traits: 'Live balance lookup' implies read-only operation, 'hits Plaid' indicates external API calls, and 'not cached' clarifies data freshness. However, it doesn't cover error handling, rate limits, authentication needs, or response format details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise and front-loaded: two brief sentences with zero wasted words. Every phrase ('Live balance lookup', 'hits Plaid, not cached', 'Filter by account_id if given') adds distinct value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's moderate complexity (single optional parameter, external API calls), no annotations, and an output schema (which handles return values), the description is minimally adequate. It covers the core purpose and parameter use but lacks details on error cases, performance implications, or integration with sibling tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description adds meaningful context for the single parameter: 'Filter by account_id if given' clarifies its optional filtering purpose. With 0% schema description coverage and no parameter documentation in the schema, this compensates well. However, it doesn't specify the account_id format or constraints.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Live balance lookup' specifies the verb and resource, and '(hits Plaid, not cached)' adds technical context. However, it doesn't explicitly differentiate from sibling tools like 'list_accounts_tool' or 'get_holdings_tool' beyond the balance focus.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides some usage context: 'Filter by account_id if given' implies optional filtering, and 'hits Plaid, not cached' suggests real-time data needs. However, it lacks explicit guidance on when to use this versus alternatives like 'list_accounts_tool' or 'get_holdings_tool', and doesn't mention prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_holdings_toolC
Current investment positions (tickers, quantities, market value, cost basis).
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It implies a read-only operation by describing data retrieval, but doesn't specify whether authentication is required, rate limits exist, what happens when account_id is null, or the format/structure of returned data. The description is minimal and lacks important behavioral context for a financial data tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise - a single sentence that efficiently communicates the core purpose and data fields. Every word earns its place, with no wasted text or redundancy. The structure is front-loaded with the main purpose followed by specific data elements in parentheses.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a financial data retrieval tool with no annotations, no output schema, and incomplete parameter documentation, the description is inadequate. It doesn't explain what happens when account_id is null (all accounts vs default account), doesn't describe the return format, and provides no context about authentication, permissions, or data freshness. The description is too minimal given the complexity of financial data tools.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description provides no information about the account_id parameter, which has 0% schema description coverage. However, with only one parameter that's optional (defaults to null), the baseline is higher. The description doesn't compensate for the lack of parameter documentation, but the simplicity of a single optional parameter keeps this from being a critical failure.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves 'current investment positions' and lists the specific data fields returned (tickers, quantities, market value, cost basis). It uses a specific verb ('positions') and identifies the resource (investment holdings), though it doesn't explicitly distinguish from sibling tools like get_balances_tool or get_investment_transactions_tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It doesn't mention sibling tools like get_balances_tool (which might provide different financial data) or get_investment_transactions_tool (which might show transaction history rather than current positions), nor does it specify any prerequisites or context for usage.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_identity_toolC
Account holder names, emails, phones, addresses as reported by the institution.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It describes what data is retrieved but does not cover critical aspects like whether this is a read-only operation, authentication requirements, rate limits, or error handling. For a data retrieval tool with zero annotation coverage, this is a significant gap in transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that directly states the tool's purpose without unnecessary words. It is appropriately sized and front-loaded, making it easy to understand quickly, though it could be slightly more structured with additional details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (data retrieval with one parameter), lack of annotations, no output schema, and low schema coverage, the description is incomplete. It does not explain return values, error cases, or how the parameter affects the query, leaving significant gaps for an AI agent to understand full usage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has one parameter (account_id) with 0% description coverage, and the tool description does not mention parameters at all. Since schema coverage is low, the description fails to compensate by explaining the parameter's role or semantics. With no parameter information in the description, it adds no value beyond the schema, resulting in a baseline score.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves specific identity data (names, emails, phones, addresses) from an institution, which is a specific verb+resource combination. However, it does not explicitly differentiate from sibling tools like 'list_accounts_tool' or 'get_balances_tool', which might also involve account data but for different purposes, leaving some ambiguity in sibling differentiation.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, such as whether it's for a specific account or all accounts, or how it relates to siblings like 'list_accounts_tool'. It implies usage for identity data but lacks explicit context, exclusions, or prerequisites, resulting in minimal actionable guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_income_toolB
Bank-detected income streams. Requires Income product enabled in your Plaid dashboard.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions a prerequisite (Income product enabled) but doesn't describe other key traits such as whether this is a read-only operation, potential rate limits, authentication needs, or what the return format looks like. For a tool with zero annotation coverage, this is a significant gap in transparency.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise with two sentences that directly state the purpose and a key prerequisite. Every word earns its place, and it's front-loaded with the core functionality. There's no wasted text or redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters (simplifying input) and no output schema (increasing the need for output description), the description is moderately complete. It covers the purpose and a prerequisite but lacks details on behavioral traits (e.g., read-only status, return format) and doesn't explain what the output contains, which is a gap since there's no output schema to rely on.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters, and schema description coverage is 100%, so there are no parameters to document. The description doesn't need to add parameter semantics, and it appropriately doesn't mention any. A baseline of 4 is applied since no parameters exist, and the description doesn't mislead about inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states what the tool does ('Bank-detected income streams') with a specific resource (income streams) and verb (detected). It distinguishes from siblings like get_balances_tool or get_transactions_tool by focusing on income data rather than balances or transactions. However, it doesn't specify the exact scope (e.g., all income streams vs. recent ones), keeping it from a perfect 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides some usage context by stating 'Requires Income product enabled in your Plaid dashboard,' which implies a prerequisite condition. However, it doesn't explicitly guide when to use this tool versus alternatives (e.g., vs. get_holdings_tool for investment income) or mention any exclusions, leaving the guidance incomplete.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_investment_transactions_toolC
Brokerage transactions: buys, sells, dividends, fees.
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | Yes | ||
| end_date | Yes | ||
| account_id | No | ||
| limit | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It implies a read operation by listing transaction types, but lacks details on permissions, rate limits, pagination (despite a 'limit' parameter), or response format. For a tool with 4 parameters and no annotations, this is insufficient behavioral disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise—a single phrase with zero waste. It's front-loaded with the core purpose, though this brevity comes at the cost of detail. Every word earns its place by specifying the transaction types.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters with 0% schema coverage, no annotations, and no output schema, the description is incomplete. It doesn't address parameter usage, behavioral traits, or output expectations, making it inadequate for a tool of this complexity. The agent lacks critical context to use it effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate for undocumented parameters. It mentions 'Brokerage transactions' but doesn't explain how parameters like 'start_date', 'end_date', 'account_id', or 'limit' affect the query. The description adds minimal value beyond the schema's parameter names.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool retrieves brokerage transactions (buys, sells, dividends, fees), providing a specific verb ('Brokerage transactions') and resource scope. However, it doesn't explicitly differentiate from sibling tools like 'get_transactions_tool' or 'search_transactions_tool', which likely handle similar data but with different filtering or scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description offers no guidance on when to use this tool versus alternatives. It doesn't mention prerequisites, context for usage, or compare to sibling tools like 'get_transactions_tool' or 'search_transactions_tool', leaving the agent to infer based on tool names alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_liabilities_toolC
Credit cards, student loans, mortgages with APRs, balances, due dates.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It implies a read operation by listing data fields, but doesn't specify if it requires authentication, returns all liabilities or filtered ones, handles errors, or has rate limits. This leaves significant gaps for a tool with potential data sensitivity.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that lists key elements without fluff. It could be slightly more structured by front-loading the action (e.g., 'Retrieve liabilities such as...'), but it's appropriately sized and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no annotations, no output schema, and the tool's complexity (retrieving financial data), the description is incomplete. It lists data fields but doesn't explain return format, error handling, or scope (e.g., all accounts or filtered), making it inadequate for safe and effective use by an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters with 100% schema description coverage, so no parameter documentation is needed. The description doesn't add param info, which is appropriate here. Baseline is 4 for zero parameters, as it avoids unnecessary detail.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description lists types of liabilities (credit cards, student loans, mortgages) and data fields (APRs, balances, due dates), which implies a retrieval function. However, it lacks an explicit verb like 'retrieve' or 'list', making the purpose somewhat vague rather than clearly stated as a specific action. It distinguishes from some siblings like 'add_external_debt_tool' by implying read-only access, but not all.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No explicit guidance on when to use this tool versus alternatives is provided. The description hints at retrieving liability data, but it doesn't specify contexts, prerequisites, or compare to siblings like 'get_balances_tool' or 'summarize_debt_tool', leaving usage unclear without external context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_transactions_toolA
Query cached transactions. Dates are YYYY-MM-DD. Run sync_transactions first to refresh. Positive amounts = spend.
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | Yes | ||
| end_date | Yes | ||
| account_id | No | ||
| category | No | ||
| merchant | No | ||
| min_amount | No | ||
| max_amount | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden. It discloses key behavioral traits: the data is cached (implying potential staleness), requires prior sync for freshness, and clarifies amount semantics ('Positive amounts = spend'). However, it doesn't mention pagination behavior, rate limits, error conditions, or authentication requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three concise sentences with zero waste. First establishes purpose, second provides date format and prerequisite, third clarifies amount semantics. Each sentence earns its place by adding distinct, valuable information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 8 parameters with 0% schema coverage, no annotations, but an output schema exists, the description provides adequate context. It covers the core purpose, prerequisite, date format, and amount interpretation. The output schema handles return values, so the description focuses on usage context appropriately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It adds crucial semantic context: date format ('YYYY-MM-DD'), amount interpretation ('Positive amounts = spend'), and implies filtering capabilities. While it doesn't detail all 8 parameters individually, it provides enough guidance for effective use given the output schema exists.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Query cached transactions' specifies both the verb (query) and resource (cached transactions). It distinguishes from siblings like 'search_transactions_tool' by emphasizing the 'cached' aspect, though it doesn't explicitly contrast with all similar tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage guidance: 'Run sync_transactions first to refresh' indicates a prerequisite. It distinguishes from 'sync_transactions_tool' by positioning this as a query tool for cached data, though it doesn't explicitly state when NOT to use it or compare with 'search_transactions_tool'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
link_accountA
Start a new Plaid Link session. Returns a URL the user opens in their browser to authenticate with their bank. After they finish, call complete_linking with the returned link_token.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses key behavioral traits: it initiates a session, returns a URL for user authentication, and requires a follow-up call to 'complete_linking'. However, it lacks details on error handling, timeouts, or authentication requirements, which are relevant for a session initiation tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence, followed by essential usage details. Every sentence earns its place with no wasted words, making it highly efficient and easy to parse.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (session initiation with a follow-up step), no annotations, and no output schema, the description is mostly complete. It covers the purpose, usage flow, and output, but could improve by mentioning potential errors or the URL's validity duration for full contextual coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters with 100% coverage, so no parameter documentation is needed. The description adds value by explaining the output (a URL) and the subsequent action, which compensates for the lack of output schema, though it doesn't detail the URL format.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Start a new Plaid Link session') and resource ('Plaid Link'), distinguishing it from siblings like 'complete_linking' or 'list_linked_institutions_tool'. It uses precise verbs and identifies the exact functionality.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly states when to use this tool ('Start a new Plaid Link session') and provides a clear alternative ('call complete_linking with the returned link_token'), guiding the agent on the workflow sequence without ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accounts_toolA
List every account across every linked institution (from the local cache).
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool lists accounts from a local cache, which is useful behavioral context about data freshness. However, it lacks details on permissions, rate limits, or error handling, leaving gaps for a tool with no annotation support.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the key action and scope without any wasted words. It directly communicates the tool's purpose and data source, making it highly concise and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has no parameters, an output schema exists, and no annotations, the description is reasonably complete for a simple listing operation. It specifies the scope ('every account across every linked institution') and data source ('local cache'), though it could benefit from mentioning output format or caching implications for full completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters with 100% schema description coverage, so the schema fully documents the inputs. The description adds no parameter-specific information, but this is acceptable as there are no parameters to describe, aligning with the baseline for zero parameters.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('List every account') and resource ('across every linked institution'), specifying it operates on data from the local cache. This distinguishes it from siblings like get_balances_tool or get_holdings_tool, which focus on specific data types rather than a comprehensive account listing.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a broad overview of all accounts is needed, but does not explicitly state when to use it versus alternatives like list_linked_institutions_tool or get_balances_tool. It provides clear context by mentioning 'from the local cache', which suggests it retrieves cached data rather than real-time updates.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_external_debts_toolA
List every external (non-Plaid-linked) debt the user has recorded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries full burden. It states the tool lists debts but does not disclose behavioral traits such as whether it requires authentication, how results are formatted, if there are rate limits, or if it's a read-only operation. The description is minimal and lacks essential context for safe invocation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the purpose without waste. It is appropriately sized for a tool with no parameters, making every word count.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 0 parameters and no annotations or output schema, the description is complete in stating what the tool does. However, it lacks details on behavioral aspects like return format or error handling, which are important for a tool with no structured output documentation. It meets minimum viability but has clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters with 100% coverage, so no parameter documentation is needed. The description does not add parameter details, which is appropriate. Baseline is 4 for 0 parameters, as it avoids unnecessary information.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('List every') and resource ('external (non-Plaid-linked) debt'), with precise scope ('the user has recorded'). It distinguishes from siblings like 'get_liabilities_tool' by specifying 'external' and 'non-Plaid-linked', avoiding tautology.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving external debts only, but does not explicitly state when to use this tool versus alternatives like 'get_liabilities_tool' or 'summarize_debt_tool'. No exclusions or prerequisites are mentioned, leaving some ambiguity.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_linked_institutions_toolA
List every institution currently linked, with account counts and any errors.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses that the tool lists institutions with account counts and errors, which is useful behavioral context, but does not cover aspects like permissions, rate limits, or response format details beyond what the output schema might provide.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that front-loads the core purpose ('List every institution currently linked') and adds specific details ('with account counts and any errors') without any wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's low complexity (0 parameters, no annotations, but with an output schema), the description is reasonably complete. It specifies what is listed and additional details like account counts and errors, though it could benefit from more behavioral context given the lack of annotations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has 0 parameters with 100% schema description coverage, so the schema fully documents the lack of inputs. The description adds no parameter information, which is appropriate, earning a baseline score above 3 due to the zero-parameter context.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('List every institution currently linked') and resource ('institution'), distinguishing it from siblings like 'list_accounts_tool' or 'remove_institution_tool' by focusing on linked institutions with account counts and errors.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for retrieving linked institutions with account details and errors, but does not explicitly state when to use this tool versus alternatives like 'list_accounts_tool' or 'remove_institution_tool', nor provide exclusions or prerequisites.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_overrides_toolB
List every account APR override the user has recorded.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states the action ('List every account APR override') but lacks details on permissions required, data format returned, pagination, rate limits, or error conditions. This is a significant gap for a tool that likely accesses sensitive financial data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that directly states the tool's purpose without any fluff or redundant information. It's appropriately sized and front-loaded, making it easy to understand at a glance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the lack of annotations and output schema, the description is incomplete. It doesn't explain what an 'APR override' entails, the format of the returned data, or any behavioral aspects like data freshness or access controls. For a financial data tool with no structured metadata, this leaves critical gaps for an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0 parameters with 100% coverage, so no parameter documentation is needed. The description appropriately doesn't discuss parameters, earning a baseline score of 4 for not adding unnecessary information beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb ('List') and resource ('account APR override'), specifying that it retrieves every override recorded by the user. It distinguishes from siblings like 'set_account_override_tool' and 'clear_account_override_tool' by focusing on listing rather than modifying, though it doesn't explicitly differentiate from other list tools like 'list_accounts_tool'.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
No guidance is provided on when to use this tool versus alternatives. While it implies usage for viewing APR overrides, there's no mention of prerequisites, timing, or comparison with related tools like 'get_balances_tool' or 'get_liabilities_tool' that might overlap in financial data context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
refresh_transactions_toolA
Nudge Plaid to pull fresh transactions from the bank right now.
Use when a user just made a purchase and wants to see it, or when transactions look stale. Plaid normally refreshes on its own every few hours; this forces an immediate pull. Asynchronous — wait 30-60s then call sync_transactions to ingest any new data.
Pass item_id to refresh one institution, or leave empty to refresh everything. Some smaller banks don't support on-demand refresh.
| Name | Required | Description | Default |
|---|---|---|---|
| item_id | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden and does an excellent job disclosing behavioral traits: it explains the asynchronous nature, timing expectations (30-60s wait), dependency on another tool (sync_transactions), and limitations ('some smaller banks don't support on-demand refresh'). Only minor gap: doesn't mention error handling or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Perfectly structured and front-loaded: first sentence states core purpose, subsequent sentences provide essential context. Every sentence earns its place with no wasted words. Four concise paragraphs cover purpose, usage, workflow, and parameter semantics efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with no annotations, no output schema, and 0% schema coverage, the description provides excellent context about behavior, timing, dependencies, and limitations. It explains the asynchronous workflow clearly. Could be 5 with more detail about return values or error cases, but given the tool's relative simplicity, this is highly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It clearly explains the semantics of the single parameter: 'Pass item_id to refresh one institution, or leave empty to refresh everything.' This adds crucial meaning beyond the schema's basic type information. Could be 5 with more detail about item_id format or examples.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('nudge Plaid to pull fresh transactions') and identifies the resource ('transactions from the bank'). It distinguishes this tool from siblings like 'sync_transactions_tool' by explaining this triggers the data pull while sync_transactions ingests it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use ('when a user just made a purchase and wants to see it, or when transactions look stale') and when not to use ('Plaid normally refreshes on its own every few hours'). Provides clear alternative guidance ('wait 30-60s then call sync_transactions to ingest any new data').
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_external_debt_toolC
Delete an external debt entry.
| Name | Required | Description | Default |
|---|---|---|---|
| debt_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states 'Delete' which implies a destructive mutation, but doesn't specify whether this is permanent, reversible, requires specific permissions, or has side effects (e.g., affecting linked data). This is a significant gap for a mutation tool with zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, direct sentence with zero wasted words—'Delete an external debt entry.' It's front-loaded with the core action and resource, making it highly efficient and easy to parse. Every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (a destructive mutation with no annotations, no output schema, and 1 undocumented parameter), the description is incomplete. It lacks crucial details like behavioral traits (e.g., permanence, permissions), parameter semantics, and expected outcomes, making it inadequate for safe and effective use by an AI agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 1 parameter (debt_id) with 0% description coverage, meaning the schema provides no semantic context. The tool description doesn't add any parameter information—it doesn't explain what 'debt_id' represents, its format, or where to obtain it. This fails to compensate for the low schema coverage, leaving the parameter undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description 'Delete an external debt entry' clearly states the action (delete) and target resource (external debt entry), which is specific and unambiguous. However, it doesn't explicitly distinguish this from sibling tools like 'update_external_debt_tool' or 'list_external_debts_tool', which would be needed for a perfect score.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. For example, it doesn't mention prerequisites (e.g., needing an existing debt entry), exclusions, or how it differs from related tools like 'update_external_debt_tool' or 'remove_institution_tool'. This leaves the agent with minimal context for decision-making.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
remove_institution_toolB
Unlink an institution (Plaid item) and delete its local data.
| Name | Required | Description | Default |
|---|---|---|---|
| item_id | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It mentions 'delete its local data', implying a destructive operation, but lacks details on permissions required, whether the action is reversible, or any side effects like impact on related accounts or transactions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that is front-loaded with the core action, with no unnecessary words or redundancy, making it easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's destructive nature, lack of annotations, no output schema, and 0% schema coverage, the description is incomplete. It should address behavioral risks, parameter details, and expected outcomes to adequately guide an agent in a financial data context.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The schema description coverage is 0%, and the description does not add any meaning beyond the schema. It does not explain what 'item_id' represents (e.g., a Plaid item identifier for the institution) or where to obtain it, leaving the single parameter undocumented.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose with specific verbs ('unlink' and 'delete') and identifies the resource ('institution/Plaid item'), distinguishing it from sibling tools like 'list_linked_institutions_tool' or 'link_account' that handle listing or adding institutions.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives, such as whether it should be used for cleaning up old data or in error scenarios, nor does it mention prerequisites like needing a valid 'item_id' from a linked institution.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_transactions_toolC
Fuzzy search across transaction description and merchant name.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | ||
| start_date | No | ||
| end_date | No | ||
| limit | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden but only states the search behavior ('fuzzy search'). It lacks details on permissions, rate limits, response format (though output schema exists), or side effects. For a search tool with 4 parameters, this minimal disclosure is inadequate for informed use.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence with zero wasted words, front-loading the core functionality. It's appropriately sized for a basic tool description, though its brevity contributes to gaps in other dimensions.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters with 0% schema coverage and no annotations, the description is incomplete—it doesn't explain parameters or behavioral context. However, the presence of an output schema mitigates the need to describe return values. The tool is relatively simple (search function), so the description is minimally viable but with clear gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate but only implies 'query' for search. It doesn't explain 'start_date', 'end_date', or 'limit' parameters, their formats, or how they interact with the fuzzy search. The description adds minimal value beyond the bare schema, failing to address the coverage gap.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('fuzzy search') and target resources ('transaction description and merchant name'), making the purpose understandable. It doesn't explicitly differentiate from sibling tools like 'get_transactions_tool' or 'search_transactions_tool' (if present), but the search focus is specific enough for basic clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'get_transactions_tool' or 'refresh_transactions_tool'. It mentions 'fuzzy search' but doesn't specify scenarios where this is preferred over exact matches or other filtering methods, leaving usage context implied at best.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
set_account_override_toolA
Annotate a linked card with the real APR when Plaid misses it.
Common case: Citi doesn't consistently report 0% intro / balance-transfer promos through /liabilities/get. Use this to record the true effective APR and (optionally) a promo expiration date so summarize_debt_tool can reason honestly. After the promo_expires date, payoff analysis reverts to Plaid's reported purchase APR.
| Name | Required | Description | Default |
|---|---|---|---|
| account_id | Yes | ||
| effective_apr | No | ||
| promo_expires | No | ||
| note | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses key behavioral traits: it's a write operation ('annotate', 'record'), affects future analysis ('so summarize_debt_tool can reason honestly'), and has temporal effects ('After the promo_expires date, payoff analysis reverts'). It doesn't mention permissions or side effects, but covers the core mutation behavior well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized and front-loaded: the first sentence states the core purpose, followed by specific examples and downstream effects. Every sentence adds value—no wasted words—and the structure flows logically from problem to solution to implications.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (mutation with temporal effects), no annotations, and no output schema, the description is largely complete. It explains the what, why, and how, including interactions with 'summarize_debt_tool'. It could mention error cases or confirmation of success, but covers the essential context well for a tool with 4 parameters.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains the purpose of 'effective_apr' ('record the true effective APR') and 'promo_expires' ('optionally a promo expiration date'), adding meaning beyond the schema. It doesn't detail 'account_id' or 'note', but provides enough context for the critical parameters given the low coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Annotate a linked card with the real APR when Plaid misses it.' It specifies the verb ('annotate'), resource ('linked card'), and context ('when Plaid misses it'), distinguishing it from siblings like 'summarize_debt_tool' or 'get_liabilities_tool' by focusing on manual correction of data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool: 'Common case: Citi doesn't consistently report 0% intro / balance-transfer promos through /liabilities/get.' It also states the alternative ('reverts to Plaid's reported purchase APR') and links to 'summarize_debt_tool' for downstream effects, making usage clear relative to other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
spending_summary_toolC
Aggregate spending by category | subcategory | merchant | account.
| Name | Required | Description | Default |
|---|---|---|---|
| start_date | Yes | ||
| end_date | Yes | ||
| group_by | No | category |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It states what the tool does (aggregation) but doesn't describe any behavioral traits such as whether it's read-only, requires authentication, has rate limits, returns paginated results, or what happens with invalid inputs. For a tool with 3 parameters and no annotation coverage, this is a significant gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is extremely concise - a single sentence with no wasted words. It's front-loaded with the core purpose and efficiently lists grouping options. Every element earns its place, making it easy to parse quickly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool has 3 parameters with 0% schema coverage and no annotations, but does have an output schema, the description is moderately complete. The output schema reduces the need to describe return values, but the description should do more to explain parameter usage and behavioral context for this aggregation operation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 0% description coverage, so the description must compensate. It mentions grouping options (category, subcategory, merchant, account) which partially explains the 'group_by' parameter, but doesn't clarify the 'start_date' and 'end_date' parameters at all. The description adds some value for one parameter but leaves two completely unexplained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Aggregate spending by category | subcategory | merchant | account.' It specifies the verb (aggregate) and resource (spending), and the grouping options provide some specificity. However, it doesn't explicitly distinguish this from sibling tools like 'get_transactions_tool' or 'search_transactions_tool' that might also retrieve spending data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It doesn't mention when this aggregation tool is preferred over transaction listing tools, nor does it specify any prerequisites or exclusions. The user must infer usage from the purpose alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
summarize_debt_toolA
Rank every debt and project payoff timelines.
Merges Plaid-reported credit cards with user APR overrides and any external debts, then ranks by strategy:
avalanche(default): highest effective APR first — minimizes interest paid.snowball: lowest balance first — fastest sense of progress.
extra_monthly_payment is dollars above the priority debt's minimum
you'd put toward it each month. Returns total balance, monthly interest
accrual at current rates, priority debt, amortized payoff projections
(minimum-only vs. with-extra), and warnings for promos expiring soon.
| Name | Required | Description | Default |
|---|---|---|---|
| strategy | No | avalanche | |
| extra_monthly_payment | No | ||
| today | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. It discloses key behavioral traits: it merges data from Plaid and user inputs, ranks debts by strategy, and returns projections and warnings. However, it lacks details on permissions, rate limits, or error handling, which are important for a tool processing financial data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately sized and front-loaded, starting with the core purpose. Every sentence adds value, such as explaining data sources, strategies, and outputs. It could be slightly more structured with bullet points for clarity, but it avoids redundancy and waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (financial projections with multiple inputs) and no annotations or output schema, the description is fairly complete. It covers purpose, parameters, and return values (balance, interest, projections, warnings). However, it lacks details on output format or error cases, which would enhance completeness for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It effectively explains all three parameters: 'strategy' (avalanche vs. snowball with definitions), 'extra_monthly_payment' (dollars above minimum), and implicitly 'today' (used for projections, though not explicitly named). This adds significant meaning beyond the bare schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Rank every debt and project payoff timelines.' It specifies the verb ('rank'), resource ('debt'), and scope ('project payoff timelines'), and distinguishes itself from sibling tools like 'get_liabilities_tool' or 'list_external_debts_tool' by focusing on ranking and projections rather than just listing or retrieving data.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context for when to use this tool: to analyze debt payoff strategies (avalanche vs. snowball) with extra payments. It implies usage for financial planning scenarios. However, it does not explicitly state when not to use it or name alternatives among siblings, such as 'get_liabilities_tool' for raw debt data without projections.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
sync_transactions_toolA
Pull the latest transactions from Plaid into the local cache. Idempotent and incremental — uses cursors from the last sync.
Plaid's first sync after linking an institution runs asynchronously;
when wait_for_ready is True (default), this tool blocks briefly until
the historical pull reports HISTORICAL_UPDATE_COMPLETE. Returned
status field surfaces that state per item.
| Name | Required | Description | Default |
|---|---|---|---|
| wait_for_ready | No | ||
| wait_timeout_seconds | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key traits: idempotency, incremental syncing using cursors, asynchronous behavior for first syncs, blocking behavior with 'wait_for_ready', and the 'status' field indicating sync completion. It lacks details on rate limits or error handling, but covers essential operational aspects well.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose in the first sentence, followed by critical behavioral details. Every sentence adds value: idempotency, cursor usage, first-sync behavior, parameter effects, and output field. There is no redundant or vague language, making it efficiently structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of syncing transactions with external APIs, no annotations, and no output schema, the description does well by covering purpose, key behaviors, and parameter effects. However, it lacks details on error cases, rate limits, or the exact structure of returned data (beyond the 'status' field), leaving some gaps for a fully informed agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, so the description must compensate. It explains the semantics of 'wait_for_ready' (controls blocking behavior during first sync) and implies 'wait_timeout_seconds' relates to timeout, though not explicitly. This adds meaningful context beyond the bare schema, but falls short of fully documenting both parameters, such as the exact role of the timeout.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the specific action ('Pull the latest transactions from Plaid into the local cache'), identifies the resource (transactions from Plaid), and distinguishes it from siblings like 'get_transactions_tool' (which likely retrieves cached data) and 'refresh_transactions_tool' (which might force a full refresh). The mention of 'idempotent and incremental' further clarifies its operational scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear context on when to use this tool: for syncing transactions from Plaid, particularly noting its behavior during 'first sync after linking an institution' and the effect of the 'wait_for_ready' parameter. However, it does not explicitly state when not to use it or name alternatives like 'refresh_transactions_tool' for comparison, which prevents a perfect score.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_external_debt_toolC
Update any subset of fields on an existing external debt.
| Name | Required | Description | Default |
|---|---|---|---|
| debt_id | Yes | ||
| name | No | ||
| balance | No | ||
| apr | No | ||
| minimum_payment | No | ||
| next_payment_due_date | No | ||
| promo_expires | No | ||
| note | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries full burden for behavioral disclosure. It states this is an update operation, implying mutation, but doesn't disclose any behavioral traits like permission requirements, whether changes are reversible, rate limits, or what happens to fields not mentioned. For a mutation tool with 8 parameters, this is a significant gap.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, efficient sentence that communicates the core purpose without unnecessary words. It's appropriately sized and front-loaded with the essential information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a mutation tool with 8 parameters, 0% schema description coverage, no annotations, and no output schema, the description is inadequate. It doesn't explain what constitutes an 'external debt', what fields are updatable, what the response looks like, or any error conditions. The agent would struggle to use this tool effectively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The description mentions updating 'fields' which maps to the 7 optional parameters in the schema, but doesn't provide any additional semantic meaning beyond what's implied by the parameter names. With 0% schema description coverage, the description doesn't compensate by explaining what each field represents, their formats, or constraints. The baseline is 3 since it at least acknowledges parameters exist.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('update') and resource ('existing external debt'), and specifies it can update 'any subset of fields', which adds useful detail. However, it doesn't explicitly differentiate from sibling tools like 'remove_external_debt_tool' or 'list_external_debts_tool' beyond the basic verb difference.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives like 'add_external_debt_tool' for creating new debts or 'remove_external_debt_tool' for deletion. It mentions 'existing external debt' which implies a prerequisite that the debt must already exist, but doesn't state this explicitly or reference other tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Most tools have distinct purposes, but some overlap exists. For example, get_balances_tool and list_accounts_tool both provide account information, though one is live and the other cached. Similarly, refresh_transactions_tool and sync_transactions_tool both handle transaction updates, but with different timing and mechanisms. The descriptions help clarify these distinctions, preventing major confusion.
The naming is mixed, with no single consistent pattern. Some tools use verb_noun (e.g., link_account, search_transactions_tool), others use noun_verb (e.g., spending_summary_tool), and some are more descriptive (e.g., summarize_debt_tool). While all names are readable and snake_case is used throughout, the lack of a uniform verb-first or noun-first convention reduces predictability.
With 24 tools, the count is on the higher side but reasonable for a comprehensive financial data server like Plaid. It covers a wide range of operations from account linking to debt analysis, which justifies the breadth. However, it borders on being heavy, as some tools might be consolidated (e.g., transaction-related tools).
The tool set provides excellent coverage for financial data management. It includes core CRUD operations (e.g., add/remove/update external debts, link/remove institutions), data retrieval (balances, transactions, holdings, liabilities), and advanced analysis (spending summaries, debt payoff projections). There are no obvious gaps; agents can perform end-to-end workflows from linking accounts to analyzing financial health.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
An MCP server that provides read access to your cloud storage providers, bank accounts and more.
Query your real net worth, spending, transactions, budgets and portfolio from any MCP client.
Read-only bank & investment accounts via Plaid: balances, holdings, transactions, SQL analytics.
Personal finance for AI agents — onboard, import statements, categorize & budget over MCP.
Related MCP Servers
- AlicenseAqualityCmaintenanceSelf-hosted, read-only MCP server that connects banks, credit cards, loans, and brokerage accounts via Plaid. 9 tools for balances, transactions, recurring charges, liabilities, and investment holdings.97MIT
- AlicenseNot gradedqualityDmaintenanceA local MCP server that provides read-only SQL access to financial accounts via Plaid, enabling natural language queries about transactions, balances, and holdings.MIT
- FlicenseNot gradedqualityBmaintenanceMCP server for personal finance management. Enables natural language expense logging, budgeting, recurring charge detection, and statement import with deterministic local calculations.
- FlicenseNot gradedqualityBmaintenanceMCP server for personal finance via Open Finance, consolidating accounts and cards and answering spending questions with aggregated numbers. Provides tools for category spending, recurring subscriptions, budgets, card bills, and installment forecasts, with data stored locally in an encrypted SQLite database.1
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/t-rhex/plaid-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server