MCP gateway vs raw MCP servers: how to run a company through any agent

Every tool your company uses now has an MCP server, and the usual way to give an agent access is to plug them all in. It demos well and breaks on permissions, rules, context and the next agent you try. An MCP gateway over your company's ontology gives every agent one door, with your own actions, roles and history behind it.

Constantine Yurevich · 8 October 2026 · 15 min read

Imagine running the operational side of a company from your phone. No laptop, no dashboards, no tabs. You send a voice note on the way to a meeting and the new contact is in the CRM. You photograph a receipt and it's filed as an expense. You say the deal is moving to a pilot and it moves, with a reminder for the contract. You ask for the October update to go to the customers who stopped opening your emails, and a draft is waiting for review by the time you're back at a desk.

  1. 08:40“Met Anna Lee from Acme at the conference. Add her and put her on the Acme deal.”ChatGPT, voice, in the carcontact.createdeal.addContact
  2. 11:15“Taxi to the client, the receipt's attached.”Claude, phone, with a photoexpense.submit
  3. 13:05“Acme said yes to a pilot. Move it, and remind me to send the contract on Friday.”A bot in Telegram, voice notedeal.moveStagetask.create
  4. 16:30“Draft the October update for Pro customers who haven't opened the last three.”Grok, typed between meetingssegment.buildcampaign.draft
  5. 18:10“How did last week's campaigns do? Pause anything over €80 per sale.”ChatGPT, voice, walking homemetrics.queryadCampaign.pause
An illustrative day of operations, marketing and sales run from a phone. Five requests, most of them spoken, four different agents, one set of actions underneath.

None of this needs a new model. The agents can already listen, read a photo and call tools. What decides whether this works for a real company is what the agent is connected to, and how.

The usual way: plug everything in

The Model Context Protocol made connecting agents to software easy. By December 2025 Anthropic counted more than 10,000 active public MCP servers. Your CRM has one. So does your email platform, your inbox, your database, your expense tool. The standard advice is to add them one by one to whichever agent you use, sign in to each, and start asking.

Each of those servers does the same thing: it takes the vendor's API and exposes it as tools. HubSpot's official server has manage_crm_objects, which creates or updates any CRM record. Resend's official server registers 106 tools, from send-email and send-broadcast to create-api-key. Google's Gmail server searches and reads every thread and writes drafts. A database server offers a tool to run any SQL.

That is a fine way to explore. It is a poor way to run a company, for five reasons.

1. Every agent holds every key. Each server is authorised with its own token, stored in the agent's configuration. Whatever that token can do, the agent can do, and most tokens can do everything the account can. There is no notion of "this agent may draft campaigns but not send them" or "it may file expenses but never approve one". The MCP specification itself says there should always be a human in the loop with the ability to deny tool calls, which is hard to arrange when every server is its own all-or-nothing grant.

The servers themselves are code you trust with those keys, too. In September 2025 an unofficial npm package called postmark-mcp, a server for sending email through Postmark, added a backdoor in version 1.0.16 after fifteen clean releases: it quietly BCC'd every email it sent to an outside address.

2. The agent reads things you don't control. An agent connected to your inbox reads emails written by strangers. If the same agent can also read your customer list and send email, a single crafted message can ask it to do exactly that. Simon Willison calls this combination of private data, untrusted content and a way to send data out the lethal trifecta. Connect enough raw servers to one agent and you have all three.

It has been shown on real servers. In May 2025 Invariant Labs demonstrated that a malicious issue in a public GitHub repository could get an agent using GitHub's official MCP server to copy data from private repositories into a public pull request. Two months later, General Analysis planted instructions in a support ticket and got an agent connected through Supabase's MCP server, with a key that bypassed row-level security, to write private tables back into the ticket thread. Neither was a bug in the usual sense. The agent did what it read, with the access it had been given.

3. Your rules live nowhere. Unsubscribed contacts must not get marketing email. Nobody approves their own expense. Won deals are final. In a stack of raw servers, those rules exist only if someone remembers to put them in a prompt, and only for the agent that prompt was written for.

