Skip to content

Running your own MCP servers, or not

Running your own MCP servers is cheap for one team and expensive for a company. The line is not the servers, it is credentials, revocation and the audit trail.

Roopendra Talekar 5 min read
A single endpoint on the left, a grid of separate servers on the right, with credential paths drawn between them

What running your own MCP servers actually buys you

An Model Context Protocol server you run is a process you control. You choose the version, you see the logs, you can read the code, and nothing about your data leaves a boundary you did not draw. For a team that is already comfortable operating services, none of that is hard, and the first server is genuinely quick.

It also fits a real situation. One team, three or four systems, a shared service account per system, and one person who knows how it is wired. That team does not have an access-control problem, because everyone on it is allowed to reach everything the servers reach. The server is doing the only job it needs to do, which is speaking the protocol.

The reason to look further is not that this setup is bad. It is that two of its assumptions stop holding at a predictable point, and neither of them is about servers.

The credential math changes with the second team

A self-hosted server needs a credential for the system behind it. With a shared service account, that is one credential per system, and the agent acts as that account for everybody.

That is workable until someone asks a question the shared account cannot answer: should this person be able to reach this record. A shared account has one answer for the whole company, so the moment two groups need different answers, the credential has to become per person. Now the count is people multiplied by systems, and every one of those is a secret that has to be issued, stored, rotated and eventually removed.

In Elaichi, connector credentials are not held by the control plane at all. A separate credential service owns per-account secrets, encrypted at rest with AES-256-GCM, and owns refresh as well. A refresh that fails marks the connection needs_reauth instead of failing quietly, which matters because a quiet credential failure looks exactly like an agent deciding not to do something.

Single sign-on in front of that endpoint is a separate decision, and it settles identity rather than authorization.

There is one address for clients: POST /mcp, standard MCP over Streamable HTTP, behind OAuth. There are no per-toolbox URLs and no embedded tokens, so there is no per-user server to mint, list or revoke. The endpoint is constant and the grant is what varies.

Revocation is the part that decides it

Ask how long it takes to cut somebody off. The answer separates the two approaches more cleanly than any feature list.

With servers holding per-person credentials, revocation is a sweep. You need the list of every credential that person holds, across every server, and you need it to be complete. Nothing produces that list for you, and an incomplete sweep leaves a working credential behind with no signal that it is still there.

Through a control plane the timings are specific, and worth stating precisely because they are not all the same. Removing or suspending a member revokes every live grant in the same transaction as the membership change, and the OAuth grant is re-read from the org store on every single call with no cache, so for those the next call is genuinely the boundary. Role membership and restrictions are different: they resolve through a 60-second cache plus edge propagation, so a change to what a role may reach takes effect within about two minutes, on every surface alike.

Two minutes is not instant, and saying so is the point. A number you can plan around beats a promise you cannot verify.

Offboarding has a step people forget

Removing a person is not only a credential problem. It is also a question of what happens to the connections they set up.

Elaichi refuses the removal if a personal connection that person owns is still referenced by a toolbox entry, until that connection is resolved: transferred to the org, to a team, or to another member, or deleted. Unreferenced personal connections are cleaned up. A private connection is not transferable at all, because a credential that only its owner could ever use does not become somebody else's when its owner leaves.

That preflight is the kind of thing that does not exist until someone builds it, and its absence is invisible until the week after a departure, when a scheduled job stops working and nobody can say why.

What the audit trail has to answer

The question that arrives after an unexpected change is narrow: which account did the agent write to. Not which server, and not which user was logged in. Which of the two Notion workspaces.

Elaichi writes one entry per tool-call attempt, succeeded or failed, and both name the account. The recorded connection is the one actually reached, taken from the execution rather than from the intent, which is the distinction that makes the record usable. Recorded alongside it: the operation and tool, the classification, whether it was approved, the outcome, and an error code. Argument names and counts are logged. Argument values never are.

actor_kind is a field rather than an inference, and ai_assistant is one of its values. Whether an action was taken by an AI is written at the point of action, not guessed later from a user agent string. Self-hosted servers can produce logs, and often good ones, but they produce them per server in whatever shape each one emits, and correlating those by eye is the work you are actually signing up for.

When running your own is the right call

There are cases where the honest answer is that you do not need a control plane.

If one team uses two systems, shares a service account for each, and nobody outside that team will ever connect, a self-hosted server is less machinery for the same result. If a system has no per-user concept at all, adding per-user governance in front of it buys nothing. If your constraint is that a particular workload cannot leave hardware you own, that constraint outranks convenience and should win.

The mixed shape is also legitimate. Route the systems that need per-person rules and a defensible trail through the governed endpoint, and leave a single-account internal tool where it is. That is a smaller change than a migration and it puts the effort where the risk is.

The trade-off, stated plainly

A control plane centralizes. That is the benefit and the cost in the same sentence. One endpoint means one place to reason about access, and it also means one dependency in the path between a client and the systems it reaches.

What you get for that is a single answer to who may reach what, a revocation story with numbers attached, and one record shape that answers what happened without correlating two systems by hand. What you give up is the ability to read every line of the process in the path.

One more limit worth naming, because it is easy to assume otherwise: an MCP server never sees a user prompt, so no endpoint of this kind can be protected against prompt injection, and Elaichi's is not. What does hold on the endpoint is role-based access per operation, the forbidden classification, output redaction, OAuth scope limits and full audit logging. That is a real set of controls, and it is not the same thing as making a model trustworthy.

If you are weighing the two, the useful question is not which is more secure in the abstract. It is whether you can currently produce, in under a minute, the list of every system one departing person's agent could reach. If you can, stay where you are. If you cannot, that is the gap, and more servers will not close it.

For the shape of a first rollout, see a team-by-team playbook. Browse what connects today or read how the access model is layered.

FAQ

Frequently asked questions

Is it cheaper to run our own MCP servers?

For one team and a few systems, usually yes. The cost of self-hosting is not the compute, it is the per-person work of issuing credentials, removing them when somebody leaves, and answering questions about what an agent did. That work scales with people and systems multiplied together, while the server count scales only with systems.

Can I keep some systems self-hosted and route the rest through a control plane?

Yes, and it is a common shape. The systems that need per-person access rules and an audit trail go through the governed endpoint. A system with one service account and no per-user distinction can stay where it is. Splitting on that line is more honest than moving everything at once.

What breaks first when a self-hosted setup grows?

Offboarding. Credentials issued per person across several servers have no single list, so removing somebody becomes a manual sweep that is easy to do incompletely. The failure is silent, because a credential that was missed keeps working and nothing reports it.

Does a control plane mean giving up direct access to a system?

No. The systems keep their own interfaces and their own admin consoles. What changes is the path an AI client takes to reach them, and that path is the one that needs rules, because it is the one a model drives.

Put agents to work on your own systems

14 days on Gold, no credit card. Start with one app and one team.

Works with
Claude ChatGPT Cursor and any other MCP client, or the Elaichi Agent.
When the trial ends
Nothing is deleted. Connections, roles and the audit log stay where they are, so subscribing picks up exactly where you left off.