OpenAI Secure MCP Tunnel: 사설 MCP 서버를 공개하지 않고 ChatGPT와 Codex에 연결하는 프로젝트

Secure MCP Tunnel 소개

Model Context Protocol(MCP)이 등장하면서 AI 시스템이 외부 도구나 데이터에 접근하는 일은 한결 쉬워졌습니다. 그런데 정작 기업이 가장 연결하고 싶어 하는 MCP 서버는, 역설적으로 가장 외부에 노출하고 싶지 않은 서버인 경우가 많습니다. 사내 네트워크 안쪽, 프라이빗 서비스 메시(private service mesh), 개발자의 노트북처럼 애초에 공개 인터넷에서 들어오는 트래픽(inbound public traffic)을 거부하도록 설계된 환경에서 도는 서버들이 그렇습니다. 이런 서버를 ChatGPTCodex 같은 호스팅형 AI 제품에 연결하려면, 지금까지는 공개 엔드포인트(public endpoint)를 새로 열거나, 별도의 프록시 인프라를 배포하거나, 민감한 경로에 새로운 네트워크 운영 주체를 끼워 넣어야 했습니다.

OpenAI가 공개한 Secure MCP Tunnel은 이 딜레마를 정면으로 다룹니다. 핵심 아이디어는 단순합니다. 고객이 자신의 프라이빗 환경 안에 작은 클라이언트 하나를 띄우면, 그 클라이언트가 OpenAI 쪽으로 아웃바운드 HTTPS(outbound HTTPS) 연결을 먼저 맺습니다. 이후 클라이언트는 (1) MCP 요청을 받아서, (2) 승인된 로컬 서버로 전달하고, (3) 응답과 알림(notification)을 같은 연결을 통해 되돌려 보냅니다. OpenAI 제품 입장에서는 평범한 MCP 요청/응답 흐름을 그대로 쓰지만, 실제 서버는 고객이 이미 갖고 있는 네트워크 통제 뒤에 그대로 남아 있게 됩니다.

이 글은 그런 구조를 "왜 이렇게 만들었는가"의 관점에서 풀어낸 OpenAI 개발자 블로그를 정리한 것입니다. 사설 서버를 공개 서비스로 바꾸지 않으면서도 안정적이고 안전하게 연결하려면 여러 엔지니어링 문제를 동시에 풀어야 했습니다. 서버의 프라이빗 네트워크 경계를 그대로 보존하고, MCP의 스트리밍(streaming)과 인증(authentication) 흐름을 지원하며, 팀이 직접 들여다보고 운영할 수 있는 클라이언트를 제공하는 것입니다. OpenAI는 이 터널을 아웃바운드 전용 연결, 명시적인 목적지 설정, MCP 스트리밍 및 알림 호환성, 그리고 고객이 직접 운영하며 코드를 검증할 수 있는 클라이언트라는 몇 가지 원칙 위에 설계했다고 밝힙니다. 이 원칙들이 합쳐져서, 사설 MCP 서버를 공개 서비스로 만들지 않고도 프라이빗 도구와 데이터를 손쉽게 OpenAI 제품에 연결할 수 있게 됩니다.

사설 서버를 외부에 연결하는 세 가지 방식과 그 한계

새로운 접근을 이해하려면 먼저 기존 방식이 왜 아쉬운지 짚어야 합니다. 오늘날 팀이 프라이빗 서비스를 외부에서 접근 가능하게 만드는 방법은 대체로 세 가지입니다. 공개 엔드포인트를 여는 것, 서드파티 터널(third-party tunnel)을 도입하는 것, 그리고 VPN이나 네트워크 피어링(peering)으로 망을 확장하는 것입니다. 각각은 편의를 주지만 그만큼 대가가 따릅니다.

공개 엔드포인트(Public Endpoint): 접근은 쉬워지지만 그 대가로 보안 경계 자체가 약해집니다. 원래 외부 트래픽을 거부하도록 설계했던 서버에 인바운드 통로를 뚫는 셈이기 때문입니다.


