책쓰자. Part1 - 5 에서 5.2까지
5장. MCP SDK 개요
MCP를 활용한 에이전트 시스템을 구현하기 위해서는 단순히 개념적 프로토콜만 이해해서는 충분하지 않다. 실제로 LLM이 도구를 선택하고 실행하며, 그 결과를 문맥에 반영하는 전 과정을 코드 수준에서 구현하려면 이를 뒷받침하는 실행 환경과 개발 도구가 필요하다. 이러한 역할을 수행하는 것이 바로 MCP SDK이다.
MCP SDK는 MCP 프로토콜을 기반으로 LLM 중심의 실행형 에이전트를 구축할 수 있도록 돕는 개발자 도구 모음이며, 다양한 언어와 플랫폼에서 일관된 실행 흐름을 가능하게 한다. SDK는 단순한 API 라이브러리가 아니라, 도구 명세, 호출 처리, 트랜스포트 계층, 실행 로그 등 실행 전반을 포괄하는 기능적 기반을 제공한다.
이 장에서는 MCP SDK의 핵심 개념, 구성 요소, 각 언어별 특징, 설치와 실행 환경을 다루며, 이후 MCP 서버와 클라이언트를 어떻게 구현할 수 있는지에 대한 기반을 마련한다. 특히 Python과 TypeScript를 중심으로 실습과 예제를 제공하며, SDK의 설계 철학이 어떻게 다양한 개발 환경에 적용되는지를 살펴본다. 이후 장에서는 이 SDK를 기반으로 실제 MCPServer와 MCPClient를 구현하게 된다.
5.1 MCP SDK란 무엇인가?
버전 정보: 본 서적에서 사용하는 MCP SDK의 기준 버전은 다음과 같다. 이후의 예제 및 구현은 해당 버전을 기반으로 설명된다.
- Python SDK: v1.5.0 (2025년 3월 24일 출시) - FastMCP 기반 고수준 서버 프레임워크 포함, CLI 도구(mcp dev, mcp run 등) 제공
- TypeScript SDK: v1.7.0 (2025년 3월 10일 출시)
- Java SDK: v0.9.0 (2025년 4월 10일 출시)
- C# SDK: v0.1.0-preview.10 (2025년 3월 24일 출시)
이 책은 TypeScript를 위주로 예제를 구현하며 다른 언어들은 예제로 담고 있지 않다. MCP SDK가 주로 Python과 TypeScript 위주로 만들어지고 있고, 현재 출시된 대부분의 MCP Server 역시 두 언어 위주로 만들어져 있는 만큼, 학습도 해당 언어 위주로 하여 MCP를 익혀가는 것을 추천한다.
MCP SDK는 MCP 기반 아키텍처를 구현하기 위한 표준 인터페이스와 유틸리티를 제공하는 라이브러리이다. 현재는 Python과 TypeScript를 중심으로 활발히 운영되고 있으며, Java, Kotlin, C#, Swift, Rust 등 다양한 언어에 대한 공식 SDK도 제공된다.
Python SDK는 FastMCP 기반의 고수준 서버 프레임워크, CLI 도구(mcp dev, mcp run 등), 비동기 리소스 지원, Pydantic 2.10.0 적용 등 다양한 기능이 통합된 최신 버전(v1.5.0, 2025년 3월 24일 출시)이 제공된다. TypeScript SDK(v1.7.0, 2025년 3월 10일 출시)는 다양한 트랜스포트 방식과 간결한 도구 정의 방식을 지원한다.
Java SDK는 2025년 4월 기준 최신 버전 v0.9.0이 Spring AI 팀과의 협업으로 릴리스되었으며, 세션 관리와 커스텀 컨텍스트 경로 기능을 지원한다. C# SDK는 2025년 3월 Microsoft 및 Anthropic과의 협력을 통해 공식 릴리스되었으며, NuGet 패키지로 제공된다.
MCP SDK의 공식 저장소는 https://github.com/modelcontextprotocol에서 확인할 수 있다. 각 언어별 SDK 구현체 및 예제 코드도 이곳에서 제공된다.
MCP SDK는 언어마다 내부 구현은 상이하지만, 모든 SDK는 표준 JSON-RPC 2.0 프로토콜을 기반으로 통신하며, 도구 명세(JSON Schema 기반), 입력 파라미터 직렬화, 출력 처리 방식에 있어서 일관된 인터페이스를 제공한다. 이러한 구조 덕분에 사용자는 언어에 관계없이 동일한 방식으로 MCP 서버와 클라이언트를 구현할 수 있으며, LLM과의 도구 연동 역시 동일한 패턴으로 적용할 수 있다.
예를 들어 Swift SDK는 Apple 플랫폼(macOS, iOS 등)에서 Stdio, HTTP, WebSocket 기반 MCP 클라이언트를 만들 수 있도록 설계되어 있으며, Rust SDK는 고성능 비동기 환경에서 안정적인 MCP 서버 및 클라이언트를 구축할 수 있도록 tokio 기반으로 구현되어 있다. 두 SDK 모두 JSON-RPC 메시지 스펙을 따르며, MCPClient와 MCPServer를 분리된 구조로 제공한다.
이처럼 언어별 SDK가 플랫폼 특성에 최적화된 구현을 제공하면서도, 프로토콜 레벨에서는 완벽하게 일관된 구조를 유지한다는 점이 MCP SDK의 강점이다. 주요 목적은 다음과 같다:
- 도구(Tool)를 JSON Schema 기반으로 명세할 수 있도록 지원
- 도구 호출 시 JSON-RPC 2.0 방식으로 통신할 수 있도록 인터페이스 제공
- 도구 실행 요청을 처리하는 MCPServer와, 도구를 호출하고 결과를 전달하는 MCPClient 구현 지원
5.2 LLM과 도구 실행 흐름의 연계 구조
MCP(Model Context Protocol)를 사용할 때 LLM API가 MCP를 직접 '지원'해야 하는 것은 아니다. MCP는 외부 도구와 LLM을 유연하게 연결하는 중간 추상 계층으로서, 도구 호출의 표준화와 실행 흐름의 일관성을 제공한다. 중요한 것은 LLM이 구조화된 JSON 입출력이나 함수 호출 기능을 제공하는지 여부이며, 이러한 기능이 있다면 MCP 환경에 자연스럽게 통합될 수 있다.
예를 들어 사용자가 '이 PDF를 요약해줘'라고 지시했을 때, LLM이 그 요청의 의도를 분석하고 JSON 형식으로 요약 도구를 호출할 수 있다면, 그 LLM은 MCP와 충분히 연동 가능하다. 이처럼 핵심은 LLM이 문맥 기반 추론을 바탕으로 적절한 도구를 선택하고, 구조화된 입력으로 해당 도구를 호출할 수 있느냐다.
MCP는 특정 모델에 종속되지 않기 때문에 Claude, GPT, Gemini 등 다양한 LLM에서 클라이언트를 통해 손쉽게 적용 가능하다. 이로 인해 개발자는 다양한 백엔드 도구들을 일관된 방식으로 재사용할 수 있고, LLM에 맞는 별도의 연동 코드를 반복적으로 작성할 필요도 없어진다.
또한 Google의 Gemini는 ADK(Agent Development Kit)를 통해 MCPToolSet 클래스 기반의 도구 연동 가이드를 제공한다. 이는 Claude처럼 API 차원에서 MCP를 내장한 방식은 아니지만, 공식적인 문서를 통해 구조화된 MCP 도구 명세와의 연계를 유도하고 있다는 점에서 중요한 진전이라 볼 수 있다.
즉, LLM API가 MCP 프로토콜을 네이티브하게 내장할 필요는 없다. MCP는 모델-불가지론적(model-agnostic) 프로토콜이며, LLM이 구조화된 입력/출력 형식을 지원하고 도구 호출을 처리할 수 있다면 MCP 클라이언트를 통해 MCP 서버와 연동이 가능하다.
현재 대부분의 LLM은 MCP를 직접 내장하지 않고, 함수 호출/도구 호출 기능을 통해 MCP 클라이언트와 연동하는 방식으로 사용된다. 실제 예제로는 mcp-use
, fastapi_mcp
등의 MCP 클라이언트를 통해 Claude, GPT, Gemini 등의 모델과 연결해 MCP 서버의 도구를 호출할 수 있다.
mcp-use
는 MCP SDK에서 제공하는 CLI 기반 실행 도구로, 별도 서버 구성 없이도 단일 파일 또는 디렉터리 형태의 MCP 도구를 실행하고 테스트할 수 있도록 설계되어 있다. Claude, GPT, Gemini 등의 LLM을 프롬프트 기반으로 호출하고, 선택된 도구를 자동으로 실행하여 그 결과를 다시 프롬프트에 반영하는 방식이다. 로컬 개발 환경에서 빠르게 MCP 도구를 실험하고 싶은 경우에 매우 유용하다.
fastapi_mcp
는 Python 기반의 FastAPI 웹 프레임워크 위에 구성된 MCPServer 구현체이다. 비동기 처리 구조와 경량 HTTP 서버를 통해 JSON-RPC 2.0 기반의 도구 호출을 빠르게 처리할 수 있으며, 다양한 도구를 API 형태로 구성하고 문서화할 수 있다는 장점이 있다. 특히asyncio
기반 병렬 처리 기능과OpenAPI
연동을 통해 실전 배포에도 적합한 MCP 서버 구성 요소로 활용된다.
그러나 예외적으로 Anthropic의 Claude 시리즈는 2024년 11월 MCP 오픈소스 공개 이후 Claude API 및 Claude Desktop에 MCP를 직접 통합하였다. 따라서 2025년 4월 기준으로 MCP를 직접 지원하는 대표적인 LLM은 Anthropic Claude 라고 할 수 있다.
이러한 구조는 향후 더 많은 LLM에서 MCP가 기본적으로 지원될 수 있는 가능성을 열어준다. 특히 클라이언트 중심의 설계 철학은 특정 LLM에 종속되지 않고, Claude, GPT, Gemini 등 다양한 모델과 유연하게 조합하여 MCP 기반 에이전트를 구성할 수 있는 확장성을 제공한다.
1. 도구 선택 방식과 실행 흐름
MCPClient는 단일 LLM 호출 내에서 도구를 선택하고 실행하기 위해 사용 가능한 모든 MCP 도구 목록을 LLM에 제공한다. 이 목록은 여러 MCPServer에서 수집된 도구들을 통합한 형태이며, 각 도구는 이름(name), 설명(description), 입력 명세(inputSchema) 등의 정보를 포함한다.
LLM은 이 목록을 바탕으로 현재 문맥에 가장 적합한 도구를 추론적으로 선택한다. 이때 중요한 점은 여러 개의 MCPServer에 등록된 도구들을 동시에 사용할 수 있다는 점이다. 다시 말해, 하나의 LLM 호출에서 다수의 서버에 분산된 도구들을 자유롭게 선택하고 호출할 수 있다.
예를 들어 다음과 같은 구조를 생각해볼 수 있다:
- MCPServer A: 이미지 분석 도구, OCR 도구 제공
- MCPServer B: 날씨 API, 위치 정보 도구 제공
- MCPServer C: 번역기, 요약기 제공
LLM이 다음과 같은 질의를 받았다고 가정하자:
이 이미지를 분석하고, 그 안에 있는 텍스트를 번역해줘.
이 경우, LLM은 다음과 같은 다중 도구 호출을 계획할 수 있다:
- MCPServer A의
analyze_image
호출 → 이미지 분석 결과 획득 - MCPServer A의
ocr
호출 → 이미지에서 텍스트 추출 - MCPServer C의
translate
호출 → 추출된 텍스트 번역
2. 다중 도구 호출과 시퀀스 유지
MCPClient는 이러한 연쇄적인 호출 흐름을 지원하기 위해 각 호출 결과를 내부 문맥에 삽입하고, 그 결과를 다음 LLM 호출 시 새로운 입력으로 활용한다. 이 구조는 "tool → result → context → next tool" 구조로 이루어지며, 도구 실행의 순차성을 유지하는 데 필수적이다.
실제로 MCPClient는 다음과 같은 흐름 제어 방식을 따른다:
- 첫 번째 LLM 호출: 전체 사용자 요청을 바탕으로 첫 번째 도구 선택
- MCP 도구 실행: JSON-RPC로 도구 호출, 결과 획득
- 결과 삽입: 도구 결과를 다음 LLM 호출의 system 또는 context에 삽입
- 다음 LLM 호출: 이전 결과를 포함한 문맥에서 새로운 도구 선택
MCPClient의 실행 흐름은 도구 간 순서를 철저히 유지한다. 여러 MCPServer가 동시에 존재하더라도, LLM이 선택한 도구의 실행 순서는 MCPClient에 의해 엄격하게 제어되며, 각 결과는 다음 도구 호출의 문맥으로 반영된다. 이 구조 덕분에 사용자는 복잡한 워크플로우를 단일 질의로 구성할 수 있다.
3. 병렬 실행과 비동기 처리
현재 MCPClient의 표준 동작은 도구 간 종속성이 있는 경우(예: 첫 도구의 결과가 다음 도구의 입력이 될 때) 순차 실행을 기본으로 한다. 그러나 도구 간 의존성이 없고 병렬로 실행해도 상호 간섭이 발생하지 않는 경우에는, 일부 구현체에서는 비동기 호출 또는 병렬 실행을 지원한다.
예를 들어 이미지에서 텍스트를 추출하는 도구(ocr
)와 동시에 이미지에서 위치를 추정하는 도구(guess_location
)는 서로 독립적이므로 병렬 실행이 가능하다. 실제로 fastapi_mcp
는 이와 같은 상황에서 asyncio.gather()
와 같은 비동기 코루틴 기반 병렬 처리 구조를 통해 도구를 동시에 호출할 수 있도록 설계되어 있다. 또한 TypeScript 기반 SDK에서도 Promise.all()
을 활용한 병렬 도구 실행이 일부 실험적으로 지원된다.
다만 병렬 실행 시 다음 LLM 호출에서 결과를 전달할 때에는 주의가 필요하다. 각각의 결과가 어떤 도구로부터 생성된 것인지 명확히 구분할 수 있도록 레이블링과 순서 정리가 필요하며, 응답 시간 차이가 존재할 경우 LLM 문맥 구성 순서에도 영향을 줄 수 있다. 따라서 병렬 실행은 구조적 독립성과 문맥 구성 전략이 잘 설계되어 있을 때만 효과적으로 작동할 수 있으며, 일반적인 경우에는 순차 실행이 여전히 권장된다.
다만 병렬 실행 결과를 다음 LLM 호출에 삽입할 때는, 결과 순서 및 레이블링을 명확히 지정하여 LLM이 오해 없이 추론할 수 있도록 문맥을 구성해야 한다. 이 부분은 MCPClient의 문맥 설계 능력에 따라 품질 차이가 발생할 수 있다.
4. 도구 필터링 및 우선순위 조정
MCPClient는 모든 도구를 LLM에 그대로 노출하기도 하지만, 다음과 같은 조건을 기준으로 도구 목록을 사전에 필터링하거나 우선순위를 조정할 수도 있다:
- 도구 이름 또는 설명에 포함된 키워드 기반의 사전 필터링
- 사용자 질의와의 의미적 유사도 기반의 도구 우선순위 정렬
- LLM별로 선호하는 도구 포맷 또는 제한된 입력 구조에 맞는 도구만 선별
이러한 도구 선택 최적화는 LLM이 보다 정확하게 도구를 선택하고 실행할 수 있도록 도와준다. 특히 도구 수가 많거나 서버가 복수일 경우, 불필요한 정보 과잉을 막고 실행 효율을 높이는 데 효과적이다.
5. 오류 처리와 실패 대응 전략
MCP 기반 시스템에서 도구 호출이 항상 성공한다고 가정할 수는 없다. 입력값 오류, 외부 API 실패, 네트워크 문제, 잘못된 응답 포맷 등 다양한 이유로 호출이 실패할 수 있다. 이런 실패 상황을 MCPClient가 어떻게 감지하고 대응하는지가 시스템의 신뢰성과 직결된다.
MCPClient는 도구 실행 결과로 받은 JSON 응답 내 error
필드를 감지하여 실패 여부를 판단한다. 이 오류는 LLM에게 명시적으로 전달되어야 하며, 다음 호출 시 문맥 안에 오류 메시지를 삽입하거나, 시스템 메시지를 통해 사용자에게 안내하도록 구성할 수 있다.
오류 대응 방식은 다음과 같다:
- LLM 문맥에 오류 삽입: 실패한 도구 이름, 입력값, 오류 메시지를 LLM 시스템 메시지에 구조화하여 삽입
- 자동 재시도 로직: 일시적인 오류(예: 타임아웃, 서버 과부하 등)에 대해서는 최대 n회까지 재시도
- Fallback 도구 호출: 특정 도구 실패 시 대체 가능한 유사 도구를 자동 선택하여 호출 (예: Google OCR → Tesseract OCR)
- 사용자 피드백: 오류 내용을 사용자에게 명확히 안내하고, 수정된 입력을 다시 요청할 수 있도록 UX 설계
이러한 구조는 특히 사용자와의 상호작용에서 신뢰감을 주고, 도구 기반 시스템의 회복력을 높이는 데 핵심적이다.
오류 응답은 JSON-RPC 2.0 명세를 따라 { error: { code, message, data } }
구조로 반환되며, code
는 오류 유형, message
는 설명, data
는 추가 정보를 포함한다. MCPClient는 이를 파싱하여 사용자 피드백 또는 LLM 컨텍스트 구성에 반영할 수 있다.
6. 문맥 지속성과 장기 대화 시나리오
복수 질의에 걸쳐 사용자의 요청이 이어질 때, LLM이 이전 도구 실행 결과를 기억하고 적절히 활용할 수 있어야 한다. 이를 위해 MCPClient는 도구 호출 결과를 지속 가능한 컨텍스트 형태로 관리해야 한다.
- 예를 들어, 사용자가 '이 보고서를 요약해줘'라고 요청한 뒤, '방금 요약된 내용 중에서 2023년 매출 부분만 다시 알려줘'라고 질의하는 경우, 이전 요약 결과가 문맥에 남아있어야 정확한 후속 응답이 가능하다.
- MCPClient는 이 흐름을 유지하기 위해 LLM 호출마다
history
또는context chain
구조를 생성하고, 각 도구의 결과를 저장해 이후 요청에 반영한다.
이러한 문맥 지속성 기능은 LLM 에이전트가 인간과 비슷한 수준의 일관된 대화를 유지하게 만드는 데 중요하며, 특히 장기 세션을 처리하는 고객 서비스형 에이전트에 유용하다.
7. 도구 간 연계 플로우 (Tool Composition)
MCP의 가장 큰 장점 중 하나는 도구들을 독립적으로 사용할 수 있을 뿐 아니라, 도구 간 출력/입력을 유기적으로 연결해 복합적인 흐름을 구성할 수 있다는 점이다. 예:
ocr
→translate
→summarize
: 이미지를 텍스트로 변환하고, 번역한 뒤, 요약까지 수행fetch_html
→extract_links
→filter_by_domain
이러한 연계는 LLM의 추론 능력에 기반해 자연스럽게 구성될 수도 있고, MCPClient가 사전에 의도한 플로우를 제안하여 흐름을 유도할 수도 있다. 이 구조는 파이프라인 구성처럼 명시적인 흐름이 필요한 시나리오, 혹은 LLM의 문맥 유지 능력이 중요한 대화형 시나리오 모두에 적용될 수 있다.
8. 보안 및 권한 관리 고려사항
도구가 외부 시스템을 제어하거나 민감한 정보에 접근하는 경우, 실행 제어와 권한 관리가 반드시 필요하다. MCPClient와 MCPServer는 다음과 같은 보안 구조를 포함해야 한다:
- 토큰 기반 인증: 각 도구 호출 시 유저 세션 또는 API 키 기반의 인증 수행
- 권한 레벨 지정: 특정 도구는 관리자 권한에서만 호출 가능하도록 MCP 명세에 조건 설정
- 도구 화이트리스트 관리: LLM이 선택할 수 있는 도구를 상황별로 제한하거나 조건부로 변경
- 로그 감사 및 실행 기록: 누가 어떤 요청으로 어떤 도구를 호출했는지 저장하고, 재현 가능하도록 설계
이러한 보안 구조는 특히 SaaS 환경, 기업 시스템 연동, 개인정보 처리 시 반드시 갖추어야 할 기반이다.
9. 응답 최적화 및 지연 최소화 전략
복수의 도구 호출, 다중 LLM 요청, 결과 변환 등으로 인해 전체 응답 속도가 느려질 수 있다. 실시간 사용자 응답이 필요한 시스템에서는 MCPClient 차원에서 다음과 같은 최적화 전략이 요구된다:
- 결과 캐싱: 동일한 입력에 대해 반복된 호출이 발생하지 않도록 캐시 적용
- 중간 요약 삽입: 도구 결과가 길 경우, 중간 요약본을 LLM 응답에 사용하고 전체 결과는 후속 응답으로 분리
- 프리페치 및 병렬 호출: 문맥상 필요한 도구를 미리 호출하거나, 독립 도구들을 병렬 처리
- 응답 타임아웃 설정: 일정 시간 이상 걸리는 도구는 결과 대신 대기 중 메시지 또는 후속 결과 예고 방식 사용