Secure MCP Tunnel 소개
Model Context Protocol(MCP)이 등장하면서 AI 시스템이 외부 도구와 데이터에 연결되는 일이 한결 쉬워졌습니다. 그런데 정작 팀이 가장 중요하게 여기는 MCP 서버는, 가장 외부에 노출하고 싶지 않은 서버인 경우가 많습니다. 사내 네트워크 안쪽, 사설 서비스 메시(service mesh), 개발자 노트북처럼 애초에 외부에서 들어오는 트래픽(inbound traffic)을 거부하도록 설계된 환경에서 돌아가는 서버들이 그렇습니다. 이런 서버를 ChatGPT나 Codex 같은 호스팅형 AI 제품에 연결하려면, 지금까지는 공개 엔드포인트를 새로 만들거나, 별도의 프록시 인프라를 띄우거나, 민감한 경로에 새로운 네트워크 운영 주체를 끼워 넣어야 했습니다.
OpenAI가 공개한 Secure MCP Tunnel 은 바로 이 딜레마, 즉 사설 서버를 사설로 유지하면서도 OpenAI 제품에 평범한 MCP 요청 경로를 제공한다 는 제약을 정면으로 풀기 위해 만들어졌습니다. 핵심 아이디어는 단순합니다. 고객이 자신의 사설 환경 안에서 작은 클라이언트를 직접 실행하고, 이 클라이언트가 OpenAI를 향해 바깥으로 나가는(outbound) HTTPS 연결을 먼저 맺습니다. 클라이언트는 (1) MCP 요청을 받아, (2) 승인된 로컬 서버로 전달하고, (3) 응답과 알림(notification)을 같은 연결을 통해 되돌려 보냅니다. OpenAI 제품 입장에서는 표준 MCP 요청과 응답 모델을 그대로 쓰지만, 그 뒤의 서버는 고객의 기존 네트워크 통제 안에 계속 머무릅니다.
이 글에서는 OpenAI가 이 구조를 어떤 엔지니어링 결정으로 풀어냈는지를 정리합니다. 사설 서버의 네트워크 경계를 보존하고, MCP의 스트리밍과 인증 흐름을 지원하며, 팀이 직접 들여다보고 운영할 수 있는 클라이언트를 제공하는 일을 동시에 해결해야 했기 때문입니다. 터널은 아웃바운드 전용 연결(outbound-only connectivity), 명시적 목적지 설정(explicit destination configuration), MCP 스트리밍 및 알림 호환성, 그리고 고객이 직접 실행하고 점검하는 클라이언트라는 네 가지 원칙 위에 설계되었습니다. 이 원칙들이 합쳐져, 사설 MCP 서버를 공개 서비스로 바꾸지 않고도 사설 도구와 데이터를 OpenAI 제품에 손쉽게 연결할 수 있게 됩니다.
MCP 자체가 처음이라면, 커뮤니티에 정리된 Model Context Protocol(MCP) 개념 및 이해를 위한 학습 자료를 먼저 읽어보시면 이 글의 맥락을 잡기 쉽습니다.
잘못된 기본값들: 기존 방식이 치르는 비용
사설 서비스를 외부에서 닿게 만드는 방법은 보통 세 가지입니다. 그리고 셋 다 나름의 대가를 치릅니다.
공개 엔드포인트(public endpoint) 를 여는 방식은 접근을 쉽게 만드는 대신 경계 자체를 약화시킵니다. 가장 빠르지만, 사설로 유지하고 싶었던 서버를 사실상 인터넷에 내놓는 셈입니다.
서드파티 터널(third-party tunnel) 공급자를 쓰면 사설 서버를 빠르게 닿게 만들 수 있지만, 연결 경로에 또 하나의 벤더가 추가됩니다. 엔터프라이즈 팀에게 이것은 사소한 문제가 아닙니다. 그 터널 공급자는 검토(review)하고, 계약하고, 운영하고, 신뢰해야 하는 대상이 되며, 결국 "사설 도구를 사설로 유지한다"는 목적의 시스템에서 보안 검토와 조달(procurement) 절차, 운영 런북(runbook), 그리고 메타데이터가 흐르는 표면(metadata surface)의 일부가 되어 버립니다.
VPN이나 네트워크 피어링(peering) 은 광범위한 네트워크 연결을 새로 만들어 도달성을 해결합니다. 그러나 좁은 MCP 통합 하나를 위해 동원하기에는 지나치게 큰 장치인 경우가 많습니다.
Secure MCP Tunnel은 더 좁고 집중된 접근을 택합니다. 고객에게 MCP 서버를 옮기라거나, 네트워크 경계를 넓히라거나, 또 다른 연결 벤더를 끼우라고 요구하는 대신, 사설 서버 바로 옆에 작고 들여다볼 수 있는 오픈소스 클라이언트 를 두고 그 클라이언트가 OpenAI로의 연결을 직접 시작하고 통제하게 합니다.
안에서 바깥으로 먼저 손을 내미는 터널: 요청의 한 살이
Secure MCP Tunnel의 핵심은 도달성의 방향을 뒤집는 것 입니다. 사설 쪽이 먼저 움직입니다. OpenAI 제품은 MCP 요청을 OpenAI가 호스팅하는 터널 엔드포인트로 보냅니다. 터널 서비스는 특정 터널을 위한 작업을 큐(queue)에 쌓아 두고, 사설 MCP 서버 옆에서 이미 돌고 있던 고객의 클라이언트가 아웃바운드 HTTPS로 그 작업을 가져갑니다. 클라이언트는 요청을 로컬에서 전달하고, 같은 경로를 통해 응답을 돌려보냅니다.
이 구조 덕분에 OpenAI 제품은 평범한 MCP 요청 경로를 그대로 쓰면서도, 사설 서버가 외부에서 들어오는 공개 트래픽을 받아들이거나 더 넓은 네트워크 연결을 새로 만들 필요가 사라집니다.
위 그림은 요청 한 건이 흐르는 다섯 단계를 보여줍니다.
- ChatGPT, Codex, Responses API 같은 OpenAI 제품이 MCP 요청을 OpenAI가 호스팅하는 터널 엔드포인트로 보냅니다.
- 터널 서비스가 해당 터널을 위한 MCP 작업을 큐에 적재합니다.
- 고객이 실행하는 터널 클라이언트가 아웃바운드 HTTPS 롱폴(long-poll)로 그 작업을 가져갑니다. 이때 오가는 것은 JSON-RPC 메시지입니다.
- 클라이언트가 사설 MCP 서버로 로컬 호출을 보냅니다. 사설 서버는 고객 환경 안에 그대로 머무릅니다.
- 응답은 들어온 것과 같은 터널을 거쳐 OpenAI 제품으로 되돌아갑니다. 사설 MCP 서버로 향하는 인바운드 경로는 끝까지 존재하지 않습니다.
Secure MCP Tunnel 더 알아보기
Secure MCP Tunnel 공식 가이드 - OpenAI 개발자 문서의 설정 가이드
tunnel-client GitHub 저장소 - 고객이 직접 실행하는 오픈소스 클라이언트
운영하기에 일부러 '지루한' 전송 계층을 골랐다: 롱폴링
OpenAI는 의도적으로 운영 관점에서 지루한(operationally boring) 전송 방식부터 시작했다고 밝혔습니다. 아웃바운드 HTTPS는 이미 엔터프라이즈 방화벽, 프록시 환경, 플랫폼 팀에게 익숙한 트래픽입니다. 새로운 포트를 열거나 인바운드 규칙을 손대지 않아도 되니, 보안 검토의 문턱이 낮습니다.
여기에 더해 롱폴링(long-polling) 은 자연스러운 백프레셔(backpressure) 지점을 만들어 줍니다. 터널 클라이언트는 자신이 처리할 수 있는 만큼의 작업만 요청하므로, 클라이언트 측 큐가 무한정 버퍼링으로 부풀어 오르는 대신 스스로 흐름을 조절하게 됩니다. 처리량을 넘는 일감이 한꺼번에 밀려들지 않도록, 받는 쪽이 속도를 정하는 구조입니다.
이 선택은 배포된 결과물의 모양을 단순하게 유지하는 효과도 있었습니다. (1) 제품이 MCP JSON-RPC를 OpenAI 호스팅 엔드포인트로 보내면, (2) 터널 서비스는 고객 클라이언트가 최종 응답을 돌려줄 때까지 그 요청을 붙들거나 스트리밍하고, (3) 스트리밍 결과가 필요할 때는 중간 단계의 서버 전송 이벤트(Server-Sent Events, SSE)를 전달합니다. 제품 입장에서는 평범한 MCP 요청과 응답 경로지만, MCP 서버와 그 주소는 사설로 남습니다.
실제 와이어 프로토콜에서 클라이언트는 다음 두 엔드포인트로 OpenAI 컨트롤 플레인(control plane)에 롱폴을 겁니다. 앞쪽은 처리할 작업을 가져오고, 뒤쪽은 처리한 결과를 돌려보내는 용도입니다.
GET /v1/tunnels/{tunnel_id}/poll
POST /v1/tunnels/{tunnel_id}/response
받아온 JSON-RPC 요청은 설정된 MCP 서버로 전달되는데, 이때 전송 방식은 Streamable HTTP, stdio, 또는 인메모리(in-memory) 트랜스포트 중 하나를 쓸 수 있습니다. 덕분에 표준 입출력으로 도는 로컬 MCP 서버부터 HTTP로 노출된 사내 서버까지 같은 클라이언트로 감쌀 수 있습니다.
네트워크 경계를 지우지 않고, 오히려 또렷하게 만들기
터널을 흔히 "경계를 뚫는 장치"로 오해하기 쉽지만, Secure MCP Tunnel의 설계 의도는 정반대입니다. 경계를 지우는 것이 아니라 명시적으로 드러내는 것 입니다. 고객이 실행하는 터널 클라이언트는 터널 컨트롤 플레인에 인증하고, 제품 쪽은 OpenAI가 호스팅하는 터널 엔드포인트를 사용하며, 사설 MCP 주소는 오직 고객 환경 안에서만 쓰입니다. 터널 접근 권한은 별도의 네트워크 경로와 별도의 접근 모델을 새로 만드는 대신, 고객의 기존 OpenAI 조직(organization)과 워크스페이스(workspace) 컨텍스트, 그리고 설정된 터널 신원(tunnel identity)에 묶입니다.
이 설계가 성립하려면 올바른 네트워크 방향을 고르는 것만으로는 부족합니다. 터널 클라이언트가 고객 환경 안에서 돌기 때문에, 그 동작은 들여다볼 수 있어야 하고 의도적으로 좁아야 합니다. 고객은 어떤 코드가 돌고 있는지, 어떤 아웃바운드 경로를 여는지, 어떤 사설 서비스에 닿도록 허용되어 있는지를 이해할 수 있어야 합니다. 위 그림처럼 OpenAI가 관리하는 쪽과 고객 환경 사이에는 분명한 네트워크 경계가 있고, 그 경계를 넘는 유일한 화살표는 고객 쪽에서 시작되는 아웃바운드 HTTPS 한 줄뿐입니다. MCP 서버를 위한 인바운드 방화벽 규칙이나 공개 리스너(listener)는 어디에도 필요하지 않습니다.
로컬에서 작업하듯 느껴지는 MCP 개발 경험
OpenAI는 터널 클라이언트가 네트워크 프로젝트가 아니라 개발자 도구처럼 느껴지길 원했습니다. 개발자가 노트북에서 MCP 서버를 띄우고, 그 옆에 터널 클라이언트를 실행한 뒤, 공개 엔드포인트를 만들거나 VPN, 방화벽 규칙, 피어링 변경을 기다리지 않고도 그 서버를 ChatGPT나 Codex에 곧장 연결할 수 있어야 한다는 것입니다.
중요한 것은 서버가 노트북에서 Kubernetes나 VM, 혹은 또 다른 고객 통제 환경으로 옮겨가도 같은 멘탈 모델이 그대로 유지된다 는 점입니다. 사설 MCP 서버 옆에 클라이언트를 두고, 클라이언트가 서버에 닿는지 확인한 뒤, 클라이언트가 OpenAI를 향한 경로를 시작하게 합니다. 헬스 체크(/healthz), 준비 상태 확인(/readyz), 로그, 그리고 로컬 관리 UI(/ui)는 이 흐름을 운영 프로젝트로 키우기 위한 것이 아니라, 무언가 잘 안 될 때 그 루프를 들여다볼 수 있게 하기 위해 존재합니다.
개발 경험은 Codex 안에서도 이어집니다. 터널 클라이언트에는 Codex 플러그인이 포함되어 있어, 모든 플래그와 프로파일, 컨트롤 플레인 세부 사항을 미리 익히게 하는 대신 설정을 안내형 워크플로우로 바꿔 줍니다. 여기서 중요한 것은 이 플러그인이 일회성 로컬 단축키를 만드는 데 그치지 않는다는 점입니다. 플러그인은 서버가 노트북에서 Kubernetes나 VM, 또는 다른 프로덕션 환경으로 옮겨가도 팀이 그대로 이어 쓸 수 있는 동일한 설정 형태(configuration shape) 를 만들어 냅니다. 더 흥미로운 점은 tunnel-client에 함께 묶인 어시스턴트 워크플로우입니다. 어시스턴트가 tunnel-client가 노출하는 로컬 터널 컨텍스트를 읽을 수 있기 때문에, 일반적인 설명 대신 실제 설정 을 근거로 문제를 추론하도록 도와줍니다. 어떤 프로파일이 활성화되어 있는지, 어떤 설정이 생성되었는지, 로컬 MCP 서버에 닿는지, 터널 클라이언트가 기동 과정 중 어디쯤 있는지를 바탕으로 판단하므로, 트러블슈팅이 별도의 에스컬레이션이 아니라 개발 루프의 일부가 됩니다.
아래는 GitHub 저장소가 안내하는 가장 짧은 시작 경로입니다. 로컬 stdio MCP 서버를 프로파일로 잡고, 설정을 점검한 뒤, 포그라운드로 클라이언트를 띄우는 흐름입니다.
tunnel-client help quickstart
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 개발 워크플로우 더 알아보기
Onboarding 가이드 - 로컬 또는 사설 MCP 서버에서 ChatGPT, Codex까지 가는 최단 경로
Architecture 문서 - 고객과 공유할 수 있는 네트워크 및 신뢰 경계 설명
오픈소스 클라이언트가 중요한 이유
터널 클라이언트는 고객이 직접 실행하는 오픈소스 소프트웨어로, 고객 경계 안쪽 사설 MCP 서버 바로 옆에 자리합니다. 이 점이 신뢰 모델에서 결정적입니다. 고객과 보안 검토자(security reviewer)는 자신의 환경 안에서 돌아가는 코드를 직접 들여다볼 수 있습니다. 클라이언트가 무엇을 하는지, 어떤 아웃바운드 연결을 여는지, MCP 요청을 로컬에서 어떻게 전달하는지, 어떤 설정이 그 도달 범위를 통제하는지를 모두 검토할 수 있습니다.
이런 투명성은 신뢰 모델을 아키텍처와 일치시킵니다. 터널 서비스는 OpenAI가 호스팅하지만, 고객 환경 안에서 도는 코드는 작고, 검토 가능하며, 고객의 통제 아래 있습니다. 클라이언트는 Go로 작성되어 있어 소스 체크아웃에서 go build ./...와 go test ./...로 직접 빌드하고 검증할 수 있고, 운영자가 볼 수 있는 데몬으로서 /healthz, /readyz, Prometheus 형식의 /metrics, 그리고 가벼운 관리 UI인 /ui를 제공합니다.
광범위한 네트워크 접근 없이 엔터프라이즈 인증을 지원하기
사설 MCP 서버가 익명의 내부 HTTP 엔드포인트인 경우는 드뭅니다. OAuth, 사설 인증 기관(private Certificate Authority), 아웃바운드 프록시, 또는 MCP 구간의 클라이언트 인증서에 의존하는 경우가 많습니다. 이런 서버를 지원하려면 엔터프라이즈 네트워크 가정을 예외가 아니라 터널 설계의 일부로 다뤄야 했습니다.
핵심 제약은 그래도 MCP 서버가 여전히 사설로 남는다 는 것입니다. MCP 서버를 위한 OAuth 디스커버리(discovery)는 터널 경로를 통해 이동하므로, 호스팅 제품은 MCP 서버를 공개 인터넷에 노출시키지 않고도 인증 방법을 학습할 수 있습니다. 실제로 클라이언트는 기동 시 MCP 서버로부터 OAuth 보호 리소스 메타데이터(Protected Resource Metadata, RFC 9728)를 가져와 진단에 활용합니다. 고객 쪽에서는 클라이언트를 로컬 환경에 맞게 설정할 수 있습니다. 커스텀 CA 번들, 프록시 설정, 그리고 MCP 구간의 상호 TLS(mTLS) 가 그 예입니다.
OpenAI는 여기서도 경계를 명시적으로 유지했습니다. 터널이 관련된 모든 엔터프라이즈 엔드포인트를 자동으로 OpenAI에서 닿게 만들지는 않습니다. 인가 서버(authorization server)가 사설이라면, 그 서버는 여전히 OAuth 흐름을 수행하는 구성 요소가 닿을 수 있어야 합니다. 이 경계는 의도된 것입니다. Secure MCP Tunnel은 설정된 사설 도구로 향하는 좁은 경로를 제공할 뿐, 범용 네트워크 다리(general-purpose network bridge)가 아닙니다.
MCP를 넘어서: Harpoon으로 사설 REST API까지
MCP는 모델 도구의 주된 형태이지만, 초기 알파 테스트에서 고객들과 함께 확인한 또 하나의 밀접한 문제가 있었습니다. 모든 사설 워크플로우가 이미 MCP 서버로 포장되어 있지는 않다는 점입니다. 어떤 중요한 워크플로우는 같은 방화벽 경계 뒤에 있는 기존 REST API 형태로 존재합니다. 만약 Secure MCP Tunnel이 MCP 도달성만 해결한다면, 팀은 이런 인접 사설 API를 위해 또다시 공개 엔드포인트나 터널 공급자, VPN 경로, 피어링 프로젝트를 따로 마련해야 할 것입니다.
Harpoon 은 이 좁은 연결 모델을 승인된 REST 타깃으로 확장합니다. 임의의 URL을 노출하는 대신, 고객은 터널 클라이언트에 라벨이 붙은 타깃(labeled target)을 등록합니다. OpenAI 쪽 호출자는 그 라벨을 Secure MCP Tunnel을 통해 호출하고, 실제 HTTP 요청은 여전히 사설 서비스 바로 옆 고객 환경 안에서 시작됩니다.
여기서도 라벨은 범용 네트워크 다리가 아닙니다. 호출은 고객이 소유한 타깃 등록, 허용된 메서드(allowed methods), 응답 크기 제한(response-size limit), 타임아웃(timeout), 리다이렉트 동작(redirect behavior), 그리고 터널 접근 통제에 의해 경계가 지어진 채로 유지됩니다. 덕분에 승인된 OpenAI 워크플로우는 고객이 인바운드 네트워크 접근을 열거나 OpenAI에 VPN 같은 신원을 주지 않고도, 고객 사설 API로 향하는 통제된 경로를 갖게 됩니다. 클라이언트 내부에서는 이 기능이 별도의 harpoon 채널로 라우팅되며, Harpoon 타깃이 등록되어 있을 때만 활성화됩니다.
정리하며: 사설성을 지키는 연결의 기본값
Secure MCP Tunnel이 던지는 메시지는 분명합니다. 사설 도구를 AI 제품에 연결하기 위해 그 도구를 공개 서비스로 바꿀 필요는 없다는 것입니다. 도달성의 방향을 뒤집어 사설 쪽이 먼저 아웃바운드로 손을 내밀게 하고, 그 경로를 작고 검토 가능한 오픈소스 클라이언트가 통제하게 함으로써, OpenAI는 공개 엔드포인트, 서드파티 터널, VPN이라는 기존의 "잘못된 기본값"을 피해 갑니다.
개발자 관점에서 이 설계가 매력적인 이유는 세 가지로 요약됩니다. 첫째, 노트북에서 Kubernetes까지 같은 흐름이 유지되어 로컬에서 검증한 설정을 그대로 프로덕션으로 가져갈 수 있습니다. 둘째, 클라이언트가 오픈소스이고 고객 통제 아래 있으므로 보안 검토가 아키텍처와 어긋나지 않습니다. 셋째, OAuth와 mTLS, 프록시 같은 엔터프라이즈 인증 가정을 예외가 아닌 설계의 일부로 다뤄, 현실의 사내 MCP 서버를 그대로 연결할 수 있습니다. Harpoon까지 더해지면서, 이 좁은 연결 모델은 MCP 서버뿐 아니라 같은 경계 뒤의 REST API로도 확장됩니다.
다가오는 MCP 스펙이 Stateless 전환을 예고하는 등 프로토콜 자체가 빠르게 진화하는 가운데, "사설 서버를 어떻게 안전하게 닿게 할 것인가"라는 질문은 앞으로 더 많은 팀이 마주할 주제가 될 것입니다. Secure MCP Tunnel은 그 질문에 대한 OpenAI의 한 가지 답이며, 클라이언트가 오픈소스인 만큼 다른 언어로 호환 클라이언트를 구현할 수 있도록 와이어 프로토콜 명세(docs/protocol.md)와 OpenAPI 계약(docs/openapi.json)까지 함께 공개되어 있습니다.
Making private MCP servers reachable without making them public 소개 블로그
Secure MCP Tunnel 가이드
tunnel-client GitHub 저장소
라이선스
tunnel-client는 Apache License 2.0으로 배포되고 있어, 연구 목적은 물론 상업적 용도로도 자유롭게 사용 및 수정이 가능합니다. 고객이 자신의 환경 안에서 코드를 직접 검토하고 빌드하여 운영하는 것을 전제로 하는 도구인 만큼, 소스가 열려 있다는 점이 신뢰 모델의 핵심입니다.
더 읽어보기
-
[Deep Research] Model Context Protocol(MCP) 개념 및 이해를 위한 학습 자료
-
다음 MCP 스펙 릴리즈(2026-07-28)의 주요 내용: Stateless 전환 및 공식 확장 도입 예정
-
OpenAI, 에이전트를 구축 / 배포 / 최적화할 수 있는 에이전트 구성 및 관리 플랫폼인 AgentKit 공개
-
MCP-Scan: MCP Server 및 도구들의 보안 문제를 진단하는 CLI 도구 (feat. Invariant Labs)
이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. ![]()
파이토치 한국 사용자 모임
이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일
로 보내드립니다! 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다. ![]()
아래
쪽에 좋아요
를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ ![]()



