AI Catchup

OpenAI's Secure MCP Tunnel: Connect Private MCP Servers Over Outbound-Only HTTPS

By 9 min read

OpenAI's Secure MCP Tunnel connects private and on-prem MCP servers to ChatGPT, Codex, and the Responses API without opening inbound firewall ports. You need a tunnel_id, an API key with Tunnels Read plus Use, and -- separately -- ChatGPT developer-mode access. That permission split is the most common setup blocker.

OpenAI published a Secure MCP Tunnel guide that connects private and on-prem MCP servers to OpenAI products "without opening inbound firewall ports or exposing those servers to the public internet." The mechanism is a tunnel-client that makes outbound-only HTTPS connections: it "polls OpenAI for work, forwards MCP requests locally, and returns responses through the same tunnel."

This lands the same enterprise problem Anthropic addressed with MCP tunnels for Claude Managed Agents, and it pairs naturally with OpenAI's broader automation push around Codex hooks and programmatic access tokens. For where each vendor's agent runtime sits architecturally, our Codex CLI vs Claude Code vs Cursor comparison is the right anchor.

Key Takeaways

  • Outbound-only HTTPS, no inbound ports. The tunnel-client long-polls an OpenAI-hosted endpoint, forwards JSON-RPC requests to the local MCP server, and posts responses back through the same connection.
  • The private server stays internal. OpenAI's docs say the private MCP server address remains internal-only; OpenAI products talk to the OpenAI-hosted endpoint, not directly to your server.
  • API-key auth with scoped permissions. A runtime key needs Tunnels Read + Use; creating or editing a tunnel needs Tunnels Read + Manage.
  • Platform tunnel permissions and ChatGPT developer mode are separate grants. This is the single most common setup blocker: having one does not give you the other.
  • Works with stdio and HTTP MCP servers. Use --mcp-command for stdio servers or --mcp-server-url for HTTP servers.
  • ChatGPT, Codex, and the Responses API can all target a tunnel-backed MCP server per the docs.
  • A tunnel must be associated with the target workspace, not just a Platform organization, or it will not appear in ChatGPT.
  • Enterprise networking is first-class. The docs cite outbound proxies, custom CA bundles, control-plane client certificates, and MCP-side mTLS.

What the Secure MCP Tunnel Is

OpenAI's Secure MCP Tunnel connects private MCP servers to OpenAI products without exposing those servers to the public internet. Instead of opening an inbound firewall port so OpenAI can reach your server, you run a client inside your network that reaches out to OpenAI. Per the docs, the client "polls OpenAI for work, forwards MCP requests locally, and returns responses through the same tunnel." The private server address never leaves your perimeter.

The result is a connectivity model security teams can sign off on: there is no public endpoint to defend, and all traffic to OpenAI originates as an outbound HTTPS request from inside the network.

How the Tunnel Works

The flow OpenAI documents has five steps. First, you create and manage an OpenAI-hosted tunnel endpoint in Platform settings. Second, you run tunnel-client inside your network where it can reach the private MCP server. Third, you configure the client with the tunnel identity and the server address. Fourth, OpenAI products send MCP requests to the OpenAI-hosted endpoint. Fifth, the client long-polls for queued work, forwards JSON-RPC requests locally, and posts responses back.

