OpenAI Secure MCP Tunnel gives a private MCP server an outbound path to supported OpenAI products without an inbound firewall port or public endpoint. That solves transport exposure. It does not decide which workspace may use the tunnel, which tool may run, what downstream authority the tool receives, whether a write needs approval, or how an operator proves the final state. Release it across four planes: transport, association, tool authority and outcome evidence.
OpenAI's Secure MCP Tunnel guide describes a client inside the trusted network. The client opens outbound HTTPS to OpenAI, polls for queued work, forwards JSON-RPC to a local stdio or HTTP MCP server, then posts the response back. That removes the need to expose the MCP server directly to the internet.
For a CTO or platform owner, the important word is transport. A private route is valuable, but privacy is not permission. The release question is not “can ChatGPT or the Responses API reach this server?” It is:
Can one allowed context reach one allowed tool, exercise only its intended downstream authority, and leave enough evidence to reconstruct the terminal outcome?
If that second question has no answer, the tunnel is connected but not production-ready.
What Secure MCP Tunnel changes
The tunnel changes the network path. It can keep an internal MCP endpoint off a public URL while making it reachable from supported OpenAI surfaces. OpenAI documents ChatGPT, Codex and the Responses API among the supported contexts. The same guide says the private server remains customer-controlled and the client can use enterprise proxy settings, custom certificate authorities and MCP-side mutual TLS.
That gives an infrastructure team several concrete gains:
- no inbound public firewall rule for the MCP server;
- no public DNS and certificate lifecycle solely to expose the connector;
- a client process that can be deployed beside the server, as a separate Kubernetes workload or as a service on a virtual machine;
- explicit tunnel association with selected Platform organizations and ChatGPT workspaces;
- client health, readiness and metrics surfaces for operations.
The guide also draws boundaries. The tunnel supports private connections and custom MCP server testing. It is not a distribution mechanism for a public plugin. A public plugin still needs a stable public HTTPS endpoint.
What the tunnel does not change
OpenAI separates tunnel management, tunnel use, Platform organization permission and ChatGPT workspace MCP permission. Creating or editing a tunnel requires Tunnels Read + Manage. Running the client or selecting a tunnel requires Tunnels Read + Use. Association determines which allowed product contexts can discover and use the tunnel.
Those are necessary control-plane decisions. They do not make every tool inside the server safe for every caller. A tunnel association is eligibility to reach a server, not authorization for an arbitrary business effect.
A production release still needs to answer:
- Which organization and workspace contexts are associated with this tunnel?
- Which human or workload identity is represented at the application and downstream system?
- Which tools are visible, and which arguments and target resources are permitted?
- Which writes require approval for the exact proposed effect?
- Which downstream credential acts, and what audience and scope does it have?
- Where is invocation evidence recorded?
- Which authoritative system proves whether the effect happened?
- Who owns uncertainty, divergence, revocation and recovery?
The nearby DVNC guide on secure MCP across developer laptops and CI covers human and workload identity in depth. Secure MCP Tunnel does not erase that distinction. It changes how the client reaches the MCP server, not who the caller is or which credential should act.

