Agent security architecture

OpenAPI to MCP for Internal APIs, Without Building an MCP Server

Use your OpenAPI spec to give AI agents controlled access to a private API. Choose operations, approve sensitive writes, run calls through a private connector.

Updated Oct 26, 2026

Use your OpenAPI spec to give agents controlled access to a private API. Choose their operations, require approval for sensitive writes, and execute calls through a connector inside your network. The API stays private, and you do not build or host an MCP server for it.

Your API already does the work. Your AI agent cannot reach it.

Your billing API already knows how to read invoices and create credit notes. It runs on your own servers in AWS, in a private subnet. Your cloud AI agent cannot reach it.

Connecting the agent means more than finding a network path. You also need to expose the right operations, keep credentials out of the agent, decide which calls need approval, and record what happened.

Contro1 brings those steps together. Import your OpenAPI 3 document, review and publish selected operations, and grant them to your agents. The agents call those Actions through Contro1's MCP connection. A connector inside your network picks up authorized jobs and calls your API.

Your API stays private. You do not need to build or host an MCP server for it.

Watch a support agent request a credit note, a finance manager approve it, and the connector run it inside the VPC:

An agent asks, a person approves, and the connector runs it inside your VPC: Claude Code interface recreated for illustration. Demo organization and data are fictional.

Teams describe the wall in the same words. The API "works on my laptop", because the laptop is on the VPN and sees the private DNS. The cloud agent is not on that VPN, and the service has no public route.

Private does not mean nothing leaves the network. The API's address and its credential never leave the connector machine. The inputs of each call and the API's answer do travel through Contro1, so it can check policy and give the agent the result.

Let an agent finish work in an internal system: on-prem applications

Setup, once: from your OpenAPI document to Actions your agents can call

An OpenAPI document describes what an API can do. It is not a security policy. The policy is the choice an administrator makes from it, operation by operation.

Import the OpenAPI 3 document

Every operation arrives as a draft. Contro1 ignores the servers list and refuses remote references, so the document cannot point anywhere you did not intend.

Review each operation

Confirm what it does, its inputs, its effect and its risk. A POST is at least a medium-risk write, a DELETE is high-risk. Agents will read the title and description you approve.

Publish only what a task needs

Publishing freezes the chosen operations and their fingerprints. Anything you leave out never becomes a tool, and new operations in a later version stay drafts until someone reviews them.

Grant operations to agents

Choose which department, person or specific agent may use each operation, and whether it runs on its own or waits for a person.

Should every endpoint become a tool? No. A large API can have hundreds of endpoints. Exposing all of them floods the agent's context and invites the wrong pick. Publish the few that serve a real task.

At run time: the agent asks, Contro1 decides, the connector calls your API

Every call follows the same path. The agent never talks to your API directly, and nothing in your network listens on a public address.

Give each agent its own operations. Hiding a tool is not the same as blocking it.

Different agents need different slices of the same API. A support agent reads invoices and proposes credits. A finance agent issues them. A coding agent reads customer records and nothing else.

Billing API operationSupport agentFinance agentCoding agent
Read invoicesRuns on its ownRuns on its ownNot granted
Read customerRuns on its ownRuns on its ownRuns on its own
Create credit noteWaits for FinanceRuns on its ownNot granted
Delete customerNot grantedNot grantedNot granted

Two layers apply to every agent:

The agent sees only its own Actions

Its list holds what it was granted, so its context stays small and it does not pick an operation it should never use.

Every call is checked again, server side

Hiding is not the control. If an agent calls an operation it was not granted, Contro1 refuses it before anything reaches your API.

An operation is not a record. A grant for "Read customer" says the agent may call that operation. It does not say which customers. Contro1 enforces the operation, the agent and the approval. Which records the call can reach is decided by your API and by the rights of the credential the connector uses. Give that credential only what the published operations need, and put sensitive writes behind approval so a person sees each one.

Keep API keys outside the agent context

The credential is the real permission. If the agent holds it, the agent, its prompt and its logs can all leak it.

  • The key lives on the connector host. The person who installs the connector enters the API's address and its credential there: an API key header, basic auth or a bearer token. Contro1 never receives them. The agent never sees them.
  • One credential per application. The connector calls your API with that one credential. It does not pass each user's own OAuth identity through, so keep the credential narrow.
  • Private DNS, checked TLS. For a private hostname you pin the address the connector should dial. It still checks the TLS certificate for the hostname.
  • HTTPS for anything with a credential. Plain HTTP is allowed only to the same machine, for example when the connector runs next to the API.
  • Who acted is still recorded. One credential reaches the API, but every call in Contro1 names the person who asked and the agent that acted.

Approve sensitive writes, not every call

Approving call by call just teaches people to click yes. Reads and routine actions should run on their own. A person should see the writes that matter: money, customer records, anything hard to undo.

