MCP 서버를 직접 구현하면서 — 가이드에 없는 5가지
MCP 서버 구현의 *공식 가이드* 가 다루는 곳 + *실전에서 만난 5가지* — JSON-RPC 변환, 권한 분기, error semantics, lifecycle, 격리.
MCP 서버를 구현해 본 적 있다면, 공식 가이드는 툴 정의 → 서버 부팅 → 연결 검증 까지 잘 안내한다. 그 후 프로덕션 배포 까지의 5가지 가 가이드에 없다.
이 글은 우리가 부딪힌 5가지의 실측 노트.
1 — JSON-RPC 의 변환 함정
MCP 는 JSON-RPC 2.0 위에 박혀 있다. 가이드는 JSON-RPC 사용을 전제. 하지만 우리 내부 RPC 가 gRPC 였음. 변환 layer 가 필요했고, 그 layer 의 세부 행동 이 까다로움.
가장 자주 깨지는 패턴:
- streaming response — JSON-RPC 는 single response 가정. MCP 는 progress notification 으로 streaming 흉내. gRPC streaming 과 매핑 정확히 안 됨
- cancellation — 클라이언트가 cancel 하면 progress 중단 + cleanup. JSON-RPC native 지원 X — 별도 cancel notification
- binary 데이터 — JSON 안에서 base64 encode 필요. 큰 binary (이미지, 파일) 는 별도 transport 권장
2 — 권한 분기는 서버 단 아니라 툴 단
가이드는 서버 가 모든 클라이언트에 모든 툴 노출 가정. 실전에서는 *같은 서버 * 가 서로 다른 권한 클라이언트 에 부분적 툴 노출.
해결: 매 호출마다 (client, tool, args) 를 권한 평가. 우리 그래프 권한 모델이 그대로 적용. → 권한 모델을 그래프 위로
호출 수신 →
client identity 검증 →
tool 호출이 client 의 권한에 있는가 →
args 가 client 의 scope 안인가 →
실행이 분기를 서버 코드 안에 박지 않으면 모든 호출이 같은 권한 — 보안 위험.
3 — Error semantics — JSON-RPC 코드 + MCP 의미
JSON-RPC 표준 error code (-32600 ~ -32099) + MCP 가 정의한 추가 error 종류 + 우리 도메인 error.
함정 — JSON-RPC error 만 표준화돼 있고, MCP 의 도메인 error 는 어떻게 표현할지 모호.
우리 답:
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32000, // JSON-RPC server-defined error
"message": "Authorization failed",
"data": {
"type": "mcp.authorization.denied", // 우리 의미
"tool": "deploy.production",
"reason": "missing scope: prod.deploy",
"audit_id": "audit-xyz" // 감사 추적용
}
}
}data 안에 우리 도메인 error 의미 박음. 클라이언트가 이걸 사용해 사용자에게 정확한 메시지 표시.
4 — 서버 lifecycle
가이드 — initialize → use → terminate. 실전 — 연결이 자주 끊기고 다시 연결. 클라이언트는 상태 유지 가정, 서버는 stateless 가정. 충돌.
해결: 서버 측 세션 store 를 별도. 클라이언트의 reconnect 시 세션 ID 로 복원. 세션 안에 현재 도구 사용 권한 / 진행 중 작업 / 컨텍스트 캐시 박음.
세션 만료는 idle 30분 default. active 한 동안은 무한.
5 — 격리 — 한 클라이언트가 다른 클라이언트 영향 X
여러 클라이언트가 동시에 같은 서버 사용. 하나가 long-running tool 호출 중일 때, 다른 빠른 호출 이 block 안 되어야.
가이드 — 동시성 전혀 다루지 않음.
우리 답:
- 각 클라이언트의 호출을 별도 worker pool
- 한 클라이언트의 long-running 호출은 그 클라이언트의 다음 호출만 block
- 전역 자원 (DB connection, external API) 은 별도 rate limit 적용
이 격리 없이는 한 사용자의 무거운 요청이 전체 서비스 장애 로 확장.
5 가지 후 알게 된 것
위 5 가지를 모두 다루지 않은 MCP 서버는 PoC 환경 에서는 동작하지만, 프로덕션 배포 후 1~3개월 안에 사고가 난다. 사고 패턴은 우리가 본 것 그대로 — 권한 누수, error 해석 불가, 세션 손실, 격리 깨짐.
MCP 서버의 공식 가이드 는 시작하기 위한 가이드지 프로덕션을 위한 가이드가 아니다.
프로덕션 가기 전에
MCP 서버를 직접 구현하거나 MCP-기반 에이전트 인프라 를 짜는 팀이라면, 위 5가지 중 2~3개 의 답만 처음부터 명시적으로 박아도 3~6개월의 재작업 을 피할 수 있다. PoC 에서 돌아간다는 건 증명이 아니다 — 사고는 프로덕션 1~3개월 차 에 온다.
비슷한 글
기획자가 코드를 배포하면, 장애는 누가 책임질까
AI로 제품 담당자가 직접 코드를 만들고 여러 에이전트가 동시에 작업하는 조직에서, 운영에 나가는 변경을 누가 무엇으로 확인해야 하는지. NIST SSDF, SLSA provenance, Google SRE 포스트모템 문화를 근거로 작성자와 분리된 검증·승인·복구의 역할 설계를 정리했다.
백재민
에이전트 시대의 Eclipse 플러그인 — 작업 컨텍스트는 20년 전에도 문제였다
Mylyn 이 2000년대에 풀려던 문제와 지금 에이전트 컨텍스트 문제는 같습니다. 달라진 건 그 컨텍스트를 읽는 쪽에 사람만 있는 게 아니라는 점입니다.
김영상
에이전트 시대의 VS Code 확장 — 개발자는 에디터에서 무엇을 보는가
코드 작성 비용이 무너진 뒤 개발자의 시간은 판단과 승인으로 옮겨갔습니다. 그 일들이 왜 에디터 밖에 있으면 안 되는지, VS Code 확장을 만들며 내린 선택들.
이승백