4. There is no single source of truth. "Customer" means one thing in the CRM, another in billing and a third in the email platform's audience. An agent connected to all three has to stitch them together on every request, and it will stitch them differently from one day to the next. That is where many agent mistakes in business work come from: not invented facts, but three systems with three definitions and nobody saying which one counts.

5. The context fills up with tools. Every tool's name, description and input schema is loaded into the agent's context before it reads your question. Anthropic's engineers measured a typical setup of five servers, GitHub, Slack, Sentry, Grafana and Splunk: 58 tools and about 55,000 tokens of definitions before the conversation starts. They also found the most common failures are picking the wrong tool and passing the wrong parameters, especially when tools have similar names. VS Code refuses more than 128 tools in a request. The agent spends its attention on vendors' API surfaces instead of your question.

The part nobody talks about: switching agents

There is a sixth problem, and it is the one I run into every day.

I don't use one agent. Some tasks go to ChatGPT, some to Claude, some to Grok, some to a bot on my phone, and next year there will be another one worth trying. Every one of them needs its own connectors, its own sign-ins and tokens, its own folder of skills and its own idea of what it is allowed to do. On every laptop and every phone. Switch agents and you start again.

Companies are the same at a larger scale. Netskope's 2026 Cloud and Threat Report counted an average of eight generative AI apps in use per organisation, up from six a year earlier.

Set up inside each agent

ChatGPT

Connectors · Tokens and sign-ins · Skills folder · Permissions

Claude

Connectors · Tokens and sign-ins · Skills folder · Permissions

Grok

Connectors · Tokens and sign-ins · Skills folder · Permissions

Telegram bot

Connectors · Tokens and sign-ins · Skills folder · Permissions

…again on every laptop and phone, and from scratch when you switch.

Set up once, in the workspace

ChatGPTClaudeGrokTelegram botnext year's agent
One gateway URL · each agent signs in as you

Connections

Every system connected once, with keys in the workspace

Skills and guides

How your company works, in guides every agent reads

Roles

What each person and each agent may do

History

Every action, whichever agent ran it

Without a gateway, the setup lives inside each agent. With one, it lives in the workspace and every agent signs in to it.

The large vendors have noticed. In Claude Team and Enterprise, an owner adds a connector for the whole organisation and can provision skills centrally. In ChatGPT Business and Enterprise, admins publish MCP apps for the workspace, and Enterprise can limit them by role. Grok, Gemini Enterprise and Microsoft's Copilot Studio have their own versions. Each is a good answer inside its own product, and wherever a connector uses each person's own sign-in, everyone authorises it again, in that vendor's console. The connectors, the skills and the permissions you configure there belong to that ecosystem. Move to another agent, or let a team use the one they prefer, and the work is redone from scratch. Your company's context ends up locked into whichever assistant you picked first.

The open standards get you halfway. MCP now belongs to the Linux Foundation's Agentic AI Foundation, and Anthropic's Agent Skills format is read by GitHub Copilot, OpenAI Codex and Cursor. But a connection authorised in one client doesn't carry over to another. In practice each client registers with a server as itself and keeps its own tokens; ChatGPT, for one, identifies itself with its own client ID. The specification adds that a token is bound to the server it was issued for and must not be passed on. The protocol is portable; your setup isn't.

Your company's context should belong to your company, and any agent should be able to use it.

What an MCP gateway is

An MCP gateway is a single MCP endpoint that sits between your agents and your systems. Agents connect to the gateway instead of to each server. The gateway decides who is calling, what they may do and where the call goes, and keeps a record of it.

There are plenty of them now. Docker, Microsoft and IBM have open-sourced MCP gateways; Cloudflare and Kong build them into their platforms; startups like Runlayer, Lasso and Obot are built around them; and Gartner tells software engineering leaders to evaluate and implement one. Reading their documentation, they do some mix of the same things: gather servers behind one endpoint, handle sign-in, allow-list tools, scan for injected instructions and log every call. That is useful, and it fixes the first problem. But they pass through the same raw vendor tools: the agent still sees "create or update any CRM record" and "send any email", just through one door. Where they create tools at all, they translate an existing REST endpoint one-to-one or bundle tools that already exist.

