MCP 서버를 처음 만드는 팀이 범하는 실수는 대부분 비슷하다. API를 그대로 툴로 래핑하고, 읽기와 쓰기를 구분하지 않으며, 모든 호출자에게 동일한 툴 목록을 노출한다. 세 기사—GoodBarber의 프로덕션 MCP 구축 사례, vellum MCP의 Tool vs Resource 철학, 그리고 $0 비용 자율 운영 에이전트 아키텍처—를 함께 읽으면, 이 세 가지 실수가 왜 구조적으로 위험한지 그리고 어떻게 설계 단계에서 차단할 수 있는지가 선명하게 드러난다.
실수 1: Resource를 Tool로 만드는 것
MCP 프로토콜에는 두 개의 명확히 다른 원시 타입이 있다. Tool은 행동을 위한 것이고, Resource는 읽기를 위한 것이다. 그런데 대부분의 서버가 읽기 작업까지 전부 Tool로 노출한다. vellum MCP의 사례가 이 문제를 정확히 짚는다. Tool 정의는 이름·설명·JSON 스키마 전체가 매 요청마다 모델의 컨텍스트 윈도우에 올라간다. 쓰기 작업만 처리하는 턴에도 읽기용 Tool 4개가 조용히 컨텍스트를 잠식하고 있는 셈이다.
반면 Resource로 노출된 문서는 vellum://note/projects/launch.md 같은 안정적인 URI로 참조된다. 에이전트가 Tool 호출 없이 이름으로 직접 문서를 붙일 수 있고, 클라이언트는 해당 URI를 구독해 변경 시점에만 알림을 받는다. 결론은 단순하다. 읽기는 Resource, 행동은 Tool. 이 선을 흐리는 순간부터 컨텍스트 낭비가 시작된다.
실수 2: 쓰기 성공을 검증하지 않는 것
GoodBarber의 프로덕션 서버가 가장 강하게 방어한 실패 모드는 '환각된 성공(hallucinated success)'이다. 에이전트가 쓰기 작업을 실행하고 성공했다고 보고하지만 실제 상태가 다른 경우다. 이를 막기 위해 모든 쓰기 응답에 _mcp_policy.verification_required: true를 반환하도록 설계했다. 에이전트는 반드시 방금 수정한 객체를 다시 읽어(read-back) 결과를 확인해야 다음 단계로 넘어갈 수 있다.
이 패턴은 토큰과 레이턴시를 더 쓰는 트레이드오프를 의도적으로 감수한다. GoodBarber 팀의 표현을 빌리자면 "verified writes beat fast fiction." 150개 툴이 프로덕션에서 운영되는 서버에서 이 원칙이 깨지면, 에이전트가 "상품을 등록했습니다"라고 말했지만 실제 카탈로그에는 없는 상황이 된다. 작업 파이프라인 전체가 잘못된 전제 위에서 돌아가는 것이다.
실수 3: 모든 호출자에게 같은 툴을 노출하는 것
$0 비용 자율 운영 에이전트 아키텍처 사례는 세 번째 실수를 가장 선명하게 보여준다. 이 아키텍처는 하나의 MCP 서버 위에 Claude(대화형), 로컬 모델 기반 Telegram 봇, 워치독, 야간 감사 에이전트 등 네 개의 클라이언트가 연결된다. 동일한 서버지만 클라이언트마다 완전히 다른 툴 표면(tool surface)이 노출된다.
- Telegram 봇 → 읽기 전용 툴만
- 워치독 → 읽기 + 제한된 쓰기 (패치 제안)
- 야간 감사 → 읽기 + 이슈 생성만
- Claude → 전체 (사람이 루프에 있을 때)
이 설계의 핵심은 "모델에게 쓰지 말라고 지시하는 것"이 아니라 "툴 목록 자체에 쓰기가 없는 것" 이라는 점이다. 프롬프트 레벨의 제약은 충분히 신뢰할 수 없다. 보안 경계는 서버 사이드에서, 호출자별 최소 권한 원칙으로 구현해야 한다.
세 원칙이 가리키는 하나의 설계 철학
세 사례를 관통하는 메시지는 같다. MCP 서버의 안전성과 효율은 모델의 지능에 기대면 안 된다. GoodBarber는 기능 게이팅(feature gating)으로 존재하지 않는 툴은 목록에서 아예 제거한다. vellum MCP는 읽기/쓰기 분리로 컨텍스트 낭비를 구조적으로 막는다. $0 에이전트 아키텍처는 툴 검증을 유니코드 정규화(NFKC)와 네임스페이스 차단까지 내려서, 로컬 모델이 툴 이름을 환각해도 서버 레벨에서 차단한다.
세 사례 모두 동일한 결론에 도달한다. 로컬 모델은 틀려도 된다. 프론티어 모델도 환각을 낸다. 따라서 펜스(fence)는 모델이 아니라 서버에 있어야 한다. 이 원칙을 설계 초반에 내재화하지 않으면, MCP 서버는 에이전트 자동화 도구가 아니라 에이전트가 저지른 실수를 뒤늦게 수습하는 구조가 된다.
팀 리드가 지금 당장 적용할 체크리스트
지금 팀에서 MCP 서버를 설계하고 있다면, 아래 세 가지를 구조 설계 단계에서 확인해야 한다.
- 읽기 작업이 Tool로 구현돼 있는가? → Resource URI로 전환하고 컨텍스트 윈도우 낭비를 측정하라.
- 모든 쓰기 작업에 read-back 검증이 있는가? →
verification_required패턴을 서버 응답 스펙에 명시적으로 넣어라. - 호출자 유형마다 다른 툴 표면을 설계했는가? → 클라이언트별 최소 권한 목록을 서버 사이드에서 강제하라.
이 체크리스트는 새로운 기능을 추가하는 것이 아니다. 설계 단계에서 "아니오"라고 말하는 결정들이다. GoodBarber의 150개 툴 운영, vellum MCP의 24MB 단일 컨테이너, $0 자율 운영 에이전트—세 사례 모두 명시적으로 범위를 좁히고, 경계를 코드가 아닌 구조로 만들었기에 프로덕션에서 버텼다. AI 에이전트가 점점 더 많은 시스템에 손을 뻗는 시대에, MCP 서버 설계의 기준선을 지금 팀 내에서 합의해두지 않으면 그 비용은 나중에 훨씬 비싸게 돌아온다.