There are two ways to let an agent act in your systems. Run an MCP server per integration yourself, or point the agent at a gateway that has already done it.
We build one of these, so read accordingly. What follows is still the version we would give a friend, including the cases where the answer is not us.
The trap is that the first one is easy
Self-hosting a single integration is genuinely pleasant. npx a package, put a
token in an environment variable, point your editor at it. Twenty minutes. If you
need one MCP server for one API, do exactly that and skip the rest of this post.
The problem is that nobody stops at one, and none of the work is reusable.
An OAuth application per vendor. Not a token — an application. Register it, configure redirect URIs, submit it for review if the scopes are sensitive, and do that separately for Google, Slack, Notion, HubSpot and everything else. This is the work people consistently underestimate, because the first one takes an hour and feels fine.
Token refresh, forever. Access tokens expire. Refresh tokens rotate, and some vendors invalidate the old one the moment you use the new one — so a crash between the two loses the connection. This is a small piece of code you will write several times and get slightly wrong at least once.
Somewhere to keep secrets. Not environment variables on a laptop, once more than one person is involved. A real secret store, with real access control.
Multi-account routing. Two Slack workspaces means two credentials and a naming scheme so an agent can address one rather than the other. Irritating to retrofit, easy to design badly.
An audit trail. Which agent called what, with which arguments, as whom, and what came back. Nobody builds this on day one and everybody wants it the first time something surprising happens.
Permission enforcement. A prompt saying "never delete anything" is not enforcement. Building real enforcement means a place every call passes through — which is a gateway, just one you now maintain.
Each is a small piece of work. The problem is that it is the same small piece of work per integration, it never finishes, and it is not the work you wanted to be doing.
What a gateway does instead
All of the above, once, for every app in the catalogue.
You connect an app through its own consent screen and the authorisation stops being your problem: it goes into an encrypted vault, gets refreshed before it expires, and is addressed by name rather than by token. Connect the same app twice and each connection keeps its own credential, addressed apart by a suffix.
Permissions become three rows per app — read, write, destructive, each allowed or blocked — checked at the gateway on every call, before anything reaches the vendor. Blocked tools are not even offered to the agent. That is enforcement you would otherwise have built yourself, and it is the piece most self-hosted setups never get to.
And every call lands in an activity log with the tool, the arguments, the outcome, the duration, which connection it used and who it acted as. Not because someone remembered to add logging, but because the calls all go through one place.
The honest concessions
Four of them, and they are real.
A vendor is in the path. If the gateway is down, your agents are down. Your own process has a smaller blast radius — one integration fails, not all of them.
You do not control the process. You cannot patch it, profile it or pin a version. When behaviour changes you find out by observing it.
Data transits a third party. Arguments and results pass through someone else's servers. For some organisations that is a compliance conversation before it is a technical one, and it is a legitimate reason to self-host.
The integration surface is ours, not yours. If we do not carry the app you need, you wait or you build alongside.
If any of those is disqualifying, self-host. That is the right call and no comparison table changes it.
Side by side
| Self-hosted MCP servers | Managed gateway | |
|---|---|---|
| First integration | An afternoon | Minutes |
| Tenth integration | Ten times the maintenance | The same as the first |
| OAuth applications | One per vendor, registered by you | Already registered, or bring your own |
| Token refresh | Yours to write and operate | Handled |
| Secret storage | Yours to choose and secure | Encrypted vault |
| Multi-account | Design it yourself | Addressed by suffix |
| Audit trail | Build it | Every call logged |
| Permissions | Build it, or trust the prompt | Enforced before the call |
| Failure blast radius | One integration | Everything at once |
| Data path | Your infrastructure only | Through a third party |
| Version control | Total | None |
The decision rule
Self-host when the integration is the product, when you need one or two of them, or when data residency rules the alternative out. Those are real cases and they are not rare.
Use a gateway for everything else — which, for most teams, is everything. Integrations are almost never the product. They are the tax you pay to get to the product, and it is a tax that recurs per vendor, per quarter, forever. The moment you have more than a handful, or more than one person who needs them under different permissions, the arithmetic stops being close.
The question worth asking is not "can we build this?" — you can, none of it is hard. It is "is maintaining six OAuth applications the thing we should be doing this quarter?" For most teams the honest answer is no, and it stays no.
The middle path nobody mentions
These are not exclusive. An MCP client can talk to several servers at once.
The arrangement that tends to work: a gateway for the long tail — the twenty apps your team touches where the integration is not interesting and you just want it to exist — and a hand-written server for the one system that is genuinely yours, where you want control of the process and the shape of the tools.
You get leverage where integration is commodity, and control where it is not. That is not a compromise; for most teams it is the correct architecture.
Try it against something real
The fastest way to settle this is not to read another comparison. Connect one app you would otherwise have written a server for, set its rules, and give an agent a task you actually care about. It takes about five minutes, and by the end of it you will know which side of this you are on.