The wrong question is “Can we expose this through MCP?”
The better question is, how do you decide which internal systems should be exposed through an MCP server versus kept behind a narrower custom action layer? That choice decides whether your agents become genuinely useful, or just another way to create expensive mistakes at speed.
I’ve seen teams get this backwards. They start with the most impressive system, the one with the richest API or the biggest business impact, and expose it first. A few weeks later, the agent is making changes no human would have made, and everyone is suddenly talking about “guardrails” as if the problem was only permissions.
It usually isn’t.
MCP is for breadth, custom actions are for control
An MCP server makes sense when the underlying system can tolerate exploration, partial context, and a broader set of agent behaviours. A custom action layer makes sense when you already know the exact business moves you want the agent to make, and you want to constrain everything else.
That’s the real split.
If you’re still asking how do you decide which internal systems should be exposed through an MCP server versus kept behind a narrower custom action layer?, start with the shape of the work, not the shape of the API. Human operators can cope with ambiguity because they can stop, ask, and recover. Agents will happily continue until they hit a hard failure, or worse, a soft one that looks successful.
A good rule: expose systems that are mostly about finding, checking, comparing, and assembling. Keep systems that move money, change stock, alter customer records, or trigger downstream workflows behind narrower actions with explicit intent.
The first system people regret exposing is usually the order or fulfilment system
The first regret I see is not some exotic AI scenario. It’s the internal ordering or fulfilment system, especially in wholesale businesses where staff have spent years working around quirks in the ERP.
Why that one? Because it looks read-heavy on the surface, but it usually has hidden side effects. A “view order” call might update last-accessed timestamps. A “check availability” call might reserve stock. A “create draft” path might kick off validation jobs, notifications, or pricing recalculations. The agent doesn’t know the difference unless you make it painfully obvious.
In Australia, I’ve seen this most often around ERP-connected ordering flows where teams are trying to reduce manual order processing without rebuilding the whole stack. The temptation is to point the agent straight at the ERP and call it progress. It isn’t. It’s just a wider blast radius.
The practical test for messy side effects
When an MCP server seems attractive but the underlying system has messy side effects, I use a blunt test:
- Can this action be run repeatedly without changing state in a way the user would care about?
- Can I explain every side effect in one sentence?
- Can I undo it, or at least detect and reconcile it cleanly?
If the answer to any of those is no, it probably does not belong directly behind MCP.
That third question matters most. A lot of enterprise systems were designed for humans in a browser or a back office screen, not for agents firing structured calls at machine speed. If the system writes audit notes, recalculates pricing, sends emails, updates dashboards, and emits webhooks all from one action, you do not have a clean tool. You have a chain reaction with a UI.
This is where a custom action layer earns its keep. It lets you define a smaller contract, one that does one business thing well, with the side effects you actually intend.
Key takeaway: Expose the system, not the mess. If the agent can’t predict the side effects, the integration is too loose.
What breaks first in production
The first thing to break is usually not security. It’s operator assumptions.
Systems built for humans assume pauses, judgement, and correction. Agents do not pause unless you force them to. So the first failures are often:
- duplicate submissions because the agent retries after a timeout,
- stale reads because the agent cached the wrong thing,
- approval loops because the system expected a human to notice context,
- and silent partial failures where the API returns success but the business process did not complete.
That last one is the nasty one. A human sees an odd screen and stops. An agent sees a 200 response and moves on.
The second thing to break is your support burden. Once an MCP-exposed system is in production, people start using it in ways you never planned. Not maliciously. Just efficiently. If the system can answer a question, they’ll ask broader questions. If it can make a change, they’ll ask it to make five.
That is why how do you decide which internal systems should be exposed through an MCP server versus kept behind a narrower custom action layer? is really a governance question, not a tooling question.
Read-only through MCP, writes through custom actions
The cleanest split is often read-only through MCP, writes through custom actions.
That works when:
- the read path is stable,
- the write path has business rules you can name,
- and the write path needs tighter validation, approvals, or idempotency controls.
For example, an agent can safely inspect customer order history, stock status, open invoices, or analytics through MCP if those views are genuinely read-only and do not mutate anything behind the scenes. But when it comes time to create an order, change a customer’s credit terms, or reprice a wholesale account, I would usually keep that behind a narrower action.
Where does the split fail? When the read path is not really read-only, or when the write path is so simple that the extra layer just adds lag and duplication. I’ve seen teams overcomplicate tiny, low-risk updates by hiding them behind a custom action layer that mirrors the original API one-for-one. That gives you all the maintenance cost and none of the safety benefit.
The right split is not philosophical. It is operational.
A simple decision matrix that actually helps
If you are trying to decide how do you decide which internal systems should be exposed through an MCP server versus kept behind a narrower custom action layer?, use this:
| System trait | MCP server | Custom action layer | |---|---:|---:| | Mostly read-only | Yes | Sometimes | | Hidden side effects | No | Yes | | Needs business-rule validation | Sometimes | Yes | | Multiple agent clients will use it | Yes, if stable | Yes, if tightly scoped | | Human operators already use messy UI workflows | Usually no | Usually yes | | Changes often | Only with strong versioning | Better for fast-moving workflows |
If a system sits in the left column, MCP is usually fine. If it sits in the right column, build the smaller contract first.
The important part is not the label. It is whether the contract matches the business risk.
Versioning is different once multiple agent clients are in play
This is where teams get caught out.
With MCP-exposed systems, you are often supporting multiple agent clients at once, maybe an internal assistant, a workflow agent, and a customer-facing copilot. That means version drift becomes a real problem. One client will be upgraded. Another will not. Someone will pin to an older schema. Someone else will assume the tool still behaves the way it did last month.
For MCP, I treat the exposed surface like a public contract, even if it is only used internally. Version it deliberately. Keep names stable. Add new capabilities without changing old meanings. Deprecate slowly, and log usage before you remove anything.
Custom action endpoints can move faster, but only if they are genuinely narrower. Because the scope is smaller, you can change the implementation more often without breaking every client. Still, do not confuse narrow with disposable. If an agent workflow depends on it, that action now has a contract, whether you wrote one down or not.
The rule I use is simple: broad exposure means slow change, narrow action means controlled change. If you cannot support that discipline, do not publish the tool yet.
The systems I would not expose directly
There are a few internal systems I would almost never expose directly through MCP unless they had already been wrapped in a safer façade:
- ERP posting or journal entry functions
- stock allocation and fulfilment release
- customer credit or pricing overrides
- payment capture and refund logic
- anything that fires external notifications as a side effect
These are not “bad” systems. They are just systems with too much business consequence to hand to a broad agent interface.
If you need the agent to work with them, create a custom action layer that expresses the actual business intent. “Approve order release,” not “call ERP endpoint 17.” “Issue refund to original payment method,” not “update transaction state.”
That distinction matters more than people think. It is the difference between an agent that behaves like a competent assistant and one that behaves like a very fast intern with admin access.
Where the architecture usually lands
In real production work, the answer is rarely “all MCP” or “all custom actions”. It is usually both.
Use MCP for discovery, context, and read-heavy workflows across stable systems. Use custom action layers for the few business operations that actually move the needle and carry risk. That gives you a system access strategy that is useful to agents without turning your backend into an open-ended experiment.
For businesses in Australia building around ERP, ordering, or analytics, that split is often the difference between a pilot that impresses people and a production system people trust. The production version needs auditability, permissions, and a clear contract. If your integration layer cannot show who did what, when, and through which action, you are not ready to let agents touch core workflows.
The decision you should make this week
Map the top ten internal actions you want agents to use. For each one, write down:
- whether it changes state,
- whether it has hidden side effects,
- whether it can be retried safely,
- and whether you would be comfortable explaining the outcome to a customer or auditor.
If an action fails any of those checks, keep it behind a custom action layer. If it passes, consider MCP exposure, but version it as though three different clients will depend on it next quarter, because they probably will.
If you want help deciding how do you decide which internal systems should be exposed through an MCP server versus kept behind a narrower custom action layer?, that is exactly the kind of architecture call I make in Embedded IT Leadership and MCP & Agent Tooling. The faster path is to have someone design the boundary properly and build it once, rather than discover the edge cases after an agent has already found them.




