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개월 차 에 온다.
비슷한 글
에이전트 시대의 Eclipse 플러그인 — 작업 컨텍스트는 20년 전에도 문제였다
Mylyn 이 2000년대에 풀려던 문제와 지금 에이전트 컨텍스트 문제는 같습니다. 달라진 건 그 컨텍스트를 읽는 쪽에 사람만 있는 게 아니라는 점입니다.
김영상
에이전트 시대의 VS Code 확장 — 개발자는 에디터에서 무엇을 보는가
코드 작성 비용이 무너진 뒤 개발자의 시간은 판단과 승인으로 옮겨갔습니다. 그 일들이 왜 에디터 밖에 있으면 안 되는지, VS Code 확장을 만들며 내린 선택들.
이승백
이클립스는 그대로 쓰셔도 됩니다 — IDE 연동과 ITSM 연동에 대한 답
개발툴로 이클립스를 쓰는데 어떻게 연동되냐는 질문과, ITSM 과 연동되냐는 질문은 거의 항상 같이 나온다. 표준 Git 프로토콜이라는 답의 의미, 그리고 ITSM 연동 요구의 진짜 본질이 증적 체인이라는 이야기.
백재민