The difference we care about is what's behind the door.

Raw MCP servers

Agent
CRMCreate or update any record
Email platformSend any email, create API keys
GmailRead every thread, write drafts
DatabaseRun any SQL
ExpensesCreate, edit or approve any report
Each server brings its own token, its own tool names and its own idea of a customer. Nothing checks one against another, and nothing records what the agent did across them.

MCP gateway over an ontology

Agent
Gateway · one connector, an identity for every agent

Ontology: your business's own actions

contact.createdeal.moveStageexpense.submitsegment.buildcampaign.draft

Connections, with credentials kept in the workspace

CRMEmail platformGmailWarehouseAccounting
Raw servers give the agent each vendor's API. A gateway over an ontology gives it your business's own actions, and keeps the systems and their keys behind them.

Actions, not endpoints

In SegmentStream Cloud the gateway sits on top of your company's ontology: the entities your business runs on, the actions that may change them and the roles that may run those actions, all defined in code in your repository. We wrote about why that layer matters when companies leave their CRM; here is what it means for agents.

Every action becomes a tool. Not manage_crm_objects, but expense.submit, deal.moveStage, segment.build, campaign.draft. Each has a plain-language description, typed input and your business rules inside. It is what Anthropic itself recommends when writing tools for agents: instead of list_users, list_events and create_event, build one schedule_event that does the job. This is an expense, abridged from a real definition:

export const Expense = entity("expense", {
  label: "Expense",
  description: "Money a team member spent for the company, with its receipt.",
  properties: {
    amount: p.number({ min: 0, description: "The total on the receipt." }),
    receipt: p.url({ description: "The uploaded receipt." }),
    status: p.select(
      [
        { value: "submitted", label: "Submitted", description: "Waiting for a manager." },
        { value: "approved", label: "Approved", description: "Will be paid in the next run." },
        // rejected…
      ],
      { default: "submitted", managed: true },
    ),
  },
  relationships: {
    spender: rel.one(User, { inverse: "expenses", phrase: ["was spent by", "spent"] }),
  },
}).actions((self) => ({
  approve: action({
    description: "Approve a submitted expense for payment. Check the receipt matches the amount first.",
    input: Schema.Struct({ expense: self.ref }),
    handler: ({ input, principal }) =>
      Effect.gen(function* () {
        const expense = yield* self.get(input.expense, { forUpdate: true });

        if (expense.spenderId === principal.id) {
          return yield* new ActionRejected({ message: "Nobody approves their own expense." });
        }
        yield* self.update(expense, { status: "approved" });
      }),
  }),
}));

The rule "nobody approves their own expense" is not in a prompt. It is in the action, and it holds for a person in the app, a script calling the API and every agent on the gateway alike.

Agents hold roles, like people do. A role is a list of what it may do:

export const assistant = role("assistant", {
  description: "An AI assistant that files expenses and keeps contacts and deals up to date.",
  permissions: ["contact:read", "contact:create", "deal:moveStage", "expense:submit", "segment:build", "campaign:draft", "adCampaign:pause", "metrics:query", "subscription:read"],
});

The gateway lists only the tools the caller's role allows. An agent holding assistant doesn't see expense.approve or campaign.send at all, so it can't be talked into using them.

Tool, as the agent sees itAssistant role
  • contact.findFind people and companies by any propertyListed
  • contact.createAdd a contact; one per email, linked to its companyListed
  • deal.moveStageMove a deal; won deals are final, a reason is keptListed
  • expense.submitFile a receipt against the person who paidListed
  • expense.approveApprove for payment; never your own expenseNot listed
  • segment.buildBuild a segment; unsubscribed contacts excludedListed
  • campaign.draftDraft an email to a segment for reviewListed
  • campaign.sendSend a reviewed campaign through the email platformNot listed
  • subscriptions.listList software subscriptions for the asker's departmentListed
  • metrics.queryAnswer from defined metrics, such as cost per saleListed
  • adCampaign.pausePause an ad campaign; the reason is keptListed
  • adCampaign.setBudgetChange a daily budget; above the limit, a person decidesNot listed
