bank-mcp
Click on "Deploy 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., "@bank-mcpshow me my recent transactions across all linked banks"
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.
bank-mcp
Unofficial, read-only MCP server for your own UK bank and card data, via TrueLayer Open Banking. It can read accounts, cards, balances and transactions. It cannot move money: only read scopes are ever requested.
Not affiliated with TrueLayer or any bank. See SECURITY.md before linking real accounts.
Setup
Requires Python 3.11+ and uv (or pip).
git clone https://github.com/pritch56/bank-mcp.git
cd bank-mcp
uv sync
uv run bank-mcp-link --helpOr install the package into any environment with pip install .; this provides the bank-mcp (server) and
bank-mcp-link (bank linking) commands.
Related MCP server: C6 Bank MCP
Get TrueLayer credentials
Create a free account at the TrueLayer Console.
Create an application and note its client ID and client secret. Start with the sandbox, then switch to live.
In the application's settings, add this redirect URI:
http://localhost:3000/callback(use the same port as--portif you change it).Make sure the Data API is enabled with these scopes:
info accounts cards balance transactions offline_access.Export the credentials in the shell you run
bank-mcp-linkfrom:
export TRUELAYER_CLIENT_ID=your-client-id
export TRUELAYER_CLIENT_SECRET=your-client-secret
export TRUELAYER_ENV=sandbox # or "live" (the default)Never commit these values. .env files are git-ignored.
Link a bank
bank-mcp-link opens your bank's sign-in page in the browser and stores the resulting tokens under a nickname of
your choice. You can link several banks.
# Sandbox (no real bank needed)
uv run bank-mcp-link --provider mock --name test --sandbox
# A real bank: use its TrueLayer provider id, for example ob-nationwide
uv run bank-mcp-link --provider ob-nationwide --name nationwide
uv run bank-mcp-link --list # linked banks and consent expiry
uv run bank-mcp-link --remove nationwide # forget a bankIf the browser does not open, copy the URL printed in the terminal. Linking waits five minutes for the redirect.
UK Open Banking consent lasts 90 days. When it lapses, tools return Reconnect required for '<bank>'; run
bank-mcp-link again for that bank.
Tokens are stored in ~/.bank-mcp/tokens.json, readable only by you.
Configure your MCP client
Replace /path/to/bank-mcp with your checkout. The server reads the same TRUELAYER_* credentials from its
environment, and uses the provider id and environment recorded when each bank was linked.
Claude Desktop
Add to claude_desktop_config.json (Settings > Developer > Edit Config), then restart Claude Desktop:
{
"mcpServers": {
"bank": {
"command": "uv",
"args": ["run", "--directory", "/path/to/bank-mcp", "bank-mcp"],
"env": {
"TRUELAYER_CLIENT_ID": "your-client-id",
"TRUELAYER_CLIENT_SECRET": "your-client-secret",
"TRUELAYER_ENV": "live"
}
}
}
}Claude Code
claude mcp add bank \
--env TRUELAYER_CLIENT_ID=your-client-id \
--env TRUELAYER_CLIENT_SECRET=your-client-secret \
--env TRUELAYER_ENV=live \
-- uv run --directory /path/to/bank-mcp bank-mcpHost it on Cloudflare Workers
To run the server remotely instead of over stdio, see worker/README.md: a TypeScript Worker with Workers KV for tokens, protected by Cloudflare Access.
Tools
bank-mcp (stdio) exposes five read-only tools. Each except list_connections takes an optional bank
nickname; leave it out to query every linked bank.
Tool | Returns |
| Linked banks and consent expiry |
| Accounts and cards |
| Balances (optionally one |
|
|
| Pending transactions |
When all banks are queried, the working banks are still returned and the failing ones are listed under errors.
Configuration
Variable | Meaning |
| TrueLayer Console credentials (required) |
|
|
| Provider id; set automatically per bank by |
| Token file path (default |
| Longest date range a single transaction query may span |
| Optional refresh-token seed |
Development
See CONTRIBUTING.md. Release history is in CHANGELOG.md.
Licence
Available Tools
5 toolsget_balanceCRead-onlyIdempotent
Balances. bank is a nickname (omit for all banks); account_id narrows to one account.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | No | ||
| account_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so the safety profile is covered. The description adds essentially nothing behavioral beyond the implicit fact that omitting `bank` aggregates across all banks; it says nothing about freshness, result shape, or failure behavior for an unknown nickname.
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?
Two short clauses with zero filler and the aggregation rule stated up front. The terseness borders on under-specification rather than verbosity, but nothing is redundant.
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?
An output schema exists, so return values need not be explained, and both parameters get some meaning. Still, a two-parameter read tool whose entire purpose statement is the single word "Balances" leaves an agent guessing about scope and about when this beats list_accounts.
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 carry the load, and it does partially: it clarifies that `bank` is a nickname rather than an ID and that omitting it aggregates, and that `account_id` narrows scope. It leaves the accepted `account_id` format and the interaction between the two filters unstated.
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?
"Balances." names the resource but supplies no verb and no scope statement; an agent must infer that this retrieves account balances. It is distinguishable from the list_* siblings by subject matter, but only weakly, since nothing says how it differs from list_accounts.
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 only guidance is parameter-level ("omit for all banks", "narrows to one account"). There is no statement of when to call this versus list_accounts or list_transactions, and no prerequisites or exclusions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_accountsARead-onlyIdempotent
List accounts and cards. bank is a nickname; omit it to query all linked banks.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotations already declare this to be a safe, idempotent, read-only operation against an open world, so the safety profile is fully covered. The description adds the useful behavioral detail that omitting the bank widens scope to every linked bank, but says nothing about result ordering, pagination, or empty results. With annotations carrying the heavy load, this is adequate but not rich.
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?
Two short sentences, no filler, with the primary action stated first and the parameter clarification second. Every clause carries information the agent cannot get from the schema or annotations.
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 single optional parameter tool with an output schema that documents return values, the description covers what the tool does and how the parameter's absence changes scope. The remaining gap is where an agent obtains valid bank nicknames, which likely requires the list_connections sibling that goes unmentioned.
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 schema supplies only the name 'bank' with no meaning attached. The description compensates by defining bank as a nickname and by specifying the null/omitted case as a query across all linked banks, which is the key semantic the agent needs. It stops short of showing the nickname format or where such nicknames come from.
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 opens with a specific verb and resource set, 'List accounts and cards', which is enough for an agent to separate this tool from get_balance or list_transactions. It never names a sibling tool or states the boundary explicitly, so the differentiation is inferred from the resource rather than declared.
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 phrase 'omit it to query all linked banks' tells the agent the default behavior when the optional parameter is skipped, which is genuine usage guidance. It does not say when to prefer list_connections or list_pending, nor does it explain any prerequisite for having a linked bank.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_connectionsARead-onlyIdempotent
List linked banks with consent expiry. Banks needing re-linking say 'reconnect_required'.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint, idempotentHint, and destructiveHint=false, so the safety profile is covered. The description adds one genuinely new behavioral detail — that entries can carry a 'reconnect_required' state when consent lapses — but says nothing about result shape or limits beyond that.
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?
Two short sentences, zero filler, and the most decision-relevant fact (the reconnect_required flag) is stated up front rather than buried.
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?
With an output schema present and full annotation coverage, the description only needs to convey scope and the notable status value, both of which it does. It is slightly thin on what 'consent expiry' looks like as a value, but that is reasonably delegated to the output schema.
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 takes zero parameters, so the schema imposes nothing to interpret and the baseline is 4. The description correctly implies no filtering input is available, which is consistent with the empty argument 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?
"List linked banks with consent expiry" gives a specific verb (list) and resource (linked banks), plus the key payload attribute (consent expiry). It is distinguishable from siblings like list_accounts and list_transactions, though the description never names them explicitly.
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?
Usage is only implied: an agent can infer this is the tool for auditing bank connections and finding ones needing re-linking. There is no explicit when-to-use/when-not guidance and no reference to the sibling tools that cover related listing needs.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_pendingCRead-onlyIdempotent
Pending (not yet settled) transactions. bank is a nickname; omit it for all banks.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | No | ||
| limit | No | ||
| offset | No | ||
| account_id | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, idempotentHint=true, destructiveHint=false and openWorldHint=true, so the safety profile is fully covered by structured data. The description adds only a definition of "pending"; it says nothing about result volume, ordering, pagination behavior, or whether pending items are cached/eventually consistent — which matters for a live-finance read.
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?
Two sentences, front-loaded with the resource definition and zero filler. It is tight and readable, though the second sentence jumps to parameter detail without first establishing scope or alternatives.
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?
This is a low-complexity read-only list tool, and the definition covers the core semantic (what "pending" means) plus the one non-obvious parameter behavior. Missing: differentiation from list_transactions, and any hint about limit/offset/account_id semantics, which leaves gaps despite the low complexity.
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% across 4 parameters, so the description carries the burden and only partially discharges it: it explains that `bank` is a nickname and that omitting it means all banks. The limit, offset, and account_id parameters get no explanation at all, and `bank` vs `account_id` — the one distinction most likely to confuse an agent — is never clarified.
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 names the resource precisely and defines the key term inline ("Pending (not yet settled) transactions"), so an agent knows it returns unsettled transactions rather than settled history. It does not distinguish itself from the sibling list_transactions, so the agent must infer the boundary from the name alone.
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?
There is no statement of when to use this tool versus list_transactions or get_balance, and no prerequisites or exclusions. The only usage-like sentence ("omit it for all banks") is a parameter hint rather than a selection rule.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_transactionsARead-onlyIdempotent
Transactions with since <= date < before (ISO dates; default the last 30 days), oldest first.
Page with limit and offset; next_offset is null on the last page.
| Name | Required | Description | Default |
|---|---|---|---|
| bank | No | ||
| limit | No | ||
| since | No | ||
| before | No | ||
| offset | No | ||
| account_id | No | ||
| include_pending | No |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnly, idempotent, non-destructive and open-world, so safety is covered. The description adds genuinely new behavior: the default 30-day window when dates are omitted, oldest-first ordering, and the pagination contract with next_offset becoming null on the final page. It stops short of noting anything about rate limits or cost of deep offsets.
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?
Two tight sentences with zero filler. The range semantics and default window are front-loaded, and paging is handled in a compact follow-up sentence.
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?
An output schema exists, so return values need no explanation and pagination is adequately described. But for a seven-parameter read tool with 0% schema coverage, the description leaves the filter parameters (bank, account_id, include_pending) unexplained, so an agent cannot confidently construct a filtered query.
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 carries the full burden. It explains the format and semantics of since, before, limit and offset well, but leaves three of seven parameters — bank, account_id and include_pending — completely undocumented in both the schema and the description.
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?
States the resource (transactions), the filter semantics (since <= date < before), the default window (last 30 days) and the sort order (oldest first), so an agent knows exactly what it gets. However, it does not distinguish itself from the sibling list_pending or explain why one would choose this over list_pending, despite this tool exposing include_pending.
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?
Usage is only implied: the default last-30-days window hints at the common case, and the paging sentence implies repeated calls for large result sets. There is no explicit when-to-use or when-not-to-use guidance, and no routing to list_pending or list_accounts as preparation steps.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
5 tool updates
v0.1.2- First observed
get_balance - First observed
list_accounts - First observed
list_connections - First observed
list_pending - First observed
list_transactions
TDQS
Scored across 5 tools
Most tools target clearly distinct data: connections, accounts, balances, transactions, pending items. list_transactions and list_pending overlap in domain (both return transactions), but descriptions make the settled vs. unsettled distinction clear, so confusion is limited.
All five tools follow a consistent verb_noun pattern: list_connections, list_accounts, list_transactions, list_pending, and get_balance. Predictable and easy to scan.
Five tools is well-scoped for a read-only banking data surface; each tool covers a distinct query need without bloat.
The read surface is solid: consent status, accounts, balances, settled and pending transactions, with pagination on the one listing that needs it. Minor gaps exist—no account detail/routing info, no transaction lookup by merchant or ID, and no write operations like transfers, though those may be intentionally out of scope.
Maintenance
Related MCP Connectors
Read-only access to your own UK bank data: spending, subscriptions, payday plan, net worth.
Read-only access to your bank, investment, and crypto accounts: balances, transactions, holdings.
Read-only access to your Finch finances: accounts, transactions, spending, net worth, goals.
Read-only access to Genie accounts, transactions, investments, and financial summaries.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables read-only access to personal bank accounts via the TrueLayer API, allowing querying of accounts, balances, transactions, and generating financial analytics such as spending by category, subscriptions, and monthly summaries.91MIT
- AlicenseNot gradedqualityDmaintenanceEnables reading C6 Bank account balances, statements, credit card bills, and investments via Open Finance Brasil. It is read-only and regulated by the Central Bank of Brazil.MIT
- AlicenseBqualityCmaintenanceEnables Claude to read UK bank account data—balances, transactions, cards, standing orders, direct debits, and identity—through TrueLayer's Data API, with local caching and optional live refreshes. It is read-only by design, requiring consent and never moving money.121MIT

Truthifi MCP serverofficial
AlicenseNot gradedqualityAmaintenanceEnables AI assistants to read a verified household financial record across linked accounts, including holdings, transactions, fees, performance, cash flow, advisors, diagnostics, and score findings. It can also refresh connections and manage manually tracked assets or liabilities inside the service, but cannot move money or place trades at financial institutions.MIT