Available banking operations via Model Context Protocol (MCP)
Protocol: JSON-RPC 2.0 over Streamable HTTP
MCP Endpoint: /mcp
Methods: tools/list, tools/call
Authentication: JWT in
Authorization header (from httpOnly
cookie via Agent), integration in
X-Bancony-Integration
Note: User tokens are stored in httpOnly cookies for security. The Agent reads the cookie and forwards the token to MCP Server via headers.
Get the user's bank accounts and cards. Returns each account with balances, identifiers (account number, plus IBAN/BBAN/BIC or masked PAN where the bank has them), holder, product, type, lifecycle status, and usage. Field shapes follow the Berlin Group PSD2 `accountDetails` model where they overlap.
Get bank transactions. Returns a list of transactions with amounts, dates, descriptions, and categories. The `verbosity` parameter selects between a compact default (`minimal`) and full transactions view (`full`) that surfaces every optional ISO 20022 / Open Finance field the server can populate. This tool returns data only — call it freely while reasoning and answer amount questions from it in ONE plain sentence. To DISPLAY results visually, use whichever display tools are in your toolset: `show-transactions` for a transaction list, `compare-spending` for a period comparison, `present-insight` for other charts, or `spending-summary` for the breakdown card — and only when the customer asked to SEE something. No display tool for it in your toolset → answer in text. For a company this is also the cross-account statement spanning ALL the company's accounts AND company cards by default (credits and debits, card purchases with merchant and category); narrow with account_ids. A row names its counterparty, so description finds a payer or payee by name. When a payer's name finds nothing, search by amount (min_amount/max_amount) and date range instead and read the row's reference text. get-accounts lists the accounts themselves (balances, IBANs), not their movements; balance-over-time questions are get-balance-history, not this.
NewestFirst OldestFirstLook up a single transaction by id and return every field the server can populate, including `counterparty` (with `postalAddress` for card entries) and the open `properties` bag of ISO 20022 / SEPA / card audit metadata (remittance text, end-to-end / mandate / creditor ids, purpose / transaction codes, MCC, masked PAN, etc.). Use this for audit / reconciliation flows; for compact lists prefer `get-transactions` with a `verbosity` cap.
Get transaction categories. Returns a list of categories that transactions can be classified into.
Get an aggregated summary of transactions, scoped to either income or expenses. Returns totals, counts, and averages, optionally grouped by category, month, or both. Filters mirror get-transactions: account, date, amount range, category ids. This tool returns data only — call it freely while reasoning and answer amount questions from it in ONE plain sentence. To DISPLAY results visually, use whichever display tools are in your toolset: `show-transactions` for a transaction list, `compare-spending` for a period comparison, `present-insight` for other charts, or `spending-summary` for the breakdown card — and only when the customer asked to SEE something. No display tool for it in your toolset → answer in text. For a company prefer group_by='none' for a total and group_by='month' for a trend — those are accurate. A category breakdown is NOT representative for a company: supplier payments are sent as payment batches and arrive uncategorized, so most outgoing money lands in an uncategorized or null-category group. If you do group by category, name that bucket explicitly as uncategorized rather than describing the split as a complete picture of where the company's money went, and never read a category total as a supplier total. For spend on a named supplier, list the transactions with get-transactions and total those instead.
Income Expensesnone category month bothGet saved payment recipients filtered by name. Returns matching recipients with their account details. Pass an empty name ("") to list ALL saved recipients — use that when the customer asks what recipients they have; the customer's own accounts are excluded from that listing. Never claim a recipient does or does not exist without calling this tool first.
SHOW the customer a large visual spending-breakdown card (donut chart or income-vs-spending bars) grouped by category, category group, month, or merchant. This is a DISPLAY tool: calling it always renders the big card in the chat, so call it ONLY when the customer explicitly asks to see, show, visualise, chart or break down their spending ("spending overview"). For a QUESTION about an amount — how much they spent on something, in a category, at a merchant, or in a period — do NOT call this: use get-transactions-summary with category_ids or search_text and answer in one plain sentence. A scalar question deserves a scalar answer, not a full-screen chart.
Get the bank's brand kit — colours, chart palette, font and logo — to STYLE any chart, graph, dashboard, table or visual you create. Call this before building a visualization so it matches the bank's brand: use chartColors (in order) for series, primary/accent for highlights and headers, fontFamily for text, and put logoSvg in the header. Read-only; takes no input.
Present the answer to an open-ended, analytical question about the customer's money as a branded, interactive card. Use this AFTER you have gathered the data with the read tools (get-transactions, spending-summary, etc.): pick the archetype that best fits the answer and pass the data you computed. The bank's brand and the display language are applied automatically — do not pass them. Choose the archetype: • breakdown — parts of a whole ('where does my money go?'). • trend — a value over time ('is my spending going up?'). • comparison — two or more sides ('this year vs last', 'budget vs actual'). • ranked — a leaderboard ('top merchants', 'biggest payments'). • insight — a narrative finding + an optional supporting mini-viz. `data` is an OBJECT, never a bare list, and every row is {label, value}: breakdown → data={title, total, currency, segments:[{label, value}]}; trend → data={title, currency, points:[{label, value}]}; ranked → data={title, currency, rows:[{label, value}]}; comparison → data={title, currency, periods:[{label, total}]}; insight → data={headline, body}. Values are positive amounts the read tools returned — never estimates. Write `content` as a plain-English summary; put every on-screen title and label in the language of the customer's MOST RECENT message — an English question gets English titles and labels. Merchant or category names in the data are not a reason to write the card in their language; translate them into the customer's language. The data tools (get-transactions, get-transactions-summary, get-unpaid-bills, get-loans) render their own branded cards for routine answers; reserve this for the ad-hoc, open-ended analysis they don't cover.
Compare the customer's spending in a window against the SAME window one year earlier, rendered as ONE interactive branded card (tap a month to drill into days and the underlying transactions; the card's own controls switch period, so one call also covers follow-ups). `window` is a single free-form string — ALWAYS carry the user's stated period into it verbatim: "May" → window='may'; "Q2" → window='q2'; "2024" → window='2024'; nothing stated → omit (year-to-date). The comparison is ALWAYS against the year before, so when the customer names two consecutive periods `window` is the LATER one: "2025 vs 2026" → window='2026' (window='2025' would show 2025 against 2024 — the wrong pair). Two periods that are not a year apart ("March vs June", "2023 vs 2026") are not this tool: answer those in text from two get-transactions-summary calls. Optionally focus on one merchant via `merchant` — "how much did I spend at Starbucks in May vs last year" → window='may', merchant='Starbucks'. Expenses only; brand and language are applied automatically.
SHOW the customer their transactions as the bank's branded statement card (expandable table with PDF / Excel / CSV export). Call this when the user asks to SEE / show / display transactions ("show me those transactions") — one call renders one card; never paste a transaction list as text instead. Filter with `description` (payee text); with `categories` — a LIST of one or MORE spending categories to INCLUDE (names like 'groceries' or derived ids like 'mcc_5411' / 'tk_03'), matched by name or id; with `exclude_categories` — a LIST to leave OUT (e.g. show everything except transfers, or drill into an 'Other' slice by excluding the big named categories); and either `window` (a period string: 'may', 'q2', '2025', '3m', omit for year-to-date) or explicit `start_date`/`end_date`. Pass several categories at once in `categories` — it is a list, not a single value. For reading data silently while analysing, use get-transactions instead.
CARD-SUPPORT tool: produce the bank's own account-statement file (PDF or Excel) for a date range, returned as base64 for file download. The show-transactions card's export buttons call this; you should almost never call it yourself — when the user wants to see or export transactions, call show-transactions (its card carries the export buttons). Never read or echo the returned base64 content; it is delivered to the customer as a file. Range works like show-transactions: explicit start_date/end_date win over window; neither means year-to-date.
Get the holder's loans with full detail: outstanding balance, interest rate, whether the loan is indexed or not, the monthly payment, and how much of the latest payment went to principal versus interest. Use this when the user asks about a mortgage, car loan, personal loan, or — for a company — its operating loan: total debt, what rate they pay, how much is left, the term, or how much of a payment is interest. Works for individuals AND companies; for a company this is the online bank's loans view, and get-accounts lists the same loan as an account with only its balance, so come here for the rate, the indexing and the interest split. The result renders as visual loan cards in the customer's UI, so also call this when the user asks to see or show their loans.
List the unpaid bills the holder has to PAY (e.g. utilities, telecom, insurance, supplier invoices) — with status, due dates, amounts and a summary. Works for both individuals and companies (a company's accounts payable). Use when the user asks what they owe, about pending or overdue bills, or to see/show their unpaid bills. These are bills the holder OWES; for a company's receivables — claims it has issued, money owed TO it — use list-claims instead. Each bill is settled individually against its own payment reference — incoming bills are never bundled into a payment batch (create-payment-batch is for OUTGOING mass payments to payees, the opposite direction). Bills marked auto_pay=true are informational only — do not offer to pay them; they settle automatically on the due date by direct debit. If a bill is overdue, mention the late-payment interest (late_fee) so the user knows the cost of waiting. To pay ONE bill on its final due date in bank-authorised mode, call create-payment-order with kind='bill_payment', the bill's id, its amount and requested_execution_date = its final_due_date. To pay SEVERAL, make ONE create-payment-order call with bill_ids = every id and amount = their total, and leave requested_execution_date out so each bill keeps its own final due date — different final due dates are not a reason to split into several calls. The result renders as a visual bills card in the customer's UI.
List the holder's electronic-documents inbox — payslips, payment slips for bills, monthly account statements — newest first, defaulting to the LAST 6 MONTHS when no dates are given (the card lets the customer adjust the range themselves). Each document is exactly what a bank's inbox holds: a title, the date it arrived, and a per-document pdf_url. This is an INBOX LISTING, nothing more: use it only when the user asks about the documents themselves — show my payslip, what documents have arrived, when did the statement arrive, open my payment slip. When the user asks for a SPECIFIC kind of document or sender (payslips from an employer, payment slips from a lender), do NOT list the whole inbox: call get-document-senders first and pass the matching sender here as the sender filter. It is the WRONG tool for amount or 'how much' questions: what was I paid is answered from the salary credit in get-transactions; bill amounts come from get-unpaid-bills. The result carries NO document content — titles, senders, dates and links only — so never present figures as coming from a document you have not read. To let the user open a document, give them its pdf_url: a SHORT-LIVED signed link (expires within minutes) — offer it to open right away, never store it, quote it as a stable reference, or fetch it yourself; re-call this tool to mint fresh links. Reading a document's contents requires the separate fetch-document tool (if present) and the user's explicit request. A payment slip references its bill via bill_id, so pair with get-unpaid-bills to connect a payment slip to the bill it settles; paying still happens through the bill/payment tools, never here (this tool is read-only). The result renders as a documents card listing the documents in the customer's UI — do NOT repeat the list in your reply. Answer with ONE short sentence (e.g. how many arrived and the most recent); if the user asked about one specific document, mention just that one.
List WHO sends the holder electronic documents — the distinct issuers in the document inbox (employers' payslips, a lender's payment slips, the bank's statements …), each with its name and national ID. Data only, no card. Use this BEFORE get-documents whenever the user asks about a specific kind of document or sender, then pass the matching sender to get-documents' sender filter so the customer sees only the relevant documents instead of the whole inbox.
Return coarse demographics for the authenticated user — age range, gender, postal-code prefix, language. Used by the agent at WebSocket-open time to enrich PII-sanitizer trace metadata. Plugins that don't implement this return `supported=false`.
Return the authenticated customer's display identity (name and email) so the agent can populate the live-agent CRM at handover time. Plugins that don't expose customer info return `supported=false`. Used by the handover_finalize node, not by the LLM directly.
Return the authenticated holder's segment — `retail` (individual) or `corporate` (company). Used by the agent at WebSocket-open time to tailor the assistant's suggested-prompt start screen to the customer. Plugins that don't distinguish the two return `supported=false`.
Search the bank's own knowledge base (products, fees, terms, policies, processes, branches/opening hours, FAQs) and answer ONLY from what it returns. Call this BEFORE answering any bank-specific factual or 'how do I…' question — never answer those from general knowledge. - The knowledge base is the bank's own published material: answer from the passages, in the voice your system instructions give you, and link the exact source page. Never brush the customer off with 'check the bank's website' — you have the bank's material, so quote it and link it. - Catalog/overview questions need more than one search: run 2-3 searches with different phrasings (the category, then the specific product names seen in the first results) and synthesize a complete, structured answer — name each product found with one line on who it suits. - A specific product's price, fee or terms lives on THAT product's page, so search for the product BY NAME, one search per product when the customer asks about several — a category search returns the catalog, not each product's figures, and answering a price question without the price is a failed answer. - Ground every factual claim in the returned passages and cite sources as markdown links — inline or as a final 'Sources:' line with each result's [title](url). Every knowledge-base answer must carry at least one source link. - Rates, fees and other volatile figures: quote them only when a returned passage states the figure, and attach its as-of date (from the passage's effective_date). If the passages describe the product but NOT the figure asked for, do not present tables with the numbers missing — say plainly that the exact figure isn't in your material, link the product/price-list page where it lives, and offer to connect a human. For the customer's own balances/transactions use the account tools, never the knowledge base. - Many products exist in a personal and a business version. Default to the personal version for a retail customer — never present the business version as the answer while claiming the personal one is unknown; search again for the personal version if needed. - If the search returns nothing relevant (no results, or a recoverable code), do NOT answer from general knowledge. Say plainly — in the customer's language — that you do not find it in the bank's documents. ONLY IF a human-handover tool is available to you, offer to connect a human and call it with a reason that includes the customer's original question; if you have NO such tool, do NOT offer to connect anyone — instead point the customer to the bank's own service channels. Never guess an answer. - Do not pass the limit parameter — the server default returns the right amount of context. Your search queries may be phrased in any language, and retrieved passages may be in another language than the customer — always write the final answer in the language of the customer's message.
Ask the user a short multiple-choice question and let them pick by tapping a button — the chat input turns into one button per option (plus an automatic Cancel button), and the user's tap comes back as their next message. Use it when you are NOT certain how to proceed and must not guess: - a recipient name that matched SEVERAL saved recipients (one option per candidate, so the user picks which one); - which of the user's own accounts to pay from, when it is genuinely unclear; - any yes/no you need before moving money or creating something. For a name that matched NO saved recipient, do NOT use this tool — there is nothing to choose, you simply need their account number; ask for it as a normal chat message. Only ask when there is real doubt — when exactly one saved recipient clearly matches, just proceed. Pass a short `question` and 2-4 concrete `options` phrased as the choices themselves — say what each one does (e.g. 'Transfer to **John Smith**', 'Transfer to **John Brown**'), not bare 'Yes'/'No'. Do NOT add a Cancel/'No' option of your own — a Cancel button is always added for you, so a second one is a confusing duplicate. Bold the recipient or account name with **double asterisks** wherever you name it — in the question, the options, and your message; never use «French» quotes. Both `question` and `options` must be in the user's language. The turn ends as soon as you call this tool, and the card already shows BOTH the question and the options — so do NOT also write them as a chat message; say nothing else on that turn. After the user replies, act on their choice; if they cancel, acknowledge briefly and stop — do not move money.
Get the corporate account holder's profile: company name, company ID, VAT number, legal form, and the list of users with their roles, signing authority and approval limits. Use when the user asks about the company itself, who can approve payments, who holds signing authority, or the team's access rights. Identity and people only — balances are get-accounts and loans are get-loans. Company/corporate accounts only.
List the company's issued claims / receivables (the company as creditor), with payer, amount, due date and status. Use for 'our claims', who owes us, or overdue invoices. Optionally filter by status, or set overdue_only=true to return only claims past their final due date. Also the way to answer a question about ONE claim: when the user names a claim number (a claim number, or an invoice's payment reference), list the claims and read that number's row out of the result — there is no separate single-claim tool. These are receivables owed TO the company — bills it must PAY are get-unpaid-bills. Company/corporate accounts only.
List the company's payment batches with type, status, line count and total amount. Use for 'our payment batches', recent or pending outgoing payment runs — and for what awaits sign-off: status 'awaiting_approval' means a batch still needs its one approval, 'approved' means it is approved and ready to pay. Optionally filter by status (draft / awaiting_approval / approved / completed). The agent never approves — an authorized user approves and pays in the bank's own online bank. For one batch's payee lines and approval detail use get-payment-batch. Read-only: to SET UP new outgoing payments (refunds, payouts, a pasted payment file) use create-payment-batch. Company/corporate accounts only.
Get one payment batch in full: its payee lines and its live approval state — whether it still needs its one approval or already has it, and any rejection. Use to inspect a specific batch before discussing it. The agent never approves — an authorized user approves and pays it in the bank's own online bank. If the user names a batch instead of giving its id (e.g. 'open the Suppliers batch'), first call list-payment-batches, match the name, and pass that batch's id here — never ask the user for the id. Company/corporate accounts only. The result renders as a payment-batch card in the customer's UI showing every line, the debit account and the approval state — do NOT repeat the batch in your reply. Answer with ONE short sentence (the batch's name, status and total, or what just changed); if the user asked about one line or one field, mention just that.
Get the company's total-position history: month-end snapshots of the whole position over time — total deposits, total loans (negative) and the net position, each in the company's home currency (the result's currency) with any foreign-currency balances converted at the bank's rates. Use when the user asks how the company's overall position or balances have developed over the year, about trends in total assets / the net position, or to chart total balances over time. Pass months to widen or narrow the window (1–36 month-ends, default 13). This is the time series; get-accounts is the position as it stands now, and get-loans the borrowing behind it. The series is computed from the statement balances the bank already holds, and is already aggregated and FX-converted — do not sum accounts by hand. Company/corporate accounts only.
List the bank-account products available to the company: current, savings, term-deposit and currency accounts, each with its interest rate and binding terms. Use when the user asks what accounts or savings options exist, or about deposit interest. Read-only: there is no tool that opens an account — say the company opens it in the bank's own online bank. Company/corporate accounts only.
This example shows how the Agent communicates with MCP Server. User tokens come from httpOnly cookies.