MCP (Model Context Protocol) 실전
LLM 앱에 외부 툴·데이터를 붙이는 표준 프로토콜. "서버를 직접 만들까, 그냥 API 에 툴을 인라인 정의할까"를 정할 때, 그리고 붙인 서버의 신뢰 경계를 따질 때 연다.
신선도 주의. 현행 stable 스펙 리비전은
2025-11-25(verified 2026-07). 차기 판2026-07-28은 오늘 기준 RC 단계이며 최종 확정 전이다(RC 게시일인지 최종일인지 자료 간 혼선 — 재확인 필요). 리비전은 날짜 문자열로 식별한다. 계보:2024-11-05→2025-03-26→2025-06-18→2025-11-25.
아키텍처 — 무엇이 무엇인가
(Claude 앱 · IDE) ⇄
JSON-RPC 2.0 메시지 기반이고 설계 영감은 Language Server Protocol(LSP)이다. 역할이 셋인데 흔히 헷갈린다.
| 역할 | 정체 | 관계 |
|---|---|---|
| Host | 연결을 개시하는 LLM 애플리케이션 (Claude Code, IDE, 챗) | 여러 Client 를 품는다 |
| Client | Host 안의 커넥터 | 서버 1개당 Client 1개 (1:1) |
| Server | 컨텍스트·기능을 제공하는 서비스 | Host 밖의 별도 프로세스/원격 |
2025-11-25 base protocol 은 stateful 연결(capability negotiation 포함)이다. 차기 2026-07-28 판은 stateless 코어로 뒤집혀 initialize 핸드셰이크와 Mcp-Session-Id 헤더를 없앨 예정이다 — 로드밸런서 뒤 무상태 운영을 노린 변경.
4가지(실은 6가지) 원시요소(primitive)
"툴/리소스/프롬프트/샘플링" 4개로 자주 요약하지만, 제공 방향이 서버 쪽과 클라이언트 쪽으로 갈린다.
| Primitive | 제공 방향 | 무엇 |
|---|---|---|
| Tools | 서버→클라 | 모델이 실행하는 함수 (부수효과 있음) |
| Resources | 서버→클라 | 컨텍스트·데이터 (읽기, 모델/사용자가 참조) |
| Prompts | 서버→클라 | 템플릿화된 메시지·워크플로 (사용자가 선택) |
| Sampling | 클라→서버 | 서버가 개시하는 재귀적 LLM 호출 |
| Roots | 클라→서버 | 서버가 동작할 URI·파일시스템 경계 |
| Elicitation | 클라→서버 | 서버가 사용자에게 추가 정보 요청 |
차기 판에서 Roots·Sampling·Logging 은 deprecated 로 표시될 예정이다(주석만, 메서드는 계속 동작). 새 서버에서 이 셋에 깊이 의존하는 건 지금부터 피하는 게 안전하다(재확인 필요).
트랜스포트 선택표
표준 트랜스포트는 stdio 와 Streamable HTTP 둘뿐이다. 옛 HTTP+SSE(2024-11-05)는 deprecated — SSE 는 이제 Streamable HTTP 내부의 선택적 스트리밍 메커니즘으로 흡수됐다(별도 트랜스포트 아님).
| stdio | Streamable HTTP | |
|---|---|---|
| 용도 | 로컬 서브프로세스 | 원격/네트워크 서버 |
| 통신 | stdin/stdout, 개행 구분 JSON-RPC | 단일 엔드포인트, POST + GET |
| 자격증명 | 환경변수(env) 에서 획득 | OAuth 2.1 (아래) |
| 인증 스펙 | 따르지 않음(SHOULD NOT) | OPTIONAL, 따르면 이 스펙 |
| 언제 | 내 머신 로컬 툴, 파일 접근 | 팀 공유, SaaS, 원격 배포 |
Streamable HTTP 세부: 클라이언트는 Accept 헤더에 application/json 과 text/event-stream 을 둘 다 명시해야 한다(MUST). 초기화 이후 모든 요청에 MCP-Protocol-Version 헤더 필수 — 없으면 서버는 2025-03-26 으로 가정한다. 세션은 MCP-Session-Id 헤더로(선택), 재연결 재개는 Last-Event-ID 로.
서버 직접 만들기 — 최소 예제 (Python SDK)
공식 SDK 는 10개(Tier제, verified 2026-07): Tier1 = TypeScript/Python/C#/Go, Tier2 = Java/Rust, Tier3 = Swift/Ruby/PHP/Kotlin. TS·Python 이 가장 성숙하다. (Wikipedia 가 언급하는 Perl 공식 SDK 는 공식 페이지에 없다.)
# pip install mcp
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""두 정수를 더한다."""
return a + b
if __name__ == "__main__":
mcp.run() # 기본 stdio 트랜스포트
원격으로 띄우려면 mcp.run(transport="streamable-http") 로 바꾸고, 로컬은 반드시 127.0.0.1 에만 바인딩한다(0.0.0.0 지양).
Claude Code 에 붙이기
Claude Code 는 대표적인 MCP host 다. 서버 등록은 통상 claude mcp add <이름> -- <실행명령> 형태이고, 원격 서버는 URL 로 붙인다. 프로젝트 단위 설정은 .mcp.json 에 들어간다. 설정 세부·지원 primitive 범위는 이번에 공식 문서로 재확인하지 못했다 — 실제 명령은 claude mcp --help 로 확인하라(재확인 필요).
흐름: 서버 구현 → claude mcp add 등록 → 세션에서 툴 노출·동의 프롬프트 확인. → claude-code-workflow
보안 함정 (필수)
MCP 는 신뢰 경계를 얇게 만든다. 서버가 곧 임의 코드 실행이고, 툴 설명문이 곧 모델에게 가는 프롬프트다.
- 툴 설명·annotation 은 신뢰된 서버가 아니면 untrusted 취급. 스펙(2025-11-25)이 명문화한 원칙이다. 서버가 툴
description에 숨긴 지시를 심으면 모델이 따라간다(tool poisoning). - 모든 툴 호출 전 사용자 명시 동의 필수. Host 가 강제해야 한다. "자동 승인" 을 무분별하게 켜지 마라.
- rug pull: 설치 시엔 안전하던 툴 정의가 이후 서버에서 은밀히 바뀐다(day1 정상, day7 자격증명 유출). 툴 정의 변경을 감지·고정할 방법이 있는 서버를 골라라.
- 자격증명: stdio 서버는 env 로 비밀을 받는다 — 로그·프로세스 목록 노출 주의. HTTP 서버는 OAuth 2.1 을 쓰되 토큰 passthrough 금지(받은 토큰을 상류 API 로 그대로 넘기지 마라, confused deputy 유발). RFC 9728 Protected Resource Metadata 구현 필수, PKCE
S256필수, RFC 8707resource파라미터로 토큰 audience 를 대상 서버에 묶어야 한다. - 트랜스포트: HTTP 서버는
Origin헤더 검증 필수(DNS rebinding 방지, 위반 시 403). - lethal trifecta: (신뢰 못 할 콘텐츠) + (비밀 접근) + (외부 유출 경로)가 한 에이전트에 모이면 프롬프트 인젝션이 데이터 유출로 직결된다. 여러 서버를 붙일수록 이 조합이 쉽게 성립한다(cross-server). → agent-design-patterns
⛔ 인용 금지 박스. "MCP 서버 43% 명령주입 취약", "82% 경로순회", "72.4% 캐스케이드 감염" 같은 정량 통계가 돌아다닌다(단일 집계 블로그 출처, 검증 불가). 수치를 인용하지 마라. 정성적으로 "널리 취약하다" 까지만 말할 것. OWASP 가 2025 중반 첫 "MCP Top 10" 을 냈다는 사실 자체는 참고할 만하다.
언제 MCP 서버, 언제 그냥 툴 정의
MCP 는 공짜가 아니다. 프로세스·프로토콜·신뢰 경계가 늘어난다.
| 상황 | 선택 |
|---|---|
| 단일 앱 안에서 한 번 쓰는 함수 | API 에 툴 인라인 정의 (set-up-tool-use, strict: true) |
| 프롬프트 코드와 툴이 한 코드베이스 | 인라인 툴 정의 |
| 여러 host(Claude Code + Desktop + 내 앱)에서 재사용 | MCP 서버 |
| 팀·외부에 배포·공유 | MCP 서버 (Streamable HTTP) |
| 언어·런타임이 앱과 분리돼야 함 | MCP 서버 |
한 줄 기준: 재사용·공유·격리가 필요하면 서버, 아니면 인라인 툴이 거의 항상 더 단순하다. Anthropic API 자체 툴 정의로 충분한 일에 MCP 서버를 세우는 건 과설계다.
참고
- set-up-tool-use — MCP 없이 API 에 툴을 인라인 정의하는 법 (대부분의 경우 이게 먼저)
- agent-design-patterns — 신뢰 경계·lethal trifecta·에이전트 안전 패턴
- claude-code-workflow — Claude Code 를 host 로 쓰는 실무 흐름
- anthropic-messages-api — MCP 서버가 최종적으로 호출되는 Messages API 계층
- agent-frameworks — MCP 를 감싸는 상위 에이전트 프레임워크 비교
출처: 스펙·트랜스포트·인증·SDK 는 modelcontextprotocol.io 1차 [HIGH]. 채택 현황·보안 공격군은 Wikipedia·리서치 2차 [MED], 정량 수치는 인용 금지. Claude Code 설정 세부와 2026-07-28 판 확정 여부는 재확인 필요. 원본 → 2026-07-25-mcp-protocol