Every question about an order or a failed import meant logging in and clicking through tables. An AI assistant had no safe way in.
- Client
- A commerce agency running an integration platform for online merchants
- Users
- Merchants with one or more connected stores, and the agency's own operators
- Engagement
- An MCP server inside the platform, with token auth, company scoping and rate limiting
The outcome in four lines
| Measure | Before | After | Evidence |
|---|---|---|---|
| What an AI client can reach1 | nothing, the data sat behind web screens | 24 typed tools in seven areas: 20 released, 4 finished on a branch | Measured |
| Requests sent without a valid token2 | never rate limited, the 61st in a minute was still let through to the token check | on the finished branch, counted from the first, and the 61st in a minute is refused | Measured |
| Asking for another company's store by its id3 | the first tools accepted any store id | refused, and lists show only the caller's own stores | Described |
| What a customer lookup returns4 | a list of fields to hide, which missed notes and the sign-up IP address | 12 named fields, with addresses dropped | Measured |
Three lines carry a counted figure and one describes a change with no number. The small number beside each line says how it is known.
The problem, in the client's terms
Our client runs an integration platform for online merchants. It syncs products, customers and orders from each merchant's stores into its own database, and runs scheduled jobs that import orders, inventory and fulfilments and export orders to back-office systems.
All of that data sat behind web screens. To answer "how many orders failed to export this week?" or "why did last night's inventory import fail?", a person logged in and clicked through tables. An AI assistant could not answer either question, because it had no safe way in.
The questions are routine, and they arrive at the moments a person is least free to click through tables, such as a failed overnight run with a merchant waiting for an answer.
The client wanted language models to read dashboard metrics and operational data, help troubleshoot integrations and trigger integration runs, with secure sign-in and permissions. The Model Context Protocol (MCP) is the open standard for giving an AI client a set of tools, so the job was an MCP server on top of the platform.
- ConstraintThe platform holds many companies' stores in one database. A valid token must never read another company's store.
- ConstraintWhatever a tool returns can end up in a model's context and a chat log, so no credential or personal detail may leave in an answer.
- ConstraintThe platform, its database and its sync jobs were to stay as they are, with the server as an extra door.
- ConstraintActions that change data stay off unless an operator switches them on.
The architecture, before and after
Switch between the two. The platform and its data did not move. A checked, typed door for AI clients was added in front of it.
- What hurt in this state
- Built in this engagement
Three decisions, and the options they rule out
Wiring a tool to a database is the easy part. These choices decide whose data a token can see and what can never leave in an answer. Each one names what it replaced and what it cost.
Where the server lives
Turned down
A separate service that calls each store's API
Our one-day prototype worked this way, with one store's credentials. Serving every merchant would mean holding every store's credentials and rebuilding the platform's companies, users and permissions outside it.
Chosen
A package installed inside the platform's own application
The server reuses the platform's data models, its sign-in and its idea of which company owns which store, so scoping follows the same rules as the platform's own screens.
What it cost: The server is tied to the platform's framework and release cycle, so every change to it ships with a platform release.
Where answers are read from
Turned down
A live call to the store's API on every request
Our first version did this, and every tool call spent the store's API rate limit on data the platform had already synced.
Chosen
The platform's synced database, with live calls only for price lists
Orders, products, customers and integration runs are already in the database, so tools read them there. Customer price lists are not synced, so they alone go to the store's API.
What it cost: An answer is only as fresh as the last sync, and the price list tools still depend on the store's API being up and inside its limits.
How personal data is kept out of answers
Turned down
A list of fields to hide
We started with one on customer records and it missed fields such as notes and the sign-up IP address. A list of what to hide fails open whenever the data gains a field.
Chosen
An allowlist where the shape is known, deep redaction where it is not
A customer lookup returns only 12 named fields. Webhook payloads vary by platform and topic, so 30 known personal or secret keys are replaced at any depth. Database errors become a generic message, so query text never reaches the model.
What it cost: A useful new field never appears until someone adds it to the allowlist, and the redaction list has to grow when a new kind of payload carries a new key.
How it was delivered
Our software engineers built the package, its tools and its tests. The client's team runs the platform.
Prototype, then into the platform
A one-day prototype as a separate service, then a package inside the platform's application with its first two tools.
Reading the synced data
Tools moved from live store API calls to the platform's own database, and the server moved to a different MCP library, with one class per tool. A consuming app can subclass the server and replace tools.
Tokens from the command line
An install command and a token command to create, list and revoke tokens, with no shell call from inside the installer.
Company scoping and the first release
Every tool scoped to the caller's company before the tool set widened, then 20 read-only tools released.
Write tools, the throttle fix and the test suite
The two guarded write tools, health and queue tools, the rate limit moved ahead of the token check, and 46 tests with 246 assertions, all passing on the finished version.
Who did the work
- Atyantik software engineersThe package, all 24 tools, token commands, scoping, redaction, the throttle fix and the tests
- Client's teamThe platform itself and its day-to-day running
Who owns what now
The 20 read-only tools are released. The write tools, the throttle fix and the tests are finished on a branch, to be released with a rate limit store shared across all server instances. Per-token permissions, so a token can be held to read-only tools, would come next.
Results
What an AI client can reach on the platform, before and after.
- Agency operators can ask a desktop AI client why an integration run failed or which orders did not export, without clicking through run tables.
- Merchants and their automations can connect a remote AI agent with a token that sees only their own company's stores.
- Anyone approving a change decides first: in the finished version both write tools are off until switched on, and are marked so a client can ask a person before calling them.
No figure is given for how many AI clients or tokens use the server, how many calls it answers, or how much lookup time it saves.
none
Before
20 tools
First release, read-only
24 tools
Finished version, two write tools off by default
Stores, products and pricing, customers, orders, dashboard and health, integrations and webhooks, all readable by an AI client through one checked door.
| Option | Tools the server exposes over MCP. Before, an AI client had no way to reach the platform's data at all. |
|---|---|
| Before | none |
| First release, read-only | 20 tools |
| Finished version, two write tools off by default | 24 tools |
Source: Source note 1
What answering by hand costs you today
We do not publish what an engagement costs. So this works from your side: what your team spends looking up operational data by hand, the work an AI client can take a question from.
Cost of looking data up by hand, per year
$15,167
- Hours spent looking data up, per year
- 433 h
What went wrong, and what we would do first
The rate limit never counted failed sign-ins
The endpoint listed the rate limit before the token check, but the framework sorts its middleware by a fixed priority that puts authentication first. A request without a token was refused before the rate limit saw it, so token-guessing traffic was never slowed. We moved the limit into its own class registered ahead of authentication, keyed it by a hash of the token, and fixed a cold-start fault found on the way. A test now sends 60 requests with no token and expects the 61st to be refused for rate. Next time we would write that test against the real route on the first day, for every check that sits in front of a public endpoint.
A list of fields to hide leaked fields
Customer records carry the store's raw payload, and our first filter named fields to remove. It missed notes and the sign-up IP address. We replaced it with an allowlist of 12 fields and kept deep redaction for webhooks, whose shape varies. Next time we would start from an allowlist for any data whose shape is known, before the first tool ships.
Will an MCP server work for your platform?
It fits when
- Your platform holds several companies' data in one database, and your application already knows which company owns what.
- Your team or your customers keep asking the same operational questions about orders, jobs or failed runs.
- You want AI assistants or automation agents to read that data, and some actions to stay behind a person's decision.
Look elsewhere when
- One fixed report answers the question. A scheduled report or a dashboard is cheaper than a tool layer.
- Your application has no clear owner for each record. Fix that model first, because the server can only scope what the platform can already scope.
- The data cannot leave your network for any AI provider. A local client run by your own operators is the only safe transport, and remote access should wait.
Check it yourself this week
If most of last week's lookups were routine reads of data you already hold, an AI client could take them. Put your numbers into the calculator above.
- List the questions your team answered last week by logging in to look something up.
- For each one, note which company's data it touched.
- Mark the ones that read data and the ones that changed something.
How it is built, by layer
- ProtocolThe Model Context Protocol, over a local process and over HTTP, with each tool marked read-only or destructive
- ServerA package installed inside the platform's own web application
- Sign-inBearer tokens created and revoked from the command line
- DataThe platform's synced database through its own data models; the store's API for price lists only
- Async workQueued jobs that record who asked for each run
- Rate limitingA per-token limit that runs ahead of the token check
- TestingUnit and HTTP tests on an in-memory copy of the platform's real schema
- AI clientsA desktop AI client and a workflow automation agent
How each figure was measured
- Typed tools the server exposes over MCP, counted in the first released version and in the finished version.
- An automated test that sends 61 requests without a token inside one minute, run against the endpoint before and after the fix.
- Automated tests that ask for another company's store by its id, and check that store lists hold only the caller's stores.
- Fields a customer lookup can return, counted in the tool's allowlist, and the fields the earlier filter let through, and the personal or secret keys the webhook filter replaces.
- Automated tests and assertions in the suite, run on the finished version, all passing.
Tell us what your team keeps looking up by hand, and we will tell you if an MCP server should answer it.
Send the questions your team answered last week and how your data is split between companies. A software engineer reads it and replies with an honest answer, including when a report would do.