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개월의 재작업 을 피할 수 있다.
비슷한 글
에이전틱 DevOps 12개월 후 — 첫 가설 중 무엇이 *맞았고* 무엇이 *틀렸나*
12개월 전 다음 10년의 DevOps는 에이전틱이다 의 가설들. 12개월의 데이터로 어느 가설이 맞고 어느 게 틀렸는지의 정직한 평가.
백재민
3 pillars 그 후 — 4 추가 신호의 *6개월 후* 운영 노트
3 pillars 가 더 이상 충분하지 않은 이유 발행 후 6개월. 4 추가 신호 (events / user journeys / deploy correlation / similarity) 가 운영에서 어떻게 작동했는지의 후속.
백재민
GitHub Actions vs 자체 호스팅 — *진짜 비용* 비교 (12개월 데이터)
GitHub Actions 가 *비싸 보임* 은 표면. 12개월 자체 호스팅 vs SaaS 비교 — 단순 *분당 비용* 이 아니라 *총 운영 비용* 으로.
백재민