Your MCP server is secure. The registry behind it is not. – Unite.AI
In a recent article here on Unite.AI, Gil Feig explained six best practices for creating a secure MCP server. They are valid and anyone shipping an MCP server should follow them. His advice to give each integration “its own detailed role, strictly limited to the required permissions” is exactly right. It is also assumed that the system on the other side has fine-grained roles. This points to a broader assumption that is rarely stated: that the systems behind the server can be protected to the same standard.
In enterprise software, this is often not possible. I manage the engineering team behind an integration layer that connects to 32 accounting and ERP systems, with an optional MCP server on top. We regularly see well-authenticated, well-identified, well-recorded agents on our side writing into systems that have no way of knowing an agent was involved.
This piece is about the second half of the problem: what upstream systems actually offer, what you can control from the integration layer, and where that control ends.
Where the MCP specifications go
THE MCP authorization specification has its own boundaries very clear. The MCP server is an OAuth resource server for its clients. When it calls an upstream API, it acts as a separate OAuth client, with a separate token issued by the upstream system. Passing the client token is explicitly prohibited.
This is the right design. It also means that everything about the upstream call, including who is authorized to do what and how it is recorded, depends entirely on the upstream system. The specification cannot correct what the upstream system does not offer.
The same goes for the OWASP Guide on Excessive Agency. It is recommended to limit the permissions held by an agent’s extensions in other systems to the minimum necessary and to perform actions in the context of the user for whom they act. Both are good advice. Both assume that the other system has some way to express minimum permissions and user context.
What the upstream systems actually offer
Here’s what the 32 accounting and ERP systems we connect to look like from an integrator’s seat.
A third have no OAuth at all
21 out of 32 use OAuth. The other 11 are based on static credentials: API keys, username and password, or a pair of tokens. Some of these keys never expire. One widely used system documents its API tokens as having an unlimited lifetime for as long as the user exists.
Long life, little revocation
OAuth helps less than you hope. A provider issues refresh tokens with a duration of approximately 20 years. This is a credential designed to outlive the agent who uses it, the framework on which it was built, and quite possibly the person who clicked “allow.” In another system, access tokens also do not expire.
And once a credential is used up, the question is who can deactivate it. The standard for this, OAuth Token Revocation (RFC 7009)it has been around since 2013. Yet about four in ten systems provide no technical way for an integrator to revoke credentials. Every API key system falls into that group. The only remaining control is to ask the customer to manually delete access.
Rough scopes, no agent identity
Most static keys simply inherit all the rights of the user who created them; only a few systems allow you to limit a key to individual endpoints. Many OAuth systems have scopes, but they tend to be coarse-grained, along the lines of “accounting, reading, and writing”. And in none of the 32 systems could we find a way to register, through the API, both the agent and the person he acts for on the same transaction. External agents appear as the user who connected them or as a generic system user. It is significant that the case where a supplier has integrated agents into their product, such as Microsoft has in Business Centralprovided them with dedicated user accounts. This is the same model I recommend below, reserved for seller’s agents only.
What the integration level can apply
None of this means giving up. Between the agent and the accounting system, you control almost everything:
- credentials for agent towards your level
- your scopes, such as read-only access to invoices
- an audit log of each agent call, with the human they acted for
- idempotence keys, so that a retrying agent does not post the same invoice twice
- rate limits per agent
- approval steps before any writing
None of this depends on what the target system supports. Today, an effective access layer to the integration layer is possible, and if you put agents close to financial data, you should create one.
Where it stops
What you can’t do is extend that layer beyond the system boundary. Three things break there.
Attribution
Within the accounting system, the agent’s writing appears as the person who authorized the connection, or as the technical user. Whoever controls that system sees a message from that user. They can’t tell if a person or agent made it. In the ledger, an agent accounting for 400 invoices at 3 am looks exactly like a very diligent financial manager. Reconstruction requires the integrator logs, which represent a different chain of trust than the logging system. For forensics or an audit, this is a weak position.
Even most organizations are not at the forefront of this. In the Cloud Security Alliance surveyonly 28% of respondents said they can reliably track agent actions to a human or system across all environments, and 44% use or plan to use static API keys for their agents.
The least privilege
You can mandate that an agent only reads invoices. But if the target system has no scopes, the credentials behind your layer still maintain full access. Anyone who gets them completely ignores your level and any rules you’ve written with it.
Revocation
You can exclude your agent immediately. This doesn’t help if the credentials of the target system itself are compromised. And for the four out of ten systems without revocation endpoints, the kill switch is an email to the customer.
The pragmatic answer: a dedicated user agent
The most useful thing you can do today is unglamorous. Create a dedicated user for the agent on the target system and connect the agent only through that user.
It works on every system that lets you create users, and it buys three things that the integration layer can’t:
- Attribution in the registration system. Messages appear as “AP Agent,” not as the finance manager who clicked “Connect” six months ago.
- A revocation path, even without a related API. The customer can disable the user in the interface, which works on systems that do not offer revocation endpoints.
- Partial minimum privilege. Where the system has no role model, the agent user can often be limited to the modules they actually need.
The costs are real. Someone has to manually create the user during onboarding, which adds friction at exactly the wrong time. About half of the systems charge for each additional user, from a few euros per month in small business tools to more than a hundred in a full ERP. Many others limit users by plan, so one more user can mean a more expensive plan for the entire company. And a user of the service that no one owns becomes at their own risk, part of the expansion of non-human identity Unite.AI has already addressed this issue. It needs an owner and a review date like any other account.
It also does not fix scopes on systems that do not have them. But it brings attribution and revocation back into the system where reviewers actually look.
The structural response: delegated identity
The correct answer already exists on paper. OAuth 2.0 Token Exchange (RFC 8693) distinguishes representation from delegation. With delegation, the agent maintains its identity and the token records that it acts on behalf of a person, through the “act” attestation.
Applied to accounting, this would mean:
- the log records that this agent recorded on behalf of this person
- Scopes are granted by delegation, not by user
- you can revoke a single delegation without touching your account
As far as I could find, none of the 32 systems support anything like this. So for now it remains a direction, not an option. This makes it a request to accounting and ERP software vendors rather than a task for integrators: agents are already writing to your logs, and your APIs should be able to tell.
What to do before an officer touches a register
If you are connecting agents to accounting or ERP systems, a short checklist:
- Map the credential model of each target system. Is it OAuth or a static key, how long does the credential last, does it have scopes and can you revoke it?
- Build your access level anyway. Per-agent identity, scopes, idempotency, and approvals belong to your side, whatever the target offers.
- Use a dedicated user agent wherever the system allows. Accept the onboarding effort and license cost as the attribution price.
- Keep your audit trail tamper-proof. For many systems this will be the only record of an agent’s engagement.
- Note the residual risk. Where a system has no purpose and no revocation, tell your client and your risk register.
The border is the point
You need to secure the MCP server. It’s not enough. The safety of an agent writing to a log is decided at the boundary between your level and the system of record, and today that boundary is set by the systems, not by you.
The good news is that the gap is well defined. Standards exist. What is missing is their support from the systems that keep the books.



Post Comment