The tool list is your business's actions, filtered by role. The assistant can draft a campaign; sending it takes a person who holds campaign:send.

That is also how approval works without a new mechanism. The agent prepares, a person with the permission confirms. A rule like "campaigns above a thousand recipients need marketing lead sign-off" is one more check inside the action.

One request, two ways

Here is the same voice note handled by raw servers and by the gateway: email Pro customers who haven't opened our last three updates.

Raw MCP servers

“Email Pro customers who haven't opened our last three updates.”
query("SELECT email FROM …")Its own guess at what “Pro” and “opened” mean
send-broadcast({ to, subject, html })
Sent at once. Whoever unsubscribed in the CRM last week may be on the list. Nothing lands on the contacts, and the key it used can send anything to anyone.

MCP gateway over an ontology

“Email Pro customers who haven't opened our last three updates.”
segment.build({ plan: "pro", unopened: 3 })“Pro” and “opened” as the business defines them
campaign.draft({ segment, subject, body })
Unsubscribed and bounced contacts are excluded by the segment itself. A marketer reviews and runs campaign.send; the email platform delivers it, and every contact records what they were sent.
The same request. Raw servers leave the agent to define the audience and send; the gateway gives it the business's own segment and a draft for review.

With raw servers, the agent writes its own query to decide who "Pro" and "hasn't opened" are, and calls the email platform's send tool. It may be right. It may also include the people who unsubscribed in the CRM last week, because the email platform's audience doesn't know about them yet. Nothing is recorded on the contacts. And the token it used can send anything to anyone.

With the gateway, "Pro customer" and "opened" are defined once, in the ontology, and the segment action applies them, including the rule that unsubscribed and bounced contacts are excluded. The agent drafts. A marketer reviews and sends. The email platform delivers the campaign exactly as before, and every contact's history shows what they were sent and who approved it.

Marketing: the numbers your team reports, and the buttons it presses

SegmentStream started in marketing measurement, and this is where raw connections go wrong most quietly.

Ask an agent connected to Google Ads, Meta and GA4 how last week's campaigns did, and it will ask each of them. Every ad platform reports the conversions it claims credit for, so the same sale is counted more than once and the totals add up to more orders than you had. GA4 disagrees with both. The agent adds them up or picks one, and gives you a confident answer that matches none of your reports. Then you tell it to pause anything over €80 per sale, and it does, with a token that can also change every budget in the account.

Through the gateway, "conversion", "cost per sale" and "ROAS" are defined once in your semantic layer, on the attribution model your team trusts, so the agent's answer is the number in your weekly report. Pausing a campaign is an action: the marketing assistant may run it with a reason, the change reaches the ad platform through the workspace's connection, and it lands in the same history as everything else. Raising a budget above a limit is a different action that only a person holds. Launching works the same way: the agent drafts the campaign from your targeting and creative, a person reviews it, and the launch is recorded.

Raw MCP servers

“How did last week's campaigns do? Pause anything over €80 per sale.”
Pulls each platform's own reportGoogle Ads, Meta and GA4, each with its own count of conversions
Adds them up, or picks onePlatforms each claim the same sales, so the totals exceed your orders
Pauses through the ad platform with a token that can also change every budget. The numbers match none of your reports, and nothing records why the campaign stopped.

MCP gateway over an ontology

“How did last week's campaigns do? Pause anything over €80 per sale.”
metrics.query({ measure: "costPerSale", by: "campaign", period: "lastWeek" })Cost per sale on your own attribution model, as your weekly report shows it
adCampaign.pause({ campaign, reason })
The same numbers the marketing team reports. The assistant may pause; raising a budget past the limit takes a person. Every pause reaches the ad platform through the workspace's connection and is kept with its reason.
The same request about ad campaigns. Raw servers leave the agent to reconcile three platforms' numbers; the gateway answers from your own metrics and pauses through a permitted action.

Finance: a narrow door, not the whole ledger