Use a four-plane release contract
Treat the tunnel as one layer in a four-plane contract. Each plane has its own evidence and failure state.
| Plane | Release question | Minimum evidence | Failure terminal |
|---|---|---|---|
| Transport | Can the managed client reach OpenAI and the local MCP server without public ingress? | client identity, egress path, local endpoint, health and readiness | BLOCK |
| Association | Which Platform organizations and ChatGPT workspaces may discover and use the tunnel? | tunnel ID, associations, runtime use permission, owner | BLOCK |
| Tool authority | Which tools, arguments, targets and downstream scopes may act? | allowlist, policy version, approval rule, downstream subject | APPROVAL_REQUIRED or BLOCK |
| Outcome | What did the authoritative system record, and can the operator recover? | invocation receipt, provider read-back, terminal state, recovery owner | OBSERVED, UNCERTAIN or DIVERGENT |
The contract should be versioned beside the MCP server. A compact form can look like this:
tunnel:
id: tnl_internal_orders
public_ingress: false
client_owner: agent-platform
allowed_contexts:
platform_orgs: [org_production_agents]
chatgpt_workspaces: [workspace_operations]
tools:
allow:
- orders.read
- orders.propose_hold
deny:
- orders.release_payment
writes:
approval: per-effect
downstream_audience: orders-api
evidence:
application_invocation_log: required
authoritative_readback: orders-api
uncertainty_owner: operations-control
recovery_runbook: runbooks/orders-mcp.mdThese values are illustrative. The important properties are that a permitted context does not imply an unbounded tool set, a visible tool does not imply a permitted effect, and a successful JSON-RPC response does not prove the business system accepted the change.
Size the queue and deadline together
The current OpenAI guide documents these tunnel protections:
| Protection | Current documented value | Operator consequence |
|---|---|---|
| Sustained rate | 10 requests per second | Multiple clients do not multiply the allowance |
| Minute rate | 600 requests per minute | Bursts and sustained demand share the same tunnel boundary |
| Serialized request or response | 10 MiB | Envelope and headers count toward the total |
| Absolute deadline | 120 seconds | Hosted queue time consumes the same budget as local execution |
| Pending queue | 1,000 requests | Only work waiting to be polled counts here |
OpenAI describes these as protections, not throughput or latency guarantees. Do not divide 1,000 queued requests by 10 per second and call the result a guaranteed drain time. The client, local server, downstream dependencies and response size all consume capacity. The 120-second deadline starts when work enters the hosted queue and progress messages do not reset it.
Build a budget from the outside inward:
absolute deadline
- expected hosted queue time
- tunnel-client handoff
- MCP server processing
- downstream API time
- authoritative read-back
- response upload margin
= remaining uncertainty marginHere is a synthetic planning example, not a benchmark. If a team budgets 15 seconds for queue delay, 5 seconds for both tunnel transfers, 45 seconds for the local tool and downstream call, 15 seconds for read-back and 10 seconds for response margin, it consumes 90 of 120 seconds. The remaining 30 seconds is an uncertainty reserve, not time to schedule more work. Measure the real components during a canary and reduce the allowed workload before that reserve disappears.
Keep large documents out of a single tool result. Store the artifact in an approved system, return a bounded reference and let the application retrieve only what the next decision needs. That reduces message-size risk and makes authorization attach to a durable resource rather than a transient blob.
Put application evidence beside tunnel audit evidence
The logging boundary matters. OpenAI says tunnel control-plane authentication, long-poll traffic and individual transport requests are not emitted as ChatGPT Compliance Platform app events through the tunnel path. Tunnel metadata changes appear in Platform Audit logs as create, update and delete events. Normal application-level compliance logging still applies on the application path.
That separation means a tunnel audit event can prove that configuration changed. It cannot, by itself, prove that orders.propose_hold ran with approved arguments, which downstream subject acted, or whether the order system recorded the hold.
Join three records:
- Tunnel record: tunnel ID, association, client deployment, configuration revision and create/update/delete actor.
- Application record: calling context, tool, redacted normalized arguments, approval reference, policy version and invocation result.
- Authoritative outcome: downstream resource ID, provider state, read-back timestamp and terminal classification.
Do not log raw secrets or sensitive payloads to make that join. Stable identifiers, digests and redacted argument shapes are enough when the systems preserve the underlying records under their own access controls.

