cata-centavo
v0.3.1
Published
MCP server for Brazilian Open Finance data, via Pluggy
Maintainers
Readme
Cata-centavo
Ask an agent about your own money. Brazilian Open Finance data over MCP, via Pluggy.
Install · Commands · Categories · Limits · Tools · License
Cata-centavo lets you ask an agent about your own money. Point it at your bank, credit card and investment accounts and ask what you spent on food last month, how the current card statement is going, or where a strange charge came from.
You run it on your machine, against your own accounts, and the categories you correct stay there. There is no hosted version and nothing multi-user about it.
Install
You need Node 22.13 or newer, and a Pluggy account with your banks already connected.
Getting your Pluggy keys
The bank data comes from Pluggy, the Open Finance provider that does the talking to the banks. Cata-centavo only reads connections that already exist, so make them first.
- At MeuPluggy, create your account and connect your banks
- Then go to the other Pluggy portal, log in, and connect your MeuPluggy accounts to the Demo app. Also copy your
PLUGGY_CLIENT_IDandPLUGGY_CLIENT_SECRETfrom this page
- Then connect your MeuPluggy accounts one by one into the Demo App
- And then copy the
PLUGGY_ITEM_IDS, one by one
That gives you three values, all required:
PLUGGY_CLIENT_ID from your Pluggy dashboard
PLUGGY_CLIENT_SECRET from your Pluggy dashboard
PLUGGY_ITEM_IDS connection ids, separated by commasThe plain way is to export them from your .zshrc or .bashrc, and in the MCP configuration file write "PLUGGY_CLIENT_ID": "${PLUGGY_CLIENT_ID}". That leaves your keys in a file every shell reads. If you would rather not, secret-tool keeps them in your keyring and a small wrapper script can pull them out right before the server starts. Setups differ enough that it is worth pointing your agent at this page and asking it which one fits your machine.
After configuring this, run npx cata-centavo@latest doctor to check that your environment variables are working
Adding it to Claude Code
claude mcp add cata-centavo \
-e PLUGGY_CLIENT_ID=... \
-e PLUGGY_CLIENT_SECRET=... \
-e PLUGGY_ITEM_IDS=... \
-- npx -y cata-centavo@latestDrop the -e flags if the three variables are already exported in the shell you start Claude Code from, since the server inherits that environment.
The @latest is worth keeping. npm holds a cache for npx, and depending on which npm you have, a bare npx cata-centavo can be served out of that cache for months without ever asking the registry whether something newer exists. Naming the tag removes the doubt: your client checks on every start, and you get the current version.
Other clients take the same thing as JSON:
{
"mcpServers": {
"cata-centavo": {
"command": "npx",
"args": ["-y", "cata-centavo@latest"],
"env": {
"PLUGGY_CLIENT_ID": "...",
"PLUGGY_CLIENT_SECRET": "...",
"PLUGGY_ITEM_IDS": "..."
}
}
}
}Commands
cata-centavo(no argument): runs the MCP server over stdio.cata-centavo init: checks that the credentials and every configured connection are readable, and reports which ones are not.cata-centavo doctor: a fuller diagnosis, covering connection status, consent state, what is cached locally, and whether the learned categorization map has anything in it yet.
Categories
Categories come from your provider while your plan includes transaction enrichment. Every sync copies them into data.db, which is never dropped, so they survive the day the enrichment stops and the day the cache is rebuilt.
Alongside that, the server learns which categories go with which CNPJs from your own transactions. Only from a CNPJ, never from a CPF, and only when that merchant's transactions actually agree. A CNPJ has a line of business. A CPF is a person, and guessing that everything you send your sister is a "transfer" would then be applied backwards over everything you ever sent her.
That learned map is built from your data, on your machine, and is not shipped with the tool, because a CNPJ-to-category table is a line of somebody's bank statement. So there is a real asymmetry: if you install this after your own enrichment has already stopped, the map starts empty and has nothing to learn from. You still get merchant-code categorization on card purchases, plus whatever you correct by hand, and corrections apply retroactively. But you will be doing more of the work than someone who installed earlier.
Ask the agent to show you what is uncategorized and tell it what those merchants are; both kinds of correction stick.
What it cannot see
- A bank linked in MeuPluggy whose UUID never reached
PLUGGY_ITEM_IDSis invisible to this server. No endpoint lists the items on a Pluggy account, so this cannot be fixed in software. Comparedoctor's list against the banks you know you linked. - Freshness is Pluggy's schedule, not this server's. There is no "sync now": on-demand refresh is refused outright. One of the author's own three connections went three days without syncing while still reporting itself up to date, with nothing in the response explaining why.
- A credit card's
usedCreditfigure is not what the card owes this month. It mixes the current billing cycle with instalments that have not been charged yet, and will not match what a banking app shows.getBillSummaryanswers that question instead, and it answers with a range rather than one number. - An instalment plan is put back together from the rows in the cache, so a purchase whose first instalments were never cached can say what is left to pay but not what it cost.
listInstalmentPlansleaves that figure out instead of guessing at it. - An investment position tells you what it is worth now and nothing about how it got there. Pluggy returns fields that look like cost and profit, but they are not defined the same way across position types, so publishing one as a return would give a precise-looking wrong answer.
getInvestmentsalso leaves currencies apart: no conversion, and no total across them.
Tools
Accounts and balances
getAccounts: lists every account across your configured connections, with balances and credit card limits.getBalance: consolidated cash and credit-used figures across all connections, reported separately because they are not the same kind of number.getBalanceByAccount: the current figures and details for one account.
Spending
getTransactions: totals spending and income over a date range, grouped by category.listTransactions: individual transactions over a date range, paged.getTransactionDetails: full details for a bounded set of transaction ids.
Credit cards
getBills: statements for one card, newest first.getBillSummary: the cycle still in progress, as two independent estimates rather than one invented number.listInstalmentPlans: purchases still being paid in instalments, with what is left on each one and the month it finishes.setClosingDay: records a card's closing day locally, for banks that do not report it.listClosingDays: the closing days stored so far.deleteClosingDay: drops a stored closing day.
Investments
getInvestments: active investment positions across your connections, with balances and totals per currency.
Categories
setCategory: corrects the category of specific transactions.setCounterpartyCategory: assigns a category to everyone a CPF or CNPJ identifies, backwards and forwards.
Diagnostics
listSources: lists every configured connection with its sync status and consent state.
Each tool's exact parameters and return shape are published in its own MCP description, which is what a model actually reads and the one version that cannot drift out of sync with a signature.
License
MIT. See LICENSE.
