모델에게 능력을 주는 일은 곧 인터페이스를 설계하는 일이다
좋은 Tool은 좋은 API와 다르다 — 소비자가 사람이 아니라 모델이기 때문이다
Model Context Protocol — 모델과 외부 세계 사이의 표준 어댑터
| 관점 | MCP 이전 | MCP 이후 |
|---|---|---|
| 통합 방식 | 호스트마다 전용 플러그인 (N×M 문제) | 서버 1개 → 모든 호스트가 사용 (N+M) |
| 표준 | 제각각의 함수 호출 포맷 | JSON-RPC 2.0 기반 공통 규격 |
| 생태계 | 벤더 종속 | 2026년 들어 주요 코딩 에이전트가 폭넓게 채택, Linux Foundation 산하로 거버넌스 이관 |
| 역할 | "모델이 무엇을 아는가" | "모델이 무엇을 할 수 있는가" |
* 생태계 수치·채택 현황은 2026년 6월 기준 스냅샷입니다. 최신 현황은 modelcontextprotocol.io에서 확인하세요.
MCP 서버가 호스트에 제공하는 것은 결국 이 세 가지다
검색하기, 이슈 만들기, 쿼리 실행하기 — 모델이 결정하고 호출하는 능동적 행동이다. 입력 스키마(JSON Schema)와 설명을 가지며, 이 가이드 §4의 설계 원칙 대부분이 여기에 해당한다. 부작용이 있을 수 있으므로 annotations로 읽기 전용·파괴적 여부를 표시한다.
파일 내용, DB 레코드, 문서 — URI로 식별되는 읽기 전용 데이터다. Tool과의 핵심 차이는 부작용이 없고, 보통 호스트(앱)가 주도해 컨텍스트로 끌어온다는 점이다. "이 PDF를 컨텍스트에 넣어줘" 같은 흐름이 Resource다.
"이 코드 리뷰해줘", "릴리스 노트 만들어줘"처럼 인자를 받아 펼쳐지는 프롬프트 템플릿이다. 보통 사용자가 명시적으로 선택한다(슬래시 명령·메뉴). 자주 쓰는 작업을 서버가 검증된 형태로 제공해, 매번 프롬프트를 다시 쓰지 않게 한다.
메시지 규격, 전송 방식, 인증 — 만들기 전에 알아야 할 골격
호스트는 모델을 품은 앱(Claude, IDE). 각 서버 연결마다 클라이언트를 하나씩 띄워 1:1로 통신한다.
당신이 만드는 쪽. Tools·Resources·Prompts를 노출한다. 호스트가 무엇인지 몰라도 동작한다.
서버는 호스트에 독립적이다 — 한 번 만들면 프로토콜을 말하는 모든 호스트에서 재사용된다. 이게 MCP의 핵심 이득이다.
모든 메시지는 JSON-RPC 2.0 규격을 따른다. 전송 계층은 두 갈래다 — 로컬 프로세스는 stdio(표준 입출력), 원격 서버는 Streamable HTTP. 같은 메시지 규격을 쓰므로 서버 로직은 전송 방식과 분리해 작성한다.
원격 HTTP 서버는 OAuth 2.1 기반 인증을 표준으로 쓴다. 핵심은 최소 권한이다 — 토큰 스코프를 작업에 필요한 만큼만 발급하고, 비밀 키는 서버 쪽에만 둔다. 모델이 보는 도구 정의에 자격 증명이 새어 나가지 않게 한다.
소비자가 사람이 아니라 모델이라는 점이 모든 것을 바꾼다
search_orders·create_issue처럼 행동이 즉시 읽히는 이름을 쓴다. do_action·handle 같은 모호한 이름은 모델을 헷갈리게 한다. 이름은 모델이 도구를 고르는 첫 번째 신호다.
description은 사람용 주석이 아니라 모델에게 주는 지시문이다. "무엇을 하는가"뿐 아니라 "언제 적절하고, 언제는 다른 도구를 써야 하는가"를 적는다. 가장 ROI 높은 한 줄 투자다.
자유 텍스트 파라미터는 모델이 틀리기 쉽다. 가능한 값이 정해져 있으면 enum으로 고정하고, 필수값은 required로 못박는다. 파라미터가 많을수록 잘못 채울 확률이 올라가니, 꼭 필요한 것만 남긴다.
응답은 모델이 다시 파싱한다. 군더더기 없는 구조화된 결과를 돌려주고, 사람용 장식(HTML·과한 메타데이터)은 뺀다. 응답 한 번이 곧 컨텍스트 토큰이라는 점을 늘 의식한다.
스택 트레이스를 그대로 던지지 말 것. "주문 ID를 찾을 수 없음 — 형식은 ORD-XXXX입니다" 처럼 왜 실패했고 어떻게 고치는지를 자연어로 준다. 그래야 모델이 재시도로 자가 복구한다.
삭제·결제·외부 발송처럼 되돌리기 어려운 작업은 실행 전 사람 승인을 거치게 한다. annotations.destructiveHint로 표시하고, 호스트가 확인 단계를 띄울 수 있게 한다. 자동화의 편리함보다 안전이 먼저다.
도구 50개를 한꺼번에 던지면 모델이 엉뚱한 걸 고른다(컨텍스트 로트). 비슷한 기능은 하나로 묶고, 맥락에 따라 노출할 도구를 라우팅한다. "있는 기능 전부 노출"이 아니라 "지금 필요한 것만"이 원칙이다.
읽기 전용인지(readOnlyHint), 같은 호출을 반복해도 안전한지(idempotentHint)를 명시한다. 호스트와 모델이 재시도·병렬 호출을 안전하게 결정하는 근거가 된다.
10만 행을 그대로 반환하면 컨텍스트가 터지고 비용이 폭발한다. 기본 개수 제한과 커서 기반 페이지네이션을 두고, 모델이 필요하면 더 요청하게 한다.
도구가 가진 권한이 곧 사고 시 피해 범위다. 작업에 필요한 최소 스코프만 부여하고, API 키·토큰은 서버 내부에만 둔다. 모델이 보는 인터페이스에 자격 증명을 절대 노출하지 않는다.
대부분의 MCP 서버가 같은 곳에서 넘어진다
가장 흔한 낭비. 깃허브·슬랙·DB 등 주요 시스템은 공식·커뮤니티 서버가 대개 이미 있다.
기존 API 50개를 그대로 도구 50개로 만든다. 모델은 사람과 다르게 쓴다 — 도구가 너무 잘고 많아진다.
get_user+get_orders → get_customer_summary."주문 조회 API" 한 줄로 끝낸다. 모델은 언제 이 도구를 써야 할지 단서를 못 얻는다.
전체 테이블·전체 로그를 통째로 돌려준다. 컨텍스트가 터지고 토큰 비용이 폭증한다.
모델이 곧장 삭제·송금·메일 발송을 실행하게 둔다. 한 번의 오판이 돌이킬 수 없는 결과를 만든다.
"많이 줄수록 똑똑해지겠지"는 거꾸로다. 선택지가 많을수록 오선택이 늘고 비용도 늘어난다.
새 서버를 만들기 전에 거치는 3단계 판단
공식·커뮤니티 MCP 서버 레지스트리를 먼저 검색한다. 깃허브·슬랙·구글드라이브·Postgres 등은 대부분 이미 존재한다. 있으면 쓴다 — 자체 구현은 유지보수 부채다.
사내 시스템·자체 DB·도메인 로직처럼 공개 서버가 있을 수 없는 경우에만 직접 만든다. 공식 SDK(파이썬·타입스크립트 등)로 시작하고, §4의 설계 원칙을 체크리스트로 쓴다.
읽기 전용 도구로 먼저 출시해 모델이 잘 쓰는지 관찰한다. 쓰기·파괴적 작업은 승인 게이트를 붙여 점진적으로 연다. 처음부터 전권을 주지 않는다.