Most guides on how to build an MCP server stop at a weather API and a stdio transport. That is enough to see the protocol work, and nowhere near enough to point Claude at Exact Online, Yuki or AFAS. European accounting systems bring per-tenant OAuth, per-division rate limits, country-specific ledger structures and a regulator who cares where the data went. This is what changes when the system on the other end is a real one.
The Model Context Protocol is now the default way to give an AI assistant access to business systems. The ecosystem passed 10,000 public servers during 2025, MCP SDK downloads reached roughly 97 million a month by March 2026, and Stacklok’s 2026 software report put 41% of surveyed software organisations in limited or broad production with MCP servers.
The gap between those numbers and what is actually running inside European finance teams is large, and it is not a gap in enthusiasm. It is that the tutorials describe a different problem. A weather server has one anonymous endpoint, no tenancy, no write path and nothing a data protection officer would ask about. An accounting server has all four.
This guide covers the parts that only appear when you build against the European stack: Exact Online, Yuki, Silverfin, Twikey, AFAS, Visma, Odoo and Teamleader.
If you want the protocol basics first, the introduction to Claude MCP covers them properly.
For the protocol itself, the official MCP specification is the authoritative reference.
What an accounting MCP server actually has to do
An MCP server exposes three things to a model: tools it can call, resources it can read, and prompts it can use. The protocol runs over JSON-RPC 2.0, and the transport is either stdio for a local process or HTTP for a remote one.
That is the whole protocol, and it is genuinely simple. The difficulty is entirely in what sits behind the tools.
For an accounting system, the tool surface has to answer questions an accountant would actually ask. Not “get me record 4471” but “which invoices are more than 60 days overdue across these twelve clients”. That single question crosses pagination, multiple administrations, a date calculation and a status field whose meaning differs by country.
If your tools map one-to-one onto API endpoints, the model has to do that assembly itself, over many round trips, holding partial results in a context window that was never designed to be a scratchpad. It will be slow, it will be expensive, and it will be wrong often enough that nobody trusts it.
Design for the question, not the endpoint. A smaller number of tools that each answer a complete question beats a large number of thin wrappers. This is the single decision that most determines whether the finished server is usable, and it is the one hardest to change later, because every tool description becomes something the model has learned to rely on.
Why the European stack breaks generic build tutorials
Four things differ from the US-centric examples, and each one costs real engineering time.
Tenancy is not a header
Exact Online organises data by division, and a division is close to a company administration. An accountancy firm serving 200 clients is looking at 200 divisions, each with its own scope on the token.
This shapes everything downstream. Your auth flow has to enumerate divisions, your tools need a division parameter, your rate limiting is per division rather than global, and your permission model has to stop one client’s data appearing in an answer about another. Odoo, AFAS and Visma each have their own version of the same shape.
That last point deserves emphasis, because it is the one with consequences beyond a bad answer. A model that can see two clients at once will eventually combine them in a response. For an accountancy firm that is a confidentiality breach, not a bug report. Scope at the token or the query layer, never in the prompt.
Generic tutorials assume one tenant, because a weather API has none.
Rate limits multiply with clients, not with usage
Exact enforces limits on two windows, per minute and per day, applied per division. The ceilings depend on your agreement rather than being one published figure, which is why quoted numbers around the web disagree. Read them from the response headers rather than counting requests yourself.
The trap is that per-division budgets sound generous. For one company they are. For a firm running a nightly extract across every client administration, the daily window is the one that bites, and a single refresh can consume most of an allowance before anyone asks a question.
An MCP server makes this sharply worse than a scheduled pipeline does. A pipeline’s call volume is predictable and you can tune it once. A model exploring a question is not predictable, and it will happily paginate through a large collection because you gave it a tool that allows it to. The first week in production is usually where teams discover their quota maths assumed a human clicking.
Chart of accounts is not portable
A Belgian chart of accounts, a Dutch one and a Norwegian one do not line up. Account 7000 means different things in different countries, VAT treatment differs, and a firm running clients across borders cannot ask one question across all of them without a mapping layer.
This is unglamorous work and it is most of the value. Peliqan’s docs cover the pattern in mapping charts of accounts across countries, and any MCP server serving a multi-country practice needs the equivalent somewhere. Skipping it does not remove the problem, it just moves the reconciliation into the model, where it happens differently each time.
The regulator is a stakeholder
Routing personal data from an EU accounting system through a US-hosted MCP server to a US-based model is a cross-border transfer, and it needs a lawful basis. Only about 8.5% of public MCP servers implement the protocol’s mandatory OAuth 2.1 standard, which tells you how much of the ecosystem was built without any of this in mind.
We deal with this properly further down, because it is an architecture decision rather than a paperwork one.
The three build patterns
There are three honest ways to do this, and the right answer depends on how many systems and how many clients you are serving.
The direct wrapper is the right starting point for a single system, and it is what most tutorials teach. It stops scaling the moment somebody asks a question spanning two systems, because the model has to join them in its context window.
That failure is worth picturing concretely. “Which customers are overdue in the ledger and still have an active mandate” needs invoices from Exact and mandates from Twikey. With two wrapper servers, the model pulls a page of invoices, pulls a page of mandates, matches them on a customer identifier that is formatted differently in each system, and quietly drops the ones it could not match. Nobody sees the drop.
The data warehouse pattern inverts this. Reads hit a database rather than a rate-limited API, joins across systems become ordinary SQL, history is available because you kept it, and the production system is protected from an exploring model. The cost is that data is as fresh as your last sync. For month-end work that is fine. For “did this payment land in the last ten minutes” it is not, which is why writeback and live lookups still matter.
Building it: the parts that take the time
Step 1: authentication and token lifecycle
Every European accounting system worth connecting uses OAuth 2.0 authorization code flow, and MCP’s own auth specification moved to OAuth 2.1 for remote servers.
The flow is standard: register an application, get a client ID and secret, send the user through consent, exchange the code for an access and refresh token. Nothing surprising.
What breaks is the lifecycle, months later. Refresh tokens rotate, and several providers invalidate the old one immediately on use. Two processes refreshing concurrently means one wins and the other is holding a dead token. Store tokens centrally, refresh in one place, and serialise it.
Process B retries with the stale token
Provider returns invalid_grant
Connection drops silently until someone notices at month end
For a multi-client server this is not an edge case, it is the normal operating condition, because the number of concurrent refresh opportunities scales with the number of client connections. Peliqan’s permission layer for AI agents exists partly because per-agent scoping and central token handling turn out to be the same problem viewed from two directions.
Step 2: tool design
Give the model few, well-named, well-described tools. The description is prompt engineering, not documentation, and it is how the model decides what to call.
The difference is easiest to see side by side. A thin wrapper exposes what the API has:
get_customer(division, id)
list_payments(division, page)
Answering “who is overdue and by how much” with those means the model paginates invoices, fetches each customer by ID, pulls payments, and does the arithmetic itself. A tool built for the question exposes what the accountant wants:
divisions: list,
days_overdue: int = 30,
limit: int = 50
) -> rows with customer, amount, days, currency
One call, bounded result, arithmetic done in code where it is testable. Three rules hold up in production.
Bound every result. A tool that can return 40,000 rows will eventually return 40,000 rows. Take a limit, default it low, and state the default in the description.
Make the expensive thing explicit. If a tool crosses divisions, name it so. The model cannot infer cost, so it will call a cross-client aggregation as casually as a single lookup.
Separate read from write. Never let one tool do both. Write tools need different scoping, different logging and different confirmation behaviour.
Step 3: rate limits and pagination
Read the limits from response headers rather than tracking them yourself, because your counter and the provider’s will diverge and theirs is the one that matters. Slow down as remaining approaches zero rather than waiting for the 429, since a 429 costs you both the request and the retry.
Keep interactive traffic and scheduled jobs on separate budgets. If a user exploring data can exhaust the window a nightly sync needs, the sync fails and nobody connects the two events.
Pagination is where models burn quota fastest. Handle it inside the tool and return a bounded result with a clear indication that more exists. Do not expose a next-page cursor and hope the model uses it sparingly, because it will not.
Step 4: writeback and audit
Read-only is where most MCP servers stop, and it is also where most of the value stops. Approving a payment run, posting a journal, updating a mandate: these are the tasks worth automating.
Writeback needs three things a read tool does not. Scope the credentials narrowly, so the write path cannot touch what it does not need. Log every write together with the prompt that caused it, because “the AI did it” is not an audit trail and an auditor will ask. Make destructive operations require an explicit confirmation parameter, so a model cannot trigger one while exploring.
The writeback via MCP post covers the pattern in more depth.
For the implementation detail, see the writeback and reverse ETL documentation.
Step 5: transport and hosting
Local stdio servers are fine for one developer on one machine. They do not work for a team, because every user needs the binary, the credentials and the config file, and updating any of it means updating all of them.
Remote servers over HTTP solve distribution and create an auth problem, which is what OAuth 2.1 in the MCP spec addresses. For a finance team, remote is almost always right, and the hosting location is a compliance decision rather than a preference. Peliqan documents building a remote MCP server if you want the concrete version.
Step 6: testing
Test the tools directly before you test them through a model, because a failing tool and a model choosing the wrong tool look identical from the chat window. Unit tests against recorded API responses catch the first class of problem cheaply.
Then test with the model, on questions phrased the way an accountant phrases them rather than the way you designed the tool. “Show me what is outstanding” and “list overdue receivables” should reach the same tool. The gap between those two phrasings is where most tool descriptions get rewritten, usually twice.
Keep a fixed set of questions and re-run them whenever a tool description changes. Descriptions are prompts, and editing one can change which tool the model picks for an unrelated question. The reference server implementations are a useful sanity check for how the protocol expects tools to be shaped.
Notes on the specific systems
Each of these brings a different constraint to the build. The order below is roughly how often they come up in Benelux practices.
Exact Online
Division-scoped everything, two rate limit windows, and by far the deepest ledger data of the Benelux systems. The Exact Online API guide covers the endpoints and the auth failure modes in detail. Start here if you are serving Dutch or Belgian accountancy clients.
Yuki
Built for hands-off bookkeeping, which means the interesting data is processed rather than raw. Good for month-end status questions, less good for transaction-level forensics. Setup is documented in getting started with Yuki.
Silverfin
A working-papers and reporting layer over the ledger rather than a ledger itself, so it answers “is this file ready” better than “what did we bill”. Belgian accountancy firms usually want it alongside Exact rather than instead of it, as the Silverfin MCP post sets out.
Twikey
Mandates, SEPA direct debits and payment follow-up, mostly Belgian and Dutch. There is no public MCP server for it, so this one is a genuine build rather than an integration. The API is a straightforward REST surface with official clients for Python, Node, Go, PHP and .NET, and the same call shape covers mandates, transactions, invoices and paylinks.
The part worth modelling carefully is the mandate lifecycle, because “why did this collection fail” is the question people actually ask, and the answer spans three separate states: whether the mandate is signed and valid, whether the transaction was submitted in time for the SEPA cycle, and what the bank returned as a reason code. A tool that surfaces only the transaction status answers none of them. Model the join, not the endpoint, and expose reason codes in plain language rather than as raw bank strings.
AFAS
Strong on HR and payroll as well as finance, which makes it the one where data minimisation matters most. Payroll data through an AI assistant is a category of personal data deserving its own scoping decision, separate from whatever you decided for the ledger. See connecting AFAS to Claude.
Visma
Nordic coverage with meaningful differences between country editions, so verify which edition you are against before assuming an endpoint exists. Connection details are in the Visma.net documentation.
Odoo
An ERP rather than an accounting package, so the surface is much larger and the per-client customisation is real. Partners running many client instances hit the multi-tenancy problem hardest, which the Odoo MCP post addresses.
Teamleader
CRM plus invoicing for smaller firms, and usually the system that has to be joined to the accounting one before either answer is useful. Covered in the Teamleader MCP guide.
GDPR and EU residency are architecture, not paperwork
If an EU accounting system holds personal data, and your MCP server routes it to a model hosted outside the EU, you have started a cross-border transfer. That is true whether or not anyone has written it down.
Three architectural choices decide your posture, and none of them can be retrofitted with a policy document.
Where the server runs. An EU-hosted MCP server keeps the data plane inside the EU up to the model call. Peliqan is EU-hosted, SOC 2 Type II certified and ISO 27001 certified, which is the baseline a regulated client will ask about.
What reaches the model. Minimise before the call, not after. If the question is about ageing balances, the model does not need names and bank details in the payload. Field-level minimisation at the tool boundary is the cheapest control you will implement, and the easiest to demonstrate to an auditor, because it is visible in the tool definition.
Where the model runs. Claude via AWS Bedrock EU regions or Google Cloud Vertex AI EU regions are the two documented routes to EU inference, and both need explicit region configuration. The default consumer endpoints are US-hosted, so this is something you turn on rather than something you inherit.
The GDPR-compliant MCP servers post works through the Article 28 and Schrems II detail properly.
Beyond GDPR, the EU AI Act obligations arrive on a separate timetable and apply to how the assistant is used, not only to where the data sits.
Build or connect
Building your own is right when you have one or two systems, a single tenant, a specific workflow and an engineer who will still be there in a year to rotate the credentials.
It stops being right at the point where you are maintaining OAuth flows for eight providers, per-division rate limiting, a chart of accounts mapping, an audit log and a permission model, none of which is the product you sell. Each of those is a few days to build and an indefinite commitment to maintain, and they fail quietly rather than loudly.
Real-world example: OdooExperts
An Odoo partner running reporting across many separate client environments, where the multi-tenancy problem described above is the whole job rather than an edge case. Read the full case study.
Where Peliqan fits
Peliqan is a data platform with an MCP server on top, rather than an MCP server with a database behind it, and that ordering is the point.
Data from 300+ connectors syncs into a built-in data warehouse running Postgres and Trino. The MCP server queries that, so a question spanning Exact Online, Teamleader and Twikey is one SQL join rather than three live APIs and a model doing arithmetic in its context window. Federated queries handle the sources that should stay live rather than synced.
Writeback goes the other way, back into the source system, with per-agent permissions deciding what any given assistant can touch. Custom connectors carry a 48 hour SLA, which matters for the long tail of European tools nobody else supports.
Installation is pip install mcp-server-peliqan, and the MCP server documentation covers configuration. Connector-specific MCP repos for Exact Online, Teamleader, AFAS, Odoo and PowerOffice are open source on GitHub if you would rather start from working code than a blank file.
The takeaway
The protocol is the easy part. Any competent engineer can stand up an MCP server in an afternoon, and the tutorials are accurate as far as they go.
What takes the time is per-tenant OAuth that survives a year, rate limits that multiply by client count, a chart of accounts that does not line up across borders, an audit trail that holds up when someone asks who approved the journal, and a data path a DPO will sign off. Those are the same five problems whichever European accounting system you point at, and none of them is visible in a weather API tutorial.
Decide early whether solving them is your product. If it is not, connect rather than build.