Which software subscriptions are we still paying for, who owns each one, and what do they cost us a month? It is a good question for an agent, and a risky one to answer with a raw connection.

Xero's official MCP server has 51 tools. Next to listing bank transactions and invoices, they create payments, bank transactions and manual journals, and read payroll employees and timesheets, and its default sign-in asks for scopes that cover all of it. Connect it with those defaults, and the agent you asked about software spend can also post payments and journals to the ledger and, on Xero Payroll in the UK or New Zealand, read employee records and timesheets. To answer, it reads every bank transaction and guesses which ones are subscriptions.

Through the gateway, you give the agent a narrow door instead. Xero is one of the workspace's connections, its transactions land in your warehouse, and the ontology says what a subscription is: a supplier, a monthly cost, an owner, a department and the last charge. One read-only query answers the question, and roles decide which rows come back. The head of marketing, asking through whichever agent they like, sees marketing's subscriptions. Finance sees all of them. Nobody's agent sees payroll, because no role that agents hold grants it. Cancelling stays a person's decision: the agent can open a task for the owner, and it can't touch the ledger.

Raw accounting server

“Which software subscriptions is marketing still paying for?”

What the token reaches, among 51 tools

list-bank-transactionslist-invoiceslist-payroll-employeescreate-paymentcreate-manual-journalupdate-bank-transaction
To find software spend, the agent reads every bank transaction and guesses which are subscriptions. The same token can post payments and journals and, in the UK and New Zealand, read payroll records.

MCP gateway over an ontology

“Which software subscriptions is marketing still paying for?”
subscriptions.list({ department: "marketing" })
Semrush€499/moDanalast Oct 1
Canva, 2 seats€220/moMarialast Sep 28
Figma€135/moAlexlast Oct 3
Hotjar€80/moOwner left in Junelast Oct 2
Read-only, and only marketing's rows for the head of marketing. Payroll, payments and journals aren't in the agent's tool list at all.
The same question about software spend. A raw accounting server hands the agent the whole ledger; the gateway gives it one read-only view, filtered to the asker's department. Subscription data is illustrative.

The same pattern answers most finance questions people want to ask an agent: cash and runway, overdue invoices, spend by team. Each becomes a defined, read-only view with its own permission, like the ones our own finance app is built on, instead of a key to the books.

What happens on every call

  1. 01

    Who is calling

    Which agent, acting for which person. Each agent has its own identity and key.

  2. 02

    What it may do

    The tool list holds only the actions this agent's role may run.

  3. 03

    Valid input

    Input is checked against the action's types. Unknown fields and records are refused.

  4. 04

    Your rules

    The action's business rules run in one transaction, or nothing changes.

  5. 05

    Outside systems

    Calls to outside systems go through a connection. The agent never holds the key.

  6. 06

    History

    The change is kept with the agent, the person and the values before and after.

Every call through the gateway takes the same path, whichever agent made it.

One history for everything agents do

Sooner or later someone asks. Who moved the Acme deal on Friday? Who emailed the customer who had unsubscribed? Who deleted this contact, and what was in it?

With raw servers, the answer is spread across every vendor. The CRM's history shows the integration user whose token the agent used, not which agent it was or whom it was acting for. The email platform's log shows which API key sent the message. The database remembers nothing unless someone turned on audit logging. What the agent was asked, and by whom, sits in one person's chat history in one vendor's app. And many of those connections are personal: someone linked their own inbox or CRM account to their own assistant, and the company can't see that connection at all. Reconstructing a Friday afternoon means asking around.

With a gateway, every call goes through one place, so the record does too. The gateway logs each call with the person, the agent acting for them, the action it asked for and its input, refused calls included. The ontology keeps every change the action made, record by record, with the values before and after. A change that reached another system, like a campaign sent through the email platform, is recorded as the action that sent it.

  1. Fri 13:05Maria, via a Telegram botdeal.moveStageAcme: Negotiation → Pilot. “They said yes to a pilot.”
  2. Fri 13:05Maria, via a Telegram bottask.createSend the Acme contract, due Friday
  3. Fri 16:30Maria, via Grokcampaign.draftOctober update to 1,212 Pro customers
  4. Fri 18:10Danacampaign.sendSent through the email platform
  5. Sat 09:30Ops bot, via Telegramcontact.deleteDeleted J. Smith; every value kept in history
  6. Sat 11:15Ops bot, via Telegramexpense.approveRefused: nobody approves their own expense
