Private MCP 서버 연결 방식: 내부 도구를 공개하지 않고 AI에 붙이는 법
OpenAI 개발자 블로그의 “Making private MCP servers reachable without making them public”은 MCP를 운영하는 팀이 꼭 봐야 할 주제입니다. 많은 팀이 MCP 서버를 만들면서 첫 번째로 부딪히는 문제가 “내부 도구를 AI 제품에 연결하려면 서버를 인터넷에 열어야 하나”이기 때문입니다. 답은 단순하지 않습니다. 연결성은 필요하지만, 공개 노출은 피해야 합니다.
이 글은 private MCP server, MCP streaming, MCP authentication, internal tools for AI agent 같은 검색 의도를 가진 개발자를 위한 정리입니다. 목표는 MCP를 멋지게 소개하는 것이 아니라, 실제 사내 도구를 AI 에이전트에 붙일 때 어디서 사고가 나는지와 어떤 구조가 덜 위험한지를 잡는 것입니다.
MCP가 편해질수록 내부망 경계가 흔들립니다
MCP의 장점은 모델이 외부 도구를 표준 방식으로 발견하고 호출할 수 있다는 점입니다. 파일 검색, 티켓 조회, 배포 상태 확인, 문서 검색, SQL 조회 같은 기능을 tool로 노출하면 에이전트가 업무 흐름 안으로 들어올 수 있습니다.
문제는 이 도구들이 대개 내부 시스템이라는 점입니다. Jira, GitHub Enterprise, Datadog, 사내 관리자 API, 고객 DB 조회 도구는 모두 권한이 강합니다. MCP 서버를 단순히 public URL로 열면 인증, rate limit, 감사 로그, 네트워크 접근 제어를 모두 제대로 갖춰야 합니다. 작은 자동화 서버가 갑자기 회사 핵심 API의 관문이 됩니다.
private MCP 접근 방식의 핵심은 내부 네트워크 경계를 유지하면서도, AI 제품이 필요한 순간 안전하게 도구 호출을 중계하는 것입니다. 즉 “서버를 전 세계에 공개하지 않기”와 “에이전트가 필요한 도구를 쓸 수 있게 하기” 사이에서 균형을 잡아야 합니다.
공개 URL 하나로 해결하면 안 되는 이유
가장 쉬운 방법은 MCP 서버를 HTTPS로 배포하고 OAuth나 API key를 붙이는 것입니다. 하지만 이 구조는 몇 가지 리스크가 있습니다.
첫째, 공격 표면이 커집니다. MCP 서버가 외부에서 접근 가능해지면 인증 우회, SSRF, 입력 검증 실패, 과도한 도구 설명 노출 같은 문제가 생깁니다. 서버가 내부 API를 대신 호출한다면 피해 범위는 더 커집니다.
둘째, 권한이 뭉칩니다. “AI 도구 서버용 토큰” 하나에 읽기·쓰기·관리 권한이 모두 들어가면 에이전트가 실수하거나 악용될 때 피해를 나누기 어렵습니다.
셋째, 감사가 약해집니다. 누가 어떤 요청으로 어떤 도구를 호출했는지, 사람이 승인했는지, 모델이 자동으로 선택했는지, 외부 입력이 섞였는지 추적하지 못하면 운영 사고 후 원인을 찾기 어렵습니다.
넷째, 도구 설명 자체가 정보 유출이 됩니다. MCP는 도구 목록과 설명을 모델에게 보여줍니다. 여기에 내부 엔드포인트 이름, DB 테이블명, 운영 절차가 과하게 들어가면 공격자가 시스템 구조를 추론하는 재료가 됩니다.
안전한 private MCP 연결의 기본 구조
실무적으로는 네 가지 경계가 필요합니다.
첫째, 네트워크 경계입니다. MCP 서버는 가능하면 내부망에 두고, 외부 제품과는 relay, connector, tunnel, gateway 같은 통제된 경로로 연결합니다. 이 경로는 목적지와 도구 범위를 제한해야 합니다.
둘째, 인증 경계입니다. 사용자가 누구인지, 어떤 워크스페이스인지, 어떤 세션인지가 도구 호출까지 내려가야 합니다. “MCP 서버 공용 토큰” 하나로 모든 요청을 처리하면 사용자의 권한 차이를 반영할 수 없습니다.
셋째, 도구 경계입니다. 서버 전체를 붙이지 말고, AI가 필요한 함수만 좁게 공개합니다. 예를 들어 'runSql(query)'보다 'getIncidentSummary(incidentId)'가 안전합니다. 자유도가 높은 도구는 반드시 읽기 전용, 제한된 데이터셋, 비용 상한을 둬야 합니다.
넷째, 승인 경계입니다. 배포, 삭제, 권한 변경, 고객 데이터 수정, 외부 알림 발송은 모델이 바로 실행하지 못하게 합니다. 에이전트는 “제안”하고, 사용자가 승인하면 별도 실행 경로가 처리하는 구조가 좋습니다.
MCP streaming에서 봐야 할 운영 포인트
MCP streaming은 긴 작업이나 단계별 결과를 다룰 때 유용합니다. 에이전트가 로그를 읽고, 중간 분석을 보내고, 추가 도구를 호출하고, 최종 결과를 만드는 과정이 자연스러워집니다. 하지만 streaming은 관측이 없으면 디버깅이 어렵습니다.
각 stream event에 세션 ID, 사용자 ID, 도구 이름, 입력 요약, 상태, 지연시간을 붙여야 합니다. 실패한 이벤트도 저장해야 합니다. 실패는 공격이나 오용의 신호일 수 있습니다. 예를 들어 권한 없는 incidentId를 계속 조회하거나, 허용되지 않은 파일 경로를 바꾸며 호출하는 패턴은 탐지 대상입니다.
또 하나 중요한 점은 부분 결과 처리입니다. 모델이 중간 결과를 보고 다음 도구를 호출한다면, 잘못된 중간 결과가 다음 행동을 오염시킬 수 있습니다. 외부 문서나 티켓 본문에서 읽은 텍스트는 신뢰할 수 없는 입력으로 표시하고, 도구 실행 정책은 모델 출력이 아니라 서버 정책으로 결정해야 합니다.
도구 설명은 짧고 입력은 좁아야 합니다
좋은 MCP 도구는 이름만 봐도 용도가 명확하고, 입력 스키마가 좁습니다. 나쁜 도구는 “어떤 API든 호출 가능”, “임의 SQL 실행”, “임의 파일 읽기”처럼 범용성이 과합니다. 범용 도구는 개발 속도는 빠르지만 보안 사고의 반경도 큽니다.
예를 들어 장애 대응 에이전트라면 다음처럼 설계할 수 있습니다.
- 'searchIncidents(query, since)'는 최근 장애 목록만 검색합니다.
- 'getIncidentTimeline(incidentId)'는 특정 장애 타임라인만 반환합니다.
- 'getServiceDeployments(serviceName, range)'는 배포 이력만 읽습니다.
- 'proposeRollback(incidentId, deploymentId)'는 실행하지 않고 제안만 만듭니다.
이 구조에서는 에이전트가 충분히 일할 수 있지만, 임의 시스템을 건드리기는 어렵습니다. “적당히 똑똑한 도구”보다 “좁고 예측 가능한 도구”가 운영에는 더 낫습니다.
실행 체크리스트
- MCP 서버를 public URL로 바로 열기 전에 private 연결 경로를 검토했다.
- 사용자, 워크스페이스, 세션 권한이 도구 호출까지 전달된다.
- 공용 admin token 하나로 모든 MCP 호출을 처리하지 않는다.
- 도구 이름과 설명에서 내부 구조를 과하게 노출하지 않는다.
- 임의 SQL, 임의 URL, 임의 파일 경로를 받는 도구는 기본 금지한다.
- streaming event에는 세션, 도구, 상태, 지연시간, 실패 이유를 남긴다.
- 외부 문서나 티켓 본문은 신뢰할 수 없는 입력으로 취급한다.
- 쓰기 작업은 모델 호출 경로와 실제 실행 경로를 분리하고 사람 승인을 둔다.
출처: OpenAI Developers Blog, “Making private MCP servers reachable without making them public”