codex
Lightweight coding agent that runs in your terminal
tunnel-client is the customer-run agent behind Secure MCP Tunnel. It connects a private or localhost MCP (Model Context Protocol) server to ChatGPT, Codex, the Responses API, and AgentKit through an OpenAI-hosted MCP tunnel endpoint, while keeping the MCP
$ npx -y skills add openai/tunnel-client --agent claude-code
Repo: openai/tunnel-client
What's inside
tunnel-client is the customer-run agent behind Secure MCP Tunnel. It connects
a private or localhost MCP (Model Context Protocol) server to ChatGPT, Codex,
the Responses API, and AgentKit through an OpenAI-hosted MCP tunnel endpoint,
while keeping the MCP server off the public internet.
Use it when:
/healthz, /readyz, /metrics,
and /ui before a connector or API call depends on it.If you searched for "secure MCP tunnel", "MCP tunnel ChatGPT", "connect local
MCP server to ChatGPT", "connect local MCP server to Codex", "localhost to
ChatGPT", or "Codex local MCP", start with tunnel-client help quickstart,
then read the onboarding guide below.
docs/onboarding.md.docs/architecture.md.docs/permissions.md.docs/deployment/overview.md.docs/troubleshooting.md.docs/protocol.md and use
docs/openapi.json. Optional client features use the
common X-Tunnel-Client-Capabilities header.--mcp.forward-trace-context to carry W3C trace context in MCP params._meta
over stdio and Streamable HTTP.examples/go-sdk-inmemory.With a runtime API key and tunnel ID, run the built-in server_info, echo,
and uppercase tools without a separate MCP server:
export CONTROL_PLANE_API_KEY="sk-..."
export CONTROL_PLANE_TUNNEL_ID="tunnel_0123456789abcdef0123456789abcdef"
tunnel-client run --embedded-stateless-mcp-stub --health.listen-addr 127.0.0.1:0
--embedded-stateless-mcp-stub uses stateless MCP handling even when a client
sends initialize and notifications/initialized. It issues no MCP session
ID, and these demo tools do not require MCP session affinity between processes.
OAuth and application state have separate requirements.
--embedded-mcp-stub keeps its existing compatibility behavior: legacy
initialization and session requests use stateful handling; self-contained
modern discovery and tool requests use stateless handling. Choose one embedded
mode per run. Both share the embedded listen-address, Unix-socket, server-name, and
server-version options; see embedded demo configuration
for defaults and target conflicts.
The module can run in the same process as a Go MCP server. The MCP server does
not need to bind a port or use stdio: give the server side of an in-memory MCP
transport pair to your server and the client side to tunnelclient.New.
go get github.com/openai/tunnel-client
import (
"context"
"github.com/modelcontextprotocol/go-sdk/mcp"
tunnelclient "github.com/openai/tunnel-client"
)
ctx := context.Background()
server := mcp.NewServer(&mcp.Implementation{Name: "my-server", Version: "1.0.0"}, nil)
serverTransport, tunnelTransport := mcp.NewInMemoryTransports()
go server.Run(ctx, serverTransport)
client, err := tunnelclient.New(tunnelclient.Config{
TunnelID: "tunnel_0123456789abcdef0123456789abcdef",
APIKey: apiKey,
}, tunnelTransport)
if err != nil {
return err
}
return client.Run(ctx)
The runnable Go SDK example registers an echo
tool and connects it to the OpenAI Tunnel control plane.
developers.openai.com/api/docs/guides/secure-mcp-tunnelsdocs/end-user-guide.mddocs/onboarding.mddocs/permissions.mddocs/architecture.mddocs/connectors.mddocs/protocol.mddocs/openapi.jsondocs/enterprise-customer-onboarding.mddocs/configuration.mddocs/deployment/overview.mddocs/deployment/cloudflared.mddocs/troubleshooting.mddocs/development.mdexamples/go-sdk-inmemorydocs/roadmap.mdOn macOS, Homebrew is the supported installation path. Directly downloaded
release ZIPs are not currently notarized and can be blocked by Gatekeeper. If
a manually downloaded archive is blocked, do not use xattr, spctl, or
Open Anyway to bypass the check; install from the official OpenAI tap
instead:
brew install openai/tools/tunnel-client
Verify the installed version, then start with the guided setup:
tunnel-client --version
tunnel-client help quickstart
The Formula installs the matching tunnel-client, bundled cloudflared,
and companion manifest together, while exposing only the tunnel-client
command. For Docker, Kubernetes, or VM deployments, see
docs/deployment/overview.md.
To generate the shareable guide output locally:
make end-user-guide-screenshots
make end-user-guide-html
make end-user-guide-slides
If you want the shortest supported path from a local or localhost MCP server to
ChatGPT or Codex, start with tunnel-client help quickstart. For Codex plugin
lifecycle work, use the native tunnel-client runtimes ... and
tunnel-client admin-profiles ... command trees surfaced by
tunnel-client help plugin.
Supervision choice:
tunnel-client run ... when you intentionally want a foreground daemon
attached to the current terminal.tunnel-client runtimes connect .... Do not use nohup or disown as the
tunnel-client supervision path.runtimes connect, check tunnel-client runtimes status <alias>
before reporting success. Only report success when status shows the managed
runtime running with health reported. Use --json when Codex needs the
explicit process_running, healthy, and ready fields.Use these exact setup pages during first use:
https://platform.openai.com/settings/organization/tunnelshttps://platform.openai.com/settings/organization/people/roleshttps://platform.openai.com/settings/organization/people/groupshttps://platform.openai.com/settings/organization/api-keyshttps://platform.openai.com/settings/organization/admin-keyshttps://chatgpt.com/#settings/ConnectorsWhich value comes from where:
CONTROL_PLANE_TUNNEL_ID: create or inspect it in Tunnels management, or via
tunnel-client admin tunnels create|list|get ... with OPENAI_ADMIN_KEY.CONTROL_PLANE_API_KEY: create it in Runtime API keys; this is the key used
by tunnel-client doctor and tunnel-client run.OPENAI_ADMIN_KEY: only for tunnel-client admin tunnels list|create|update|delete. Do not use the admin key for the long-lived
daemon.Required tunnel permissions:
CONTROL_PLANE_API_KEY need
Tunnels Read + Use.See docs/permissions.md for the group/role workflow
and screenshots.
Binary-first flow:
tunnel-client help quickstart
tunnel-client profiles samples list
tunnel-client profiles samples show sample_mcp_enterprise_proxy
tunnel-client init --sample sample_mcp_stdio_local --profile local-stdio --tunnel-id tunnel_0123456789abcdef0123456789abcdef --mcp-command "python /path/to/server.py"
tunnel-client doctor --profile local-stdio --explain
tunnel-client run --profile local-stdio
tunnel-client run --profile-file ./profiles/local-stdio.yaml
Stdio deployment limit: run only one active tunnel-client instance per
tunnel ID when using --mcp.command / MCP_COMMAND. Multiple active instances
sharing that tunnel ID are not supported, including overlap during a
restart. Each instance launches a separate MCP child, and initialization and
later requests can reach different children. Stop the old instance before
starting its replacement, or use distinct tunnel IDs for independent instances.
See stdio deployment limits.
Stdio initialization is checked automatically. Legacy calls require a successful
initialize exchange followed by notifications/initialized; premature calls
return mcp_initialization_required immediately. Self-contained MCP requests
using protocol version 2026-07-28 or later pass through without a handshake.
The caller owns initialization, including after child replacement. See
configuration for lifecycle behavior.
If you need the tunnel id or runtime/admin keys first, open the matching URL
above before running init. If your rollout has self-serve tunnel access,
create the tunnel yourself in Tunnels management or with
tunnel-client admin tunnels create, then export the returned id as
CONTROL_PLANE_TUNNEL_ID and a separate runtime key as
CONTROL_PLANE_API_KEY. Create or verify the connector from the ChatGPT
settings URL above only while tunnel-client run ... is healthy, and keep the
daemon running for connector discovery and every MCP call from ChatGPT.
The Platform Tunnels page download button is sourced from tunnel-service's gated tunnel metadata response. When a new public tunnel-client release becomes
Lightweight coding agent that runs in your terminal
Use Codex from inside Claude Code for code reviews or to delegate tasks to Codex. This plugin is for Claude Code users who want an easy way to start using Codex from the workflow they already have.
The OpenAI Agents SDK is a lightweight yet powerful framework for building multi-agent workflows. It is provider-agnostic, supporting the OpenAI Responses and Chat Completions APIs, as well as 100+ other LLMs. Looking for the JavaScript/TypeScript version?
FAQ
tunnel-client is a Claude Code plugin with 1 hand-picked skill for mcp servers work, indexed on Flowy. Install it with the command on its page. It includes tunnel-mcp. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it