Test a release gate before the first write
I wrote a dependency-free evaluator for this article and ran eighteen synthetic cases. They cover public ingress, local reachability, association, separated permissions, tool allowlisting, downstream authorization, write approval, every documented capacity limit, logging, health, timeout, read-back mismatch and an accepted terminal. All eighteen pass. This tests the release contract, not OpenAI availability, MCP server correctness or business performance.
The terminal logic is intentionally small:
if (transportMissing || associationMissing) return "BLOCK";
if (toolAllowlistEmpty || downstreamAuthUnbound) return "BLOCK";
if (hasWrites && approval !== "per-effect") return "APPROVAL_REQUIRED";
if (documentedLimitExceeded || evidenceMissing) return "BLOCK";
if (!canaryAttempted) return "READY_FOR_CANARY";
if (timedOut || readbackMissing) return "UNCERTAIN";
if (readbackMismatch) return "DIVERGENT";
if (accepted && readbackMatches) return "OBSERVED";This is a policy skeleton. A real implementation should bind the decision to the current caller, tool, normalized arguments, target resource, environment and policy version. Re-evaluate when any of them changes.
The stop states matter more than the happy path:
BLOCKmeans a required plane is structurally absent or a documented protection is exceeded.APPROVAL_REQUIREDmeans a write proposal exists without an approval bound to that exact effect.READY_FOR_CANARYmeans preflight is complete but no production outcome has been observed.UNCERTAINmeans the client cannot prove the terminal state, including timeout or missing read-back.DIVERGENTmeans the authoritative system disagrees with the expected result.OBSERVEDmeans the bounded canary reached an accepted state and read-back matches.
Never retry UNCERTAIN blindly. A second write can duplicate an effect that completed after the original response path failed. Reconcile by an idempotency key or authoritative resource lookup first.
Deploy and recover the client as production infrastructure
OpenAI documents sidecar, separate Kubernetes deployment and virtual-machine service patterns. Choose from failure ownership, not convenience alone.
A sidecar couples the client closely to one MCP server revision. A separate deployment can serve a stable internal MCP endpoint and scale or restart independently. A virtual-machine service may fit an existing internal tool that cannot move yet. In every pattern:
- restrict outbound access to the documented OpenAI tunnel endpoints and the intended local MCP destination;
- scope the runtime key to tunnel use rather than tunnel administration;
- monitor
/healthz,/readyzand/metricsfrom the client host; - alert on disconnection, queue pressure, deadline exhaustion and repeated response-size failures;
- record which client revision and MCP server revision served each canary;
- practice key rotation, client restart, tunnel disassociation and downstream credential revocation separately.
The guide says requests fail until a disconnected client reconnects. A fail-closed transport is useful, but an operator still needs a recovery decision. Reads may be safe to retry. Writes need reconciliation first. A prolonged outage may require disabling the associated app route, not merely restarting the tunnel client.
OAuth is another boundary. OpenAI says discovery can travel through the tunnel, but the authorization server is not automatically tunneled. If an authorization flow must reach a private identity service, verify reachability from every participant in that flow. A working MCP endpoint with an unreachable authorization server is not a partial success. It is a blocked release.
Secure MCP Tunnel release checklist
Before a production canary, require an owner to sign off each line:
- The MCP server has no unintended public ingress.
- The tunnel client has only the outbound path and local reachability it needs.
- Platform organization and ChatGPT workspace associations are explicit.
- Runtime use permission is separate from tunnel administration.
- The application records the caller and policy context.
- The exposed tool set is an allowlist, not the server's entire catalog.
- Downstream credentials are audience-bound and least-privileged.
- Each write has an effect-specific approval or an explicit pre-authorized policy.
- Peak rate, minute rate, message size, queue depth and deadline budget fit beneath the documented protections.
- Application invocation evidence joins to tunnel configuration and downstream state.
- Authoritative read-back classifies success, uncertainty and divergence.
- Health, readiness and metrics are monitored.
- Disconnection, key rotation, disassociation and write recovery have named owners.
- The canary uses a reversible or safely refused business effect.
The resulting decision is honest and narrow: private transport approved for this bounded tool route. It is not “the private network is safe,” “MCP is secure,” or “the agent may act autonomously.”
Secure MCP Tunnel FAQ
Does OpenAI Secure MCP Tunnel make a private MCP server public?
No. OpenAI says the client opens an outbound HTTPS connection and forwards requests to a local stdio or HTTP MCP server, so the server does not need an inbound public endpoint. Public plugin distribution is a separate path that still requires stable public HTTPS.
Does tunnel association authorize every MCP tool?
No. Association determines which allowed Platform organizations and ChatGPT workspaces can discover and use the tunnel. Treat tool visibility, arguments, targets, downstream scopes and write approval as separate application and server controls.
What are the current Secure MCP Tunnel limits?
OpenAI currently documents 600 requests per minute, 10 requests per second sustained, a 10 MiB serialized request or response, a 120-second absolute deadline and 1,000 pending queued requests per tunnel. The guide says these are protections, not performance guarantees.
Do multiple tunnel clients increase the rate allowance?
No. OpenAI says multiple clients do not multiply the shared allowance. Use multiple clients for availability or deployment topology, then size demand against the same tunnel boundary.
Where should Secure MCP Tunnel tool calls be logged?
Join Platform tunnel metadata events with normal application-level invocation evidence and an authoritative downstream read-back. OpenAI says individual tunnel transport requests are not emitted as ChatGPT Compliance Platform app events through the tunnel path.








