Codex가 사내 MCP를 부른다, OpenAI 터널의 권한 경계
OpenAI Secure MCP Tunnel은 ChatGPT·Codex가 공개 엔드포인트 없이 사내 MCP 서버를 호출하게 만드는 운영 경계입니다.
- 무슨 일: OpenAI가
Secure MCP Tunnel문서와openai/tunnel-client저장소를 공개했습니다.- ChatGPT, Codex, Responses API, AgentKit이 같은 private MCP 서버를 호출하는 구조입니다.
- 작동 방식: 고객 네트워크의
tunnel-client가 OpenAI tunnel service로 outbound HTTPS long-poll을 유지합니다.- MCP 서버는 공개 listener나 inbound firewall rule 없이 내부 URL로 남습니다.
- 실무 영향: MCP 도입 검토가 모델 기능보다 키 권한, OAuth, 로그, 터널 수명 점검으로 이동합니다.
- 주의점: authorization server는 터널링되지 않으며, raw HTTP logging은 기본 비활성화 상태를 유지해야 합니다.
OpenAI가 개발자 문서에 Secure MCP Tunnels를 올리고, GitHub에 openai/tunnel-client 저장소를 공개했습니다. 문서의 대상은 ChatGPT connector 하나가 아닙니다. OpenAI는 ChatGPT, Codex, Responses API, AgentKit이 private MCP 서버를 호출하는 공통 경로로 이 터널을 설명합니다. 사내 도구를 AI 제품에 붙일 때 더 이상 "MCP 서버를 어디에 공개할 것인가"만 묻지 않고, 어떤 제품이 어떤 tunnel id와 runtime key로 내부 도구를 호출하는지 확인해야 합니다.
MCP가 개발팀 안으로 들어오면 첫 병목은 JSON-RPC 스키마가 아니라 네트워크입니다. Jira, GitHub Enterprise, 코드 검색, 배포 승인, 데이터 웨어하우스, 사내 문서 검색은 대부분 공개 인터넷에 그대로 열 수 없습니다. 기존에는 VPN, reverse proxy, Cloudflare Tunnel, Tailscale, ngrok, 직접 allowlist 같은 선택지가 섞였습니다. OpenAI의 새 흐름은 OpenAI 제품군 안에서 쓰는 MCP 호출을 outbound-only 터널로 좁히려는 시도입니다.
OpenAI의 architecture 문서는 구조를 비교적 노골적으로 적습니다. 고객 네트워크 안에 작은 agent인 tunnel-client를 실행하고, 이 프로세스가 OpenAI tunnel service로 outbound HTTPS 연결을 유지합니다. OpenAI 제품은 고객 내부 URL을 직접 알지 않고 OpenAI-hosted MCP tunnel URL을 호출합니다. 고객의 private MCP 서버 주소는 tunnel-client 설정 안에서만 쓰입니다.
OpenAI Secure MCP Tunnel 요청 흐름
/v1/mcp/{tunnel_id} 요청 수신
근거: openai/tunnel-client architecture.md의 request lifecycle과 trust boundaries.
요청 생명주기는 네 단계로 압축됩니다. 먼저 tunnel-client가 GET /v1/tunnel/{tunnel_id}/poll로 작업을 기다립니다. OpenAI 제품이 POST /v1/mcp/{tunnel_id}로 MCP JSON-RPC 요청을 보내면 tunnel service가 그 작업을 client에 전달합니다. client는 내부 MCP 서버로 요청을 넘기고, 결과를 POST /v1/tunnel/{tunnel_id}/response로 되돌립니다. streaming 요청에서는 중간 JSON-RPC notification이 SSE로 이어질 수 있고, final JSON-RPC response가 스트림을 닫습니다.
운영 관점에서 첫 변화는 "사내 MCP 서버를 공개하지 않는다"는 점입니다. OpenAI 문서는 MCP 서버에 inbound firewall rule이 필요 없고, 공개 listener도 필요 없다고 설명합니다. 내부 MCP URL은 client 설정에 남고, 외부에서 보이는 주소는 OpenAI tunnel service의 tunnel URL입니다. 이 구조는 사내 API를 곧바로 인터넷에 열던 방식보다 노출면을 줄이지만, OpenAI tunnel service가 control plane이 된다는 새 의존성도 만듭니다.
보안 기본값도 기사로 볼 만합니다. architecture 문서에는 tunnel path가 client의 control-plane API key를 요구하고, admin UI와 log endpoint는 기본적으로 loopback-only라고 적혀 있습니다. 원격 UI는 --allow-remote-ui를 켜야 하며, raw HTTP logging은 기본 비활성화입니다. MCP는 tool argument와 응답 안에 토큰, 고객 데이터, 내부 URL이 섞일 수 있으므로 raw 로그는 편한 디버그 기능보다 유출 경로에 가깝습니다.
OpenAI의 onboarding 문서는 키 분리를 구체적으로 요구합니다. CONTROL_PLANE_TUNNEL_ID는 Tunnels management나 admin 명령에서 만들고, CONTROL_PLANE_API_KEY는 runtime API key로 만듭니다. OPENAI_ADMIN_KEY는 tunnel 생성, 수정, 삭제 같은 관리 작업에만 쓰라고 되어 있습니다. runtime key 주체에는 Tunnels Read와 Use가 필요하고, tunnel을 만들거나 편집하는 사람에게는 Read와 Manage가 필요합니다. 하나의 sk-...를 모든 작업에 넣는 팀은 이 지점에서 배포 절차를 고쳐야 합니다.
| 검토 항목 | 문서가 말하는 기본값 | 운영팀 질문 |
|---|---|---|
| 네트워크 | client가 OpenAI로 outbound HTTPS 연결 | 프록시, CA bundle, egress allowlist를 누가 관리하는가 |
| 권한 | runtime key는 Read/Use, admin key는 관리 작업 | daemon용 key와 생성용 key가 분리됐는가 |
| MCP 서버 | HTTP, stdio, in-memory binding 지원 | 각 tool이 어떤 내부 리소스를 읽고 쓰는가 |
| 로그 | raw HTTP logging은 기본 비활성화 | 장애 대응 때 payload 로그를 켜는 승인 절차가 있는가 |
| OAuth | Authorization header와 discovery는 터널을 통과 | authorization server가 public 또는 client host에서 접근 가능한가 |
Codex와 연결되는 부분은 특히 민감합니다. 코딩 에이전트가 사내 MCP 서버를 호출하면 코드 검색, 빌드 로그, 이슈, 배포 권한이 같은 작업 루프 안에 들어옵니다. 터널이 outbound-only라고 해서 tool 권한이 자동으로 안전해지는 것은 아닙니다. MCP 서버가 "읽기 전용 코드 검색"인지, "PR 생성과 CI 재실행"까지 하는지, "배포 승인"까지 넘겨주는지에 따라 위험 등급이 달라집니다.
OpenAI가 ChatGPT와 Codex를 같은 문서에 넣은 점도 작지 않습니다. 소비자형 채팅 제품과 개발자용 에이전트가 같은 private MCP 연결 방식을 쓰면, 사내 도구는 제품별 플러그인이 아니라 조직 단위 리소스가 됩니다. 한 팀이 ChatGPT connector로 문서 검색을 붙이고, 다른 팀이 Codex로 코드베이스 도구를 붙이며, 백엔드 팀이 Responses API에서 같은 MCP 서버를 호출할 수 있습니다. 이때 tunnel id, runtime key, connector 설정, MCP server routing이 조직 운영 자산이 됩니다.
OAuth-protected MCP는 장점과 한계를 같이 드러냅니다. onboarding 문서는 Authorization header가 OpenAI tunnel service를 거쳐 MCP 서버로 전달되고, OAuth discovery GET도 client가 고객 네트워크에서 실행한다고 설명합니다. Protected Resource Metadata의 resource URL과 WWW-Authenticate 값은 OpenAI tunnel-service endpoint로 다시 쓰입니다. 이 덕분에 private MCP 서버를 숨긴 채 표준 OAuth 흐름을 유지할 수 있습니다.
다만 authorization server 자체는 터널링되지 않습니다. 문서는 authorization server가 public internet과 tunnel-client host 양쪽에서 모두 닿지 않으면 OAuth 흐름이 실패할 수 있다고 적습니다. 사내 IdP가 VPN 안에서만 열려 있고, OpenAI 제품의 OAuth redirection이 그 IdP를 볼 수 없다면 네트워크 설계가 다시 필요합니다. Secure MCP Tunnel은 MCP 서버를 숨기는 기술이지, 모든 인증 인프라를 대신 옮겨주는 제품이 아닙니다.
배포 방식은 세 가지가 제시됩니다. 첫째는 MCP 서버와 같은 Kubernetes Pod에 sidecar로 두는 방식입니다. 둘째는 별도 Kubernetes Deployment로 운영하면서 MCP Service를 Cluster DNS로 부르는 방식입니다. 셋째는 VM이나 host service에서 systemd로 돌리는 방식입니다. sidecar는 locality가 좋고 구성이 단순하지만 MCP 서버 업그레이드와 tunnel-client 업그레이드가 묶입니다. dedicated Deployment는 독립 업그레이드가 가능하지만 service discovery와 network policy를 따로 봐야 합니다. VM/systemd는 기존 사내 서버 운영 방식과 잘 맞지만 secret 배포와 프로세스 감시를 별도 체계에 얹어야 합니다.
성능과 안정성의 단서도 있습니다. architecture 문서는 request/response traffic에 backpressure가 있고, client가 처리 가능한 만큼만 queued work를 가져온다고 설명합니다. runtime component 설명에는 bounded in-memory queue, control-plane.max-inflight, mcp.max-concurrent-requests가 나옵니다. 사내 MCP 서버가 데이터베이스 검색이나 코드 인덱스처럼 느린 작업을 수행한다면, 이 숫자는 단순 튜닝값이 아니라 OpenAI 제품 쪽 대기 시간과 내부 시스템 부하를 동시에 정하는 제한선입니다.
개발자가 처음 만날 명령은 꽤 직접적입니다. onboarding 문서는 tunnel-client help quickstart와 tunnel-client help samples를 첫 경로로 제시하고, embedded MCP stub으로 daemon과 readiness check를 바로 띄우는 예시를 보여줍니다. Codex가 설치된 로컬 환경에서는 tunnel-client codex plugin install, tunnel-client runtimes list, tunnel-client codex status 같은 명령이 문서에 들어 있습니다.
tunnel-client help quickstart
tunnel-client run \
--embedded-mcp-stub \
--control-plane.tunnel-id tunnel_0123456789abcdef0123456789abcdef \
--health.listen-addr 127.0.0.1:0 \
--health.url-file /tmp/tunnel-client-health.url
curl -fsS "$(cat /tmp/tunnel-client-health.url)/readyz"
이 예시는 제품 방향을 잘 보여줍니다. OpenAI는 MCP 터널을 복잡한 네트워크 제품으로만 두지 않고, 로컬 daemon, admin UI, Codex plugin, runtime 목록, doctor 명령으로 개발자 도구화하고 있습니다. 사내 플랫폼팀 입장에서는 "MCP 서버를 만들었다"가 끝이 아니라 "어떤 개발자가 어떤 profile로 어떤 tunnel에 붙었는가"를 추적해야 합니다.
Anthropic과의 비교도 피하기 어렵습니다. Anthropic은 Claude Managed Agents에서 self-hosted sandbox와 MCP tunnels를 함께 공개하며, Claude가 내부 도구를 호출하는 경로를 outbound-only로 만들겠다고 했습니다. OpenAI의 이번 문서는 OpenAI 제품군 전체를 한 tunnel-client 모델로 묶는 데 초점을 둡니다. Claude 쪽은 Managed Agents와 Messages API의 실행 경계가 중심이고, OpenAI 쪽은 ChatGPT, Codex, Responses API, AgentKit이 같은 private MCP 서버를 공유할 수 있다는 점이 전면에 있습니다.
경쟁사는 AI 회사만이 아닙니다. Cloudflare Tunnel, Tailscale, ngrok 같은 네트워크 도구는 이미 private service를 public edge나 identity-aware proxy에 붙이는 길을 제공합니다. OpenAI Secure MCP Tunnel의 차이는 범용 터널이 아니라 MCP JSON-RPC와 OpenAI 제품 호출 경로에 맞춰진다는 점입니다. 이 특화는 설정을 줄여주지만, OpenAI control plane에 더 깊게 들어가는 선택입니다.
조직이 지금 점검할 부분은 세 가지입니다. 첫째, private MCP 서버마다 tool 권한을 쓰기 단위로 나눠야 합니다. 같은 tunnel 뒤에 "검색"과 "배포"가 같이 있으면 ChatGPT connector와 Codex 작업의 위험 등급이 섞입니다. 둘째, runtime key와 admin key를 분리하고 key 주체의 Read, Use, Manage 권한을 문서화해야 합니다. 셋째, raw payload log를 누가 언제 켤 수 있는지 사고 대응 절차에 넣어야 합니다.
제품팀에는 다른 질문이 생깁니다. ChatGPT에서 쓰는 사내 지식 검색, Codex에서 쓰는 코드 검색, API agent에서 쓰는 업무 자동화가 같은 MCP 표준으로 모이면 도구 재사용이 쉬워집니다. 반대로 tool description, permission prompt, audit event, rate limit, failure response가 제품별로 다르게 보이면 사용자는 같은 내부 도구를 서로 다른 위험으로 경험합니다. Secure MCP Tunnel은 연결 문제를 줄이지만, 도구의 사용자 경험과 승인 문구까지 자동으로 맞춰주지는 않습니다.
이번 공개는 화려한 모델 발표가 아닙니다. 그래도 AI 개발팀에는 더 오래 남을 수 있습니다. 모델이 내부 도구를 호출하는 순간, 에이전트 도입의 승인 문서는 "어떤 모델을 쓰는가"보다 "어떤 터널이 어떤 MCP 서버에 닿고, 어떤 키가 그 경로를 유지하며, 어떤 로그가 남는가"로 바뀝니다. OpenAI Secure MCP Tunnel은 그 질문을 OpenAI 플랫폼 안의 공식 배포 단위로 끌어온 업데이트입니다.