서드파티 터널(Third-party Tunnel): ngrok이나 Cloudflare Tunnel 같은 도구는 사설 서버를 빠르게 외부에서 닿게 해줍니다. 다만 이는 연결 경로에 검토하고 계약하고 운영하고 신뢰해야 할 벤더를 하나 더 추가하는 일이기도 합니다. 엔터프라이즈 팀에게 이건 사소한 문제가 아닙니다. 터널 제공자가 보안 검토, 구매 프로세스, 운영 런북(runbook), 그리고 "프라이빗 도구를 프라이빗하게 지키는 것"이 목적인 시스템의 메타데이터 노출 지점(metadata surface)에까지 얽혀 들어가기 때문입니다.


VPN과 네트워크 피어링(Network Peering): Tailscale 같은 메시 VPN이나 클라우드 VPC 피어링처럼 넓은 범위의 네트워크 연결을 만들어 접근성 문제를 해결합니다. 그러나 좁은 MCP 통합 하나를 위해 동원하기에는 지나치게 무거운 장치인 경우가 많습니다.

Secure MCP Tunnel은 여기에 더 좁고 집중된 답을 제시합니다. 고객에게 MCP 서버를 옮기라거나, 네트워크 경계를 넓히라거나, 또 다른 연결 벤더를 끼우라고 요구하는 대신, 작고 들여다볼 수 있는(inspectable) 오픈소스 클라이언트를 사설 서버 바로 옆에 두고 그 클라이언트가 OpenAI로 향하는 연결을 스스로 시작하고 통제하도록 합니다.

네 가지 접근을 한눈에 비교하면 다음과 같습니다.

방식 연결 방향 추가 벤더 네트워크 노출 범위
공개 엔드포인트 인바운드 허용 없음 서버 자체가 공개됨
서드파티 터널 아웃바운드 있음(터널 제공자) 좁음(그러나 벤더 경유)
VPN / 피어링 양방향 대체로 없음 넓음(망 전체 연결)
Secure MCP Tunnel 아웃바운드 전용 없음(OpenAI 호스팅) 좁음(설정된 사설 도구만)

연결의 방향을 뒤집다, 사설 쪽이 먼저 손을 내미는 구조

Secure MCP Tunnel의 핵심 발상은 접근성의 방향을 안팎으로 뒤집는 것입니다. 즉, 사설 쪽이 먼저 움직입니다(the private side makes the first move). 전체 흐름은 다음과 같습니다. OpenAI 제품이 MCP 요청을 OpenAI가 호스팅하는 터널 엔드포인트로 보냅니다. 터널 서비스는 특정 터널에 대한 작업을 큐(queue)에 쌓아 두고, 사설 MCP 서버 옆에서 이미 돌고 있던 고객 운영 클라이언트가 아웃바운드 HTTPS로 그 작업을 가져갑니다. 클라이언트는 요청을 로컬로 전달한 뒤, 같은 경로를 통해 응답을 되돌려 보냅니다.

위 그림이 그 생명주기를 그대로 보여줍니다. ChatGPT, Codex, Responses API 같은 OpenAI 제품이 ① MCP 요청을 OpenAI 호스팅 터널 엔드포인트로 보내면, ② 터널 서비스가 이를 큐에 넣고, ③ 고객 환경 안의 터널 클라이언트가 아웃바운드 HTTPS 롱 폴링(long-poll)으로 이를 집어 갑니다. ④ 클라이언트는 이를 사설 MCP 서버로 로컬 호출하고, ⑤ 응답은 같은 터널을 거쳐 돌아옵니다. 주목할 점은 그림 오른쪽의 "고객 보안 환경(Customer Secure Environment)"으로 향하는 인바운드 경로가 존재하지 않는다는 것입니다. 사설 서버는 외부의 공개 트래픽을 받아들이거나 더 넓은 네트워크 연결을 만들 필요 없이, OpenAI 제품에는 평범한 MCP 요청 경로를 제공합니다.

왜 굳이 "지루한" 롱 폴링으로 시작했나