The data path is request-response over a persistent outbound channel. Because the client initiates the connection, the only network rule you add is outbound HTTPS to api.openai.com:443 (the default) or mtls.api.openai.com:443 when control-plane mTLS is configured, both on /v1/tunnel/*. Streaming is not lost in the process: per the docs, when a connector asks for streamed results the tunnel path can forward intermediate server-sent events.

Prerequisites and Permissions

Per the docs, you need a tunnel_id from the Platform tunnel settings, a runtime API key carrying Tunnels Read and Use permissions, and a private MCP server reachable over stdio or HTTP. Tunnel-manager operations are separated out: creating or editing a tunnel uses credentials with Tunnels Read and Manage. The split keeps the credential that runs a tunnel distinct from the credential that creates or changes one.

Network-wise, the client needs outbound HTTPS to OpenAI and local reachability to the MCP server. Nothing inbound is required.

Developer Mode Is a Separate Permission

The docs are explicit that "Platform tunnel permissions and ChatGPT developer-mode access are separate." Tunnel roles apply to a Platform organization and are granted by an organization owner or RBAC administrator. ChatGPT developer mode is a workspace permission: on Enterprise and Edu a workspace admin grants it, and the user then enables it under Settings > Security and login. Holding a Tunnels role does not give you developer mode, and developer mode does not give you tunnel access. Budget for two separate approvals before you start.

Two further operational notes from the docs: tunnel permissions are organization-level rather than project-level, and a new role assignment can take up to 30 minutes to propagate.

Associating a Tunnel With Organizations and Workspaces

A single tunnel can be associated with more than one Platform organization or ChatGPT workspace, and the association list defines every OpenAI context allowed to find or use it. Per the docs, include the Platform organization that owns the tunnel, the ChatGPT workspace that should list it when creating apps, and any additional organization that Codex or the Responses API will call from. Reuse the same tunnel_id throughout: adding organizations or workspaces does not create a second tunnel or change the private MCP server endpoint.

The consequence worth knowing before you debug anything: a tunnel associated only with a personal Platform organization does not automatically appear in an Enterprise or Edu workspace.

The weekly AI Catchup

Get the week's AI coding news, distilled.

One email each week: the tools, releases, and workflows that matter for Claude Code, Codex, Cursor, and the agent stack.

Setup Commands

Get the binary first. The docs point to the download link inside Platform tunnel settings or the latest public release from the openai/tunnel-client repository, and they advise keeping your runbook pointed at the latest-release URL instead of hard-coding a specific release. If you already have a binary, tunnel-client help quickstart is the documented entry point.

The docs then walk through initializing and running the client. The stdio path looks like this:

export CONTROL_PLANE_API_KEY="sk-..."

tunnel-client init \
  --sample sample_mcp_stdio_local \
  --profile local-stdio \
  --tunnel-id tunnel_0123... \
  --mcp-command "python /path/to/server.py"

tunnel-client doctor --profile local-stdio --explain
tunnel-client run --profile local-stdio

For an HTTP MCP server, swap --mcp-command for --mcp-server-url. The doctor subcommand validates a profile before you run it, and --explain prints why each check passed or failed.

Deployment Patterns and Integration

OpenAI documents three deployment shapes: a Kubernetes sidecar (tunnel-client beside the MCP server in one Pod), a dedicated Kubernetes deployment (the tunnel runs separately from the server), and a VM or systemd service at the host level. The right one depends on how your MCP servers already run.

On the product side, ChatGPT connects from Settings > Plugins (or chatgpt.com/plugins): select the plus button to create a developer-mode app, then choose Tunnel under Connection. ChatGPT lists available tunnels, or you can paste a valid tunnel_id directly. Codex and Responses API flows target the tunnel-backed MCP server from their own supported surfaces. Endpoints are managed from Platform tunnel settings.

Keep tunnel-client run healthy while you create or test the app. App discovery and MCP tool calls both depend on the running client, so a client that has stopped polling looks like a broken connector rather than a stopped process.

Troubleshooting the Four Documented Failures

OpenAI's docs name four failure modes, and each has a specific cause rather than a general "check your config" answer.

"Tunnels access required" in Platform tunnel settings. Tunnel permissions are organization-level, not project-level. Select the intended Platform organization, then ask an organization owner or RBAC administrator to add you to a role or group with Read to view tunnels, or Read + Manage to create, edit, or delete them. Running tunnel-client or selecting a tunnel additionally requires Use. Allow up to 30 minutes for a new role assignment to propagate.

The tunnel is not visible in ChatGPT. Check that the tunnel includes the target ChatGPT workspace and not only a Platform organization, then check the operator's Tunnels Use permission. If an enterprise workspace cannot be linked automatically, the docs direct you to your OpenAI account team for a reviewed manual association override.

Connector discovery or tool calls fail. Confirm tunnel-client run is still running, then re-run tunnel-client doctor --profile <name> --explain. If the client is not connected, requests through the tunnel fail until it reconnects.

You can inspect a tunnel but cannot edit it. The operator has Tunnels Read but not Tunnels Manage.

Advanced: Allowlisted HTTP Callouts

Beyond MCP, the tunnel can carry narrowly scoped HTTP callouts into your network. tunnel-client embeds an MCP server called Harpoon that exposes configured HTTP targets by label and lets callers invoke them through the tunnel with bounded request and response limits. Use it to reach a small set of private REST endpoints without publishing them.

The docs are direct about the limits: Harpoon is not a general-purpose proxy. Callers cannot choose arbitrary hosts, and requests are restricted to the targets and methods the customer configures.

Security and Operations

The tunnel is built for enterprise network constraints. Per the docs, it supports outbound proxies, custom CA bundles, control-plane client certificates, and MCP-side mTLS. The private MCP server address remains internal-only throughout, and tunnel access follows the existing organization and workspace context instead of introducing a separate public ingress path.

For operations, the client exposes /healthz, /readyz, and /metrics endpoints plus a local admin UI at /ui showing whether the client is healthy, ready, and polling. The admin UI is loopback-only by default; the docs say to expose it remotely only when you intentionally need an operator network to reach it. Raw HTTP logging is disabled by default and support exports are redacted, which keeps request contents out of diagnostic bundles.

What the Tunnel Does and Does Not Log

Secure MCP Tunnel separates tunnel transport from app-level product logging, which matters if you are relying on compliance exports for evidence. Per the docs, tunnel control-plane auth, long-poll and response traffic, and individual tunnel transport requests are not emitted as ChatGPT Compliance Platform app events. Tunnel metadata changes surface through API Platform Audit logs as tunnel.created, tunnel.updated, and tunnel.deleted. Normal app-level compliance logging still applies on the app path, including app invocation logs and app auth lifecycle logs such as APP_AUTH_LOG when an app is linked or unlinked.

The OAuth Caveat

OAuth discovery can travel through the tunnel path, so an MCP server that requires OAuth can stay private, and the tunnel preserves the upstream authorization server metadata that browser-facing flows need. The authorization server itself is not automatically tunneled. If it is unreachable from both the public internet and the tunnel-client host, the OAuth flow still fails even when the MCP server is reachable. That asymmetry is worth checking before you conclude the tunnel is at fault.

When to Use It

Reach for the Secure MCP Tunnel when an MCP server holds data or capabilities that cannot be published to the public internet -- an internal ticketing system, a database gateway, a code-search service behind the VPN -- and you still want ChatGPT or Codex to use it. The trade for that reach is running and monitoring a client process inside your network, scoping its API key to Tunnels Use, and treating the key like any other production secret.

Sources

Keep building the workspace playbook

Frequently Asked Questions

What is OpenAI's Secure MCP Tunnel?

OpenAI's docs describe Secure MCP Tunnel as a way to connect private MCP servers to OpenAI products without opening inbound firewall ports or exposing the servers to the public internet. A tunnel-client makes outbound-only HTTPS connections, polls OpenAI for work, forwards MCP requests locally, and returns responses through the same tunnel.

How does the tunnel keep a private MCP server off the public internet?

Per the docs, the private MCP server address stays internal-only. The tunnel-client runs inside your network, authenticates to OpenAI with an API key, and makes outbound HTTPS to api.openai.com:443 (or mtls.api.openai.com:443 with mTLS). OpenAI products talk to an OpenAI-hosted endpoint, never directly to your server.

What permissions and prerequisites does the tunnel-client need?

OpenAI's docs list a tunnel_id from Platform tunnel settings, a runtime API key with Tunnels Read plus Use permissions, optional tunnel-manager credentials with Tunnels Read plus Manage, and a reachable private MCP server over stdio or HTTP. The client needs outbound HTTPS and local reachability to the MCP server.

Which OpenAI products can use a tunneled MCP server?

Per the docs, ChatGPT, Codex, and the Responses API can all call a tunnel-backed MCP server. In ChatGPT you connect it from Settings then Plugins, or chatgpt.com/plugins, by creating a developer-mode app and choosing Tunnel under Connection. Endpoints are managed at Platform tunnel settings.

Why does my tunnel not appear in ChatGPT?

The docs give two causes. The tunnel may be associated only with a Platform organization and not with the target ChatGPT workspace, or the person creating the app may lack Tunnels Use permission. A tunnel tied only to a personal organization will not surface in an Enterprise or Edu workspace.

Where do you download tunnel-client?

OpenAI's docs point to the download link inside Platform tunnel settings, or the latest public release of the openai/tunnel-client repository. The docs recommend pointing your runbook at the latest-release URL rather than hard-coding a specific release URL, so upgrades do not require an edit.

Do Secure MCP Tunnel requests show up in ChatGPT compliance logs?

Not the transport itself. Per the docs, tunnel control-plane auth and long-poll traffic are not emitted as ChatGPT Compliance Platform app events. Tunnel metadata changes appear in API Platform Audit logs as tunnel.created, tunnel.updated, and tunnel.deleted, and normal app-level logging still applies on the app path.

Get the weekly AI Catchup

Tools, practices, and what matters, in your inbox every week.