When a call needs approval, the approver sees it in plain words, in Contro1, Slack or Teams:

  • An approval belongs to one call. Approving this credit note does not approve the next one.
  • Nobody answers? The request climbs from the agent's reviewer to on-call, managers and admins.
  • A retry never doubles a write. The connector journals every write before it runs. If the answer is lost, the call is marked uncertain and is not retried automatically. A person checks first.

What to log for security, compliance and incident response

Matching timestamps across logs during an incident is slow. The record should answer the questions in one place:

Who asked

The person whose request started the run.

Which agent acted

The agent's own identity, not a shared key.

Which operation

The exact Action, and whether policy let it run, held it or refused it.

Who approved

The approver, when, and the reason they saw.

What happened

The result the connector reported, or an uncertain state when the answer was lost.

One trace per run

Every call of one run under one trace, next to the agent's other tool calls.

Already running an MCP server behind a firewall?

Then you have a different question: how a cloud agent reaches that server. Be clear about what Contro1 does here.

  • Contro1 does not tunnel to your MCP server. The connector calls the HTTP API, from its OpenAPI operations. If your MCP server wraps an internal API, connect that API instead, and you can retire the wrapper.
  • If your MCP server is reachable over the internet with proper auth, add it in Contro1 as an application on the internet. Contro1 connects to it directly, with the same grants, approvals and record.
  • If it must stay private and has no API underneath, an outbound MCP tunnel from your AI platform is the closer fit today. The server behind it still needs scoping, approvals and an audit trail.

VPN vs MCP tunnel vs gateway vs custom proxy

Each answers part of the question. Pick by what you need to control, not only by how packets travel.

OptionWhat it gives youWhat is still on you
VPN to the agent hostReachability with tools you already run.Hard to run for many agents. Network rules decide which hosts it reaches, not which operations it may call.
Public endpoint or reverse proxyWorks with any cloud agent.The API is now public. Auth, rate limits and abuse are yours, and the security review usually ends here.
MCP tunnelOutbound only, no public endpoint. Some AI platforms now offer one.Tied to one platform, and you still build and run the MCP server. Scoping, approvals and audit are yours.
Self-hosted MCP gatewayOne place for auth, routing and logs.Another service to run and secure, plus the MCP servers behind it.
Custom policy proxyKeys stay in the proxy. You choose hosts, methods and paths.It becomes your product: policy, approvals, retries, audit, uptime.
Contro1 connectorOperations from your OpenAPI, outbound only, grants per agent, approval for writes, one record. No MCP server to build.Early access. One credential per API on the connector host.

The same control for coding agents, from the same place

Developers hit this wall first. A coding agent in a cloud sandbox cannot see the staging API that works on the laptop. The quick fix is to hand it the VPN, an SSH key or an API key. Then nobody decides what it may change, nobody approves the risky step, and nobody can tell later what it did.

With Contro1 a coding agent gets the same controls as a production agent:

Internal APIs only through granted Actions

Reads can run at once. Changes wait for you or your lead. The agent never holds the API's address or key.

Risky steps on the machine wait for a person

Hooks for Claude Code and Codex send the actions you select, such as deploys, database operations, infrastructure changes or privileged tools, to an approver before they run. Organization-managed settings keep the rule for every developer.

What it did is on the record

Each tool call is reported to Contro1, one trace per run, next to the Actions it ran.

Its own identity, not yours

Connecting registers the coding agent as an agent of its own, with its own grants. Your personal access does not flow to it.

Connect a coding agent
contro1 connect claude-code   # or: contro1 connect codex, contro1 connect cursor

One control layer for every agent and every app

Your internal API becomes one more application in Contro1, next to your SaaS apps and your on-prem ones. Every agent in the organization reaches all of them through the same place: production agents, coding agents and personal assistants.

What you need to start

Three things. Most teams have them on day one.

An internal API with an OpenAPI 3 document

Reachable over HTTPS inside your network, or over plain HTTP if the connector runs on the same machine. No OpenAPI file? A hand-written list or the vendor's API documentation as a PDF also works.

A small VM in the same network

Linux or Windows, in a private subnet that can reach the API. It needs outbound HTTPS to Contro1, through a NAT gateway or a proxy. No public IP, no inbound rule.

The first two or three operations

Pick one task, such as reading invoices and creating a credit note. Start with reads, then add writes with approval.

Install steps for your cloud team

On-prem and self-hosted connectors are in early access, and we set up the first one with you. When you are ready, send this section to whoever runs the network. It is three commands on the VM.

Before they start: in Contro1, open the application, choose Create installation code and download the setup file. Send it to them privately, because it holds a one-use code. On the VM they fill in the API's private address, the IP to dial and the credential. Those values never leave the VM.

Link to send to your cloud team
https://contro1.com/resources/openapi-to-mcp-for-internal-apis#install-steps-for-your-cloud-team
Linux VM
# 1. Install the Contro1 CLI
curl -fsSL https://contro1.com/install.sh | sh