OpenAI는 의도적으로 운영 관점에서 지루한(operationally boring) 전송 방식으로 출발했다고 설명합니다. 아웃바운드 HTTPS는 이미 엔터프라이즈 방화벽, 프록시 환경, 플랫폼 팀 모두에게 익숙한 방식입니다. 새로운 포트를 열거나 특별한 인바운드 규칙을 협상할 필요가 없다는 뜻입니다. 여기에 롱 폴링(long-polling) 을 얹으면, 터널 클라이언트가 자기가 처리할 수 있는 만큼의 작업만 요청하게 됩니다. 이는 클라이언트 쪽 큐에 자연스러운 백프레셔(backpressure) 지점을 만들어 주어, 무한정 버퍼가 쌓이는 상황을 막아 줍니다.

이 선택은 출시되는 시스템의 형태 자체를 이해하기 쉽게 만드는 효과도 있었습니다. 흐름을 단계로 정리하면 이렇습니다.

  1. 제품이 MCP JSON-RPC 요청을 OpenAI 호스팅 엔드포인트로 보냅니다.
  2. 터널 서비스는 고객 운영 클라이언트가 최종 응답을 돌려줄 때까지 그 요청을 보류하거나 스트리밍합니다.
  3. 스트리밍 결과가 필요한 경우, 터널은 중간 서버 전송 이벤트(Server-Sent Events, SSE)를 전달할 수 있습니다.

결과적으로 제품 입장에서는 평범한 MCP 요청/응답 경로가 되지만, MCP 서버와 그 주소는 여전히 프라이빗하게 남습니다. 요청, 응답, 그리고 중간 이벤트는 모두 OpenAI가 호스팅하는 터널 엔드포인트를 거쳐 중계됩니다. 화려한 실시간 프로토콜을 앞세우는 대신, 이미 검증된 웹 인프라 위에서 예측 가능하게 동작하는 쪽을 택한 셈입니다.

네트워크 경계를 지우지 않고 오히려 명시적으로 만들기

터널이라고 하면 흔히 "경계를 없애는 도구"로 오해하기 쉽습니다. OpenAI는 이 지점을 분명히 합니다. Secure MCP Tunnel은 네트워크 경계를 지우는 방법이 아니라, 그 경계를 명시적으로 만드는(make that boundary explicit) 방법입니다. 고객이 운영하는 터널 클라이언트는 터널 컨트롤 플레인(control plane)에 인증하고, 제품 쪽은 OpenAI 호스팅 터널 엔드포인트를 사용하며, 사설 MCP 주소는 오직 고객 환경 내부에서만 쓰입니다. 터널 접근 권한은 별도의 자체 접근 모델을 가진 새로운 네트워크 경로가 되는 대신, 고객이 이미 갖고 있는 OpenAI 조직 및 워크스페이스 컨텍스트와 설정된 터널 아이덴티티에 묶입니다.

그림에서 보듯 왼쪽의 "OpenAI 관리 영역(OpenAI-managed side)"과 오른쪽의 "고객 환경(Customer environment)"은 네트워크 경계로 뚜렷하게 나뉘어 있고, 둘을 잇는 유일한 화살표는 고객 쪽에서 시작되는 아웃바운드 HTTPS 하나뿐입니다. 사설 MCP 서버를 위한 인바운드 방화벽 규칙이나 공개 리스너(public listener)는 어디에도 없습니다.

이 설계가 성립하려면 올바른 네트워크 방향을 고르는 것만으로는 부족합니다. 터널 클라이언트가 고객 환경 안에서 돌기 때문에, 그 동작은 반드시 검증 가능하고(inspectable) 의도적으로 좁아야(intentionally narrow) 합니다. 고객은 어떤 코드가 돌고 있는지, 어떤 아웃바운드 경로를 여는지, 어떤 사설 서비스에 접근하도록 허용되어 있는지를 스스로 이해할 수 있어야 합니다.

노트북에서 프로덕션까지, 로컬처럼 느껴지는 개발 경험

OpenAI는 터널 클라이언트가 네트워크 프로젝트가 아니라 개발자 도구(developer tool)처럼 느껴지도록 만들고자 했습니다. 개발자가 노트북에서 MCP 서버를 돌리고, 그 옆에 터널 클라이언트를 띄운 다음, 공개 엔드포인트를 만들거나 VPN, 방화벽 규칙, 피어링 변경을 기다리지 않고도 그 서버를 ChatGPT나 Codex에 바로 연결할 수 있어야 한다는 것입니다.

