기술 가이드
OpenAI Tunnel로 사내 MCP를 ChatGPT 커넥터로 연결한 방법
ChatGPT에서 "최신 블로그 글 목록 보여줘"라고 물었을 때, 회사 블로그 데이터를 직접 읽고 답해주면 좋겠다는 필요가 생깁니다. MCP(Model Context Protocol)는 AI 앱이 외부 도구와 데이터를 표준화된 방식으로 주고받게 하는 프로토콜입니다.[1] 우리는 블로그와 뉴스 콘텐츠를 검색·조회·생성하는 15개 도구를 MCP 서버로 이미 배포해 두었어요. 남은 것은 ChatGPT가 이 서버를 찾아가는 길이었습니다.
이 글은 그 길을 여는 과정에서 실제로 막혔던 지점과 푼 방법을 순서대로 정리합니다. 순서는 이렇습니다. 터널 생성 → 사이트 키 발급 → 터널 클라이언트 실행 위치 결정 → ChatGPT 플러그인 등록 → 연결 확인.

왜 공개 URL을 그냥 쓰지 않았나
가장 단순한 방법은 ChatGPT 커넥터 모달에 공개 주소(https://data-sketchers.com/mcp)를 넣는 것이지만, 이 방법은 두 가지 문제를 만납니다.
첫째, 사내 도구를 인터넷에 그대로 노출하는 문제입니다. 키 인증이 있더라도 엔드포인트 자체가 공개 검색 대상에 들어가고, 공격 표면이 넓어져요. 둘째, 실제로 존재하는 차단 문제입니다. 사이트 앞단의 Cloudflare가 비브라우저 User-Agent(기본 Python·Go HTTP 클라이언트)의 요청을 봇으로 보고 403으로 막습니다. ChatGPT의 터널 클라이언트도 이 규칙의 대상이 되어, 로컬 PC에서 클라이언트를 돌리면 터널이 만들어지지 않았어요.
여기서 선택한 구조가 OpenAI Tunnel입니다. 터널은 배포 서버 안쪽에서 ChatGPT 쪽으로 아웃바운드 연결을 만들고, ChatGPT는 이 터널을 통해 사내 MCP에 접근합니다. 공개 URL 노출 없이, Cloudflare 앞단을 거치지 않고, 배포 서버에서 바로 백엔드로 들어가는 길이 생기는 거죠.

1단계: OpenAI 콘솔에서 터널을 만든다
OpenAI 콘솔(platform.openai.com)의 Tunnels 메뉴에서 Create tunnel을 누르고 이름을 붙이면 터널 ID(tunnel_로 시작하는 문자열)가 발급됩니다. 이 ID가 ChatGPT 커넥터와 터널 클라이언트를 잇는 열쇠예요.

2단계: MCP 서버 키를 발급받는다
우리 MCP 서버는 발급된 키(Bearer 토큰)가 붙은 요청만 받습니다. 관리자 엔드포인트에서 키를 발급하면 스코프(읽기·쓰기·미디어 권한)와 유효기간(365일), 요청 속도 제한이 함께 정해집니다. 키 값은 화면에 다시 표시되지 않으므로 발급 시점에 안전한 곳에 저장해야 해요. ChatGPT 쪽 설정이 아니라 터널 클라이언트가 이 키를 붙여서 보내는 구조라, ChatGPT 커넥터 모달의 인증은 "인증 없음"으로 두는 것이 맞습니다.

3단계: 터널 클라이언트는 배포 서버에서 돌린다
처음에는 로컬 Windows PC에서 OpenAI의 tunnel-client를 돌렸습니다. 연결은 만들어지는데 헬스체크가 계속 실패했고, 원인은 앞서 말한 Cloudflare의 봇 차단이었습니다. tunnel-client는 자체 User-Agent를 바꿀 방법이 없어서, 이 규칙을 우회할 수 없었어요.
해법은 실행 위치를 옮기는 것. tunnel-client를 배포 서버에서 systemd user service로 상시 구동하면 Cloudflare 앞단을 아예 거치지 않습니다. 서버 안에서는 백엔드 컨테이너의 사내 주소로 직접 붙고요. 설치 순서는 이렇습니다.
- GitHub releases에서 서버용 바이너리(linux amd64)를 받아
~/tunnel-client/bin/에 둔다. ~/.config/tunnel-client/<프로필이름>.yaml에 MCP 서버 주소와 인증 헤더(extra_headers: env:CONTENT_MCP_AUTHORIZATION)를 적는다.--profile인자에는 파일 경로가 아니라 이름만 들어간다는 점을 여기서 배웠어요.- 키·터널 ID를 담은 env 파일을 두고 systemd user service로 등록한다.
서비스 기동 후 127.0.0.1:9080/healthz가 ready를 반환하고, 로그에 mcp session initialized와 mcp channel route resolved가 찍히면 터널이 살아 있는 것입니다.
4단계: ChatGPT 플러그인으로 등록한다
ChatGPT 설정 → 플러그인 → 추가 → "사용자 지정 MCP 서버 추가" 모달에서 이름과 설명을 채우고, 연결 방식 토글을 터널로 바꾼 뒤 터널 ID를 붙여 넣습니다. 인증은 "인증 없음"을 선택해요. 이유는 2단계에서 말한 구조 때문입니다. 키는 터널 클라이언트가 붙이므로 ChatGPT가 별도 인증을 할 필요가 없어요.




등록이 끝나면 플러그인 목록에서 상태를 확인합니다. 초록 점과 "연결됨" 표시가 보이면 ChatGPT가 터널을 통해 사내 MCP에 닿을 수 있는 상태예요.

실제로 막혔던 지점 세 가지
Cloudflare 봇 차단은 터널 클라이언트의 실행 위치를 바꿔 해결했습니다. 로컬에서 사이트 앞단을 통과시키려는 시도(User-Agent 우회 포함)는 구조적으로 한계가 있어요. 프로필 경로 오류는 --profile에 파일 경로가 아니라 이름을 넣는 규칙으로 정리됐고, 환경변수 전달은 값에 공백이 있는 Bearer 헤더 때문에 셸 따옴표 문제가 여러 겹 겹쳤습니다. 결국 로컬에서 파일을 base64로 인코딩해 전송한 뒤 원격에서 디코딩하는 방식으로 안전하게 넘겼어요.
ChatGPT 모달 UI 자체도 만만치 않았습니다. 드롭다운 클릭이 모달을 닫아 버려서 여러 번 다시 열었고, 추천 칩을 잘못 클릭해 터널 ID가 다른 터널로 바뀌기도 했어요(화면 자동화로 입력하다 보면 이런 실수가 생깁니다). 터널 ID는 입력 후 화면을 확대해서 한 글자씩 확인하는 게 안전합니다.
연결되면 무엇이 달라지나
ChatGPT 채팅에서 "최신 블로그 글 목록 보여줘", "이 주제로 블로그 초안 만들어줘" 같은 요청이 사내 데이터를 기반으로 동작합니다. 15개 도구가 블로그·뉴스의 조회, 검색, 생성, 예약 확인을 커버하고요. 사내 도구가 인터넷에 노출되지 않으면서 ChatGPT의 자연어 인터페이스에 붙는다는 점이 이 구조의 실익입니다.
같은 구조는 다른 사내 MCP에도 그대로 적용할 수 있어요. 터널을 하나 더 만들고, 배포 서버에 서비스를 하나 더 등록하고, ChatGPT에 커넥터를 추가하면 됩니다. 내부 지식·문서 시스템을 ChatGPT에 연결할 때 같은 절차를 반복하면 됩니다.
참고자료
[1] Model Context Protocol · Introducing MCP
https://modelcontextprotocol.io/
MCP의 개념과 AI 앱이 도구·데이터를 연결하는 표준 방식
[2] OpenAI Docs · MCP
https://platform.openai.com/docs/mcp
ChatGPT 커넥터와 MCP 서버 연결 방식, 원격 서버 요구사항
자료 확인: 2026-10-10. 본문의 스크린샷 중 터널 ID가 보이는 부분은 흐림 처리했고, 서버 주소·키 값은 본문에 적지 않았습니다.