An illustrative history. Every person and every agent, across every system, in one place, with what each change replaced.

"Who moved this deal?" becomes a lookup instead of an investigation. "What did the assistant do on Maria's behalf this week?" is a filter. And because every change keeps the value it replaced, a mistake can be traced to the action that made it and the previous values put back, whichever agent made it. That is what makes it reasonable to let agents act at all.

The systems stay where they are

Your email platform still delivers email, your inbox still holds mail, your CRM can keep running while you move off it. The gateway calls them through the workspace's connections, so their credentials stay in the workspace's secret store, never in an agent's configuration. Change your email provider and you change one connection; the actions, the roles and every agent stay as they were.

And the context goes with you. The connections, the guides that explain how your company works, the roles and the history all live in the workspace. ChatGPT, Claude, Grok, a bot on your phone or an agent that doesn't exist yet connects to the same URL, signs in as you, and starts with all of it.

Credentials
Weak:Raw: A token per server, in every agent's config
Strong:Gateway: Held in the workspace; agents never see them
Permissions
Weak:Raw: Whatever the token can do, usually everything
Strong:Gateway: Per agent and per action, checked on every call
Tools in context
Weak:Raw: Dozens per server, in each vendor's terms
Strong:Gateway: A short list of your own actions
Business rules
Weak:Raw: In the prompt, if anywhere
Strong:Gateway: Inside every action: limits, consent, approvals
Source of truth
Weak:Raw: Each system's, and the agent stitches them
Strong:Gateway: One definition of a customer for every agent
Audit
Partial:Raw: Scattered across vendors' logs, if kept
Strong:Gateway: One history: who, which agent, before and after
A poisoned email or page
Weak:Raw: Can reach every tool the agent holds
Strong:Gateway: Limited to the actions the agent's role allows
Switching vendors
Weak:Raw: Re-wire every agent and rewrite its prompts
Strong:Gateway: Change the connection; actions and agents stay

● strong   ◐ partial   ○ weak

Raw MCP servers and a gateway over an ontology, compared on what decides whether agents can run real work.

Before you connect another MCP server

Ask these about whatever your agents connect to:

  1. Whose key is it? Does the agent hold credentials, or does it sign in to something that holds them?
  2. What can it do? Is there a list of permitted actions for each agent, checked on every call?
  3. Where are your rules? In the system, enforced for everyone, or in a prompt?
  4. What does "customer" mean? Is there one definition every agent reads, or does each agent stitch one together?
  5. What happened? Can you see every change an agent made, across every system, with the value before?
  6. What happens when you switch agents? Does your setup move with you, or do you start again?

If the answers depend on which agent you're using, your company's context lives in the wrong place.

See how every workspace serves its ontology to agents over MCP and how we run our own CRM on it, or start a pilot: our engineers model your business, connect the systems you already use and hand you the repository. Or read why a company can run on one agent, why agents need a semantic layer and what to check before you cancel HubSpot or Salesforce.

Enterprise pilot

Start a pilot.

Our forward-deployed engineers build one solution on your data, in your own workspace, as code you own. Tell us what you run today and what you want; your note goes straight to our founder.

  • One solution, on your data, in your own workspace
  • First version live in two weeks
  • Parity proven before anything is switched off
  • Fixed scope and price, credited to your contract if you continue

Not ready for a pilot? Send the form anyway with your question. An engineer will reply, not a sales rep.

How the pilot works

Goes to our founder’s inbox. No sales queue, no newsletter.

Your company’s software, built by agents, owned by you.

Start a pilot

Our engineers build the first version on your data in two weeks, at a fixed price.

Or join the waitlist for self-serve:

We’ll email you product updates, tips and onboarding help. Unsubscribe anytime.

Self-serve opens to the waitlist first.