핵심은 이 흐름이 서버가 노트북에서 쿠버네티스(Kubernetes), VM, 또는 다른 고객 통제 환경으로 옮겨 가더라도 그대로 유지된다는 점입니다. 위 그림처럼 노트북이든, 쿠버네티스 클러스터든, VM이나 사설 네트워크든, 멘탈 모델(mental model)은 동일합니다. 사설 MCP 서버 옆에 클라이언트를 두고, 클라이언트가 서버에 닿을 수 있는지 검증하고, 클라이언트가 OpenAI를 향한 경로를 시작하게 하는 것입니다. 헬스 체크(health check), 준비 상태(readiness), 로그, 로컬 관리 UI는 문제가 생겼을 때 이 루프를 들여다볼 수 있게 해주는 도구이지, 터널을 별도의 운영 프로젝트로 만들기 위한 것이 아닙니다.

개발자 경험은 Codex 자체 안에서도 이어집니다. 터널 클라이언트에는 Codex 플러그인이 포함되어 있어서, 개발자가 모든 터널 클라이언트 플래그와 프로필, 컨트롤 플레인 세부사항을 미리 익혀야 하는 대신 가이드형 워크플로우로 설정을 마칠 수 있습니다. 여기서 목표는 일회성 로컬 지름길을 만드는 것이 아닙니다. 이 플러그인은 서버가 노트북에서 쿠버네티스나 VM, 다른 프로덕션 환경으로 옮겨 갈 때 팀이 그대로 이어서 쓸 수 있는 동일한 형태의 설정을 만들어 냅니다.

같은 발상이 tunnel-client에 함께 패키징된 어시스턴트 워크플로우에도 나타납니다. 어시스턴트가 tunnel-client가 노출하는 로컬 터널 컨텍스트를 읽을 수 있기 때문에, 일반론적인 지침이 아니라 실제 설정을 기반으로 개발자와 함께 문제를 진단할 수 있습니다. 어떤 프로필이 활성화되어 있는지, 어떤 설정이 생성되었는지, 로컬 MCP 서버에 실제로 닿는지, 터널 클라이언트가 기동 과정 어디쯤에 있는지를 파악하는 식입니다. 덕분에 문제 해결이 별도의 에스컬레이션 절차가 아니라 개발 루프의 일부가 됩니다.

오픈소스 터널 클라이언트가 주는 신뢰

터널 클라이언트는 고객 경계 안쪽, 사설 MCP 서버 옆에 자리 잡는 오픈소스이자 고객이 직접 운영하는(customer-run) 소프트웨어입니다. 이는 고객과 보안 검토자에게 자신의 환경 안에서 돌아가는 코드를 직접 들여다볼 수 있는 길을 열어 줍니다. 클라이언트가 정확히 무엇을 하는지, 어떤 아웃바운드 연결을 여는지, MCP 요청을 로컬에서 어떻게 전달하는지, 어떤 설정이 그 접근 범위를 통제하는지를 모두 확인할 수 있습니다.

이러한 투명성은 신뢰 모델을 아키텍처와 일치시켜 줍니다. 터널 서비스는 OpenAI가 호스팅하지만, 고객 환경 안에서 도는 코드는 작고, 검토 가능하며, 고객의 통제 아래 있습니다. 보안 검토자 입장에서 "블랙박스 벤더를 신뢰해 달라"가 아니라 "직접 읽어 보고 판단하라"고 말할 수 있다는 점이, 프라이빗 도구를 다루는 시스템에서는 특히 중요한 차이입니다.

광범위한 네트워크 접근 없이 엔터프라이즈 인증까지

현실의 사설 MCP 서버는 익명으로 열려 있는 단순한 내부 HTTP 엔드포인트인 경우가 드뭅니다. OAuth, 사설 인증 기관(private Certificate Authority), 아웃바운드 프록시, 또는 MCP 홉(hop) 구간의 클라이언트 인증서(client certificate)에 의존하는 경우가 많습니다. 이런 서버를 지원한다는 것은, 엔터프라이즈 네트워크의 전제들을 예외 상황이 아니라 터널 설계의 일부로 다뤄야 한다는 뜻이었습니다.