# 2. Install the connector as a systemd service
sudo "$(command -v contro1)" private-connector install < contro1-private-connector-<id>.json

# 3. Check that it is connected
sudo "$(command -v contro1)" private-connector status
Windows VM
# 1. In PowerShell, install the Contro1 CLI
irm https://contro1.com/install.ps1 | iex

# 2. Open a new PowerShell window as Administrator, then install the connector
Get-Content .\contro1-private-connector-<id>.json -Raw | contro1 private-connector install

# 3. Check that it is connected
contro1 private-connector status
  • Security group: no inbound rules. Allow outbound HTTPS (443) to Contro1.
  • Behind a proxy: add a proxy_url line to the setup file before step 2. It applies only to traffic to Contro1.
  • Done when: status shows Cloud: connected_authenticated and Provider: reachable. The service starts again on its own after a reboot.

Questions your security team will ask

Bring these answers to the review.

QuestionAnswer
Does the API need a public IP or endpoint?No. The connector makes outbound HTTPS calls only. The API stays in its private subnet.
Any inbound rule in the security group?No. Outbound HTTPS to Contro1 is enough.
Does Contro1 store the API's address or key?No. They are entered and stored on the connector VM.
What data passes through Contro1?The Action's inputs and the API's answer, so Contro1 can check policy and return the result to the agent. Results are size-limited. The address and the credential do not.
Which records can an agent reach?Contro1 enforces which operations each agent may call and which need approval. Record-level limits come from your API and the credential the connector uses.
Can someone send the connector an arbitrary request?No. It runs only published operations, pinned by fingerprint. Jobs carry inputs, never URLs, headers or code.
What if a job is forged or replayed?Jobs are signed and checked before they run, and each job is handed out once.
How do we turn it off?Revoke the agent's grant in Access, or stop the connector. Calls fail at once.

OWASP Top 10 for Agentic Applications ยท Model Context Protocol: Authorization

When you do not need this

If your API or MCP server is already public, with good auth and narrow scopes, connect it like any other app.

If one developer needs a coding agent to reach a staging service for an afternoon, a VPN or an SSH session is fine.

You need this when the API must stay private, agents write to it, more than one agent or person relies on it, or you will need to show later what each agent did and who allowed it.

Start with one API and one workflow

Reaching a private API is the easy half. The harder half is deciding which agent may do what there, and proving it afterwards.

Tell us which application you want to connect and what your agent should do first. We will review the API and network requirements, identify the first operations, and scope an early-access pilot with you.

Frequently asked questions

Can I turn an existing OpenAPI or Swagger spec into MCP tools?

Yes. Import the OpenAPI 3 document into Contro1, review each operation, and publish the ones you want. Agents then see them as Actions over Contro1's MCP connection, with titles and input schemas from the document. You do not build or host an MCP server.

How can a cloud AI agent reach an API that is only available on a private network?

Run a small connector inside the private network that opens an outbound HTTPS connection. The agent calls an Action in Contro1, Contro1 checks the grant and any approval, and the connector runs that one operation against the private API. The API never gets a public endpoint.

Do I need to expose an MCP server to the public internet?

No. With Contro1 the internal API does not need an MCP server at all: agents use Contro1's MCP connection, and the connector inside your network calls the API over an outbound connection.

Can Contro1 connect to an MCP server I already run behind a firewall?

Not through the connector. The connector calls HTTP APIs from their OpenAPI operations. If the MCP server wraps an internal API, connect the API instead. If the MCP server is reachable over the internet with proper auth, add it as an application on the internet.

Should every OpenAPI endpoint become a tool?

No. Publish the few operations that serve a real task. A long tool list floods the agent's context and makes a wrong pick more likely. Unpublished operations stay drafts.

How do I give different agents different API permissions?

Grant operations per department, person or specific agent, and choose for each whether it runs on its own or waits for a person. Which records an operation can reach is set by your API and the credential the connector uses.

Is hiding a tool from the agent enough?

No. Hiding keeps the agent's context small, but the control is the check on every call. Contro1 refuses any operation the agent was not granted, server side, before it reaches the API.

Where should API keys and OAuth tokens live?

Outside the agent. With the Contro1 connector, the API's credential is entered on the connector host and never reaches Contro1 or the agent. Use a dedicated credential with only the rights the published operations need.

Which actions should require human approval?

Writes with real impact: money, customer records, deletions, anything hard to undo. Let reads and routine actions run on their own so approvers are not flooded.

VPN, MCP tunnel, gateway or custom proxy: which should I use?

A VPN or tunnel gives reachability. A gateway or proxy gives a place for auth and logs. You still need grants per agent, approval for sensitive writes and a record. Pick the option that gives you those without making the API public.

Related resources