여기서도 핵심 제약은 변하지 않습니다. MCP 서버는 여전히 프라이빗하게 남아야 합니다. MCP 서버에 대한 OAuth 디스커버리(discovery)는 터널 경로를 통해 오가므로, 호스팅 제품은 MCP 서버가 공개 인터넷에 리스닝할 필요 없이 인증 방법을 학습할 수 있습니다. 고객 쪽에서는 터널 클라이언트를 로컬 환경에 맞게 구성할 수 있습니다. 커스텀 CA 번들, 프록시 설정, 그리고 MCP 구간의 상호 TLS(mutual 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 요청은 여전히 고객 환경 안쪽, 사설 서비스 바로 옆에서 시작됩니다.

여기서도 중요한 제약은 라벨이 범용 네트워크 브리지가 아니라는 점입니다. 호출은 고객이 소유한 대상 등록, 허용된 메서드(method), 응답 크기 제한, 타임아웃, 리다이렉트(redirect) 동작, 그리고 터널 접근 제어에 의해 경계가 지어집니다. 이 덕분에 승인된 OpenAI 워크플로우는 고객이 인바운드 네트워크 접근을 열거나 OpenAI에 VPN에 준하는 아이덴티티를 주지 않고도, 고객의 사설 API로 향하는 통제된 경로를 갖게 됩니다.

정리하며

Secure MCP Tunnel이 던지는 메시지는 명료합니다. 사설 도구를 AI에 연결하기 위해 반드시 사설 도구를 공개할 필요는 없다는 것입니다. 연결의 방향을 뒤집어 사설 쪽이 먼저 아웃바운드 연결을 시작하게 하고, 아웃바운드 HTTPS 롱 폴링이라는 익숙하고 예측 가능한 전송 위에 MCP의 스트리밍과 인증 흐름을 얹으며, 고객이 직접 읽고 운영할 수 있는 오픈소스 클라이언트로 신뢰 모델을 아키텍처와 일치시키는 것이 그 방법입니다.

이는 MCP를 실무에 도입하려는 조직이 마주하는 현실적인 장벽, 즉 "가장 가치 있는 서버가 하필 가장 꺼내기 어려운 곳에 있다"는 문제를 정면으로 겨냥합니다. MCP를 비롯한 에이전트 프로토콜 생태계가 빠르게 넓어지는 지금, 프로토콜 자체의 표현력만큼이나 "그 프로토콜을 어떤 네트워크 경계 위에서 안전하게 운반할 것인가"라는 배관(plumbing)의 문제가 함께 중요해지고 있습니다. Secure MCP Tunnel은 그 배관을 벤더를 늘리지 않고, 경계를 넓히지 않으며, 코드를 감추지 않는 방식으로 풀어낸 하나의 사례입니다.

:scroll: Making private MCP servers reachable without making them public 소개 블로그

:books: Secure MCP Tunnel 공식 가이드

:github: tunnel-client GitHub 저장소

라이선스

Go로 작성된 tunnel-client는 Apache License 2.0으로 공개되어 있어, 연구 목적은 물론 상업적 용도로도 자유롭게 사용 및 수정이 가능합니다. 고객 환경에서 실제로 도는 코드를 직접 검토하고 필요에 맞게 고칠 수 있다는 점이 이 프로젝트가 강조하는 투명성의 근간이기도 합니다.

더 읽어보기




이 글은 GPT 모델로 정리한 글을 바탕으로 한 것으로, 원문의 내용 또는 의도와 다르게 정리된 내용이 있을 수 있습니다. 관심있는 내용이시라면 원문도 함께 참고해주세요! 읽으시면서 어색하거나 잘못된 내용을 발견하시면 덧글로 알려주시기를 부탁드립니다. :hugs:

:pytorch:파이토치 한국 사용자 모임:south_korea:이 정리한 이 글이 유용하셨나요? 회원으로 가입하시면 주요 글들을 이메일:love_letter:로 보내드립니다! 텔레그램(Telegram)이나 Slack/Discord/Teams/Dooray/GoogleChat 등으로도 새 글 알림을 받으실 수 있습니다. :smiley:

:wrapped_gift: 아래:down_right_arrow:쪽에 좋아요:+1:를 눌러주시면 새로운 소식들을 정리하고 공유하는데 힘이 됩니다~ :star_struck: