Python으로 공식 2.x SDK를 사용하여 MCP 서버 생성하기 (FastMCP는 이제 안녕)
요약
본 문서는 공식 mcp 2.x SDK와 Python 3.13을 사용하여 MCP 서버를 구축하는 방법을 안내합니다. 특히, 최신 클라이언트(버전 2026-07-28)와 구형 클라이언트를 모두 지원하는 방식으로 서버를 설계하는 것이 핵심입니다. SDK는 타입 정의, docstring, 반환 타입을 기반으로 스키마를 자동으로 생성하며, 스트리밍 HTTP 무상태 서비스 구현 시 유의할 점들을 다룹니다.
핵심 포인트
- 공식 2.x SDK에서는 클래스 이름이 `MCPServer`로 변경되었으며, 이전 방식(`FastMCP`)은 사용 불가합니다.
- SDK는 타입 정의와 docstring을 활용하여 입력/출력 스키마를 자동으로 생성하는 강력한 기능을 제공합니다.
- 최신 프로토콜 버전(2026-07-28)에 맞춰 세션 없이 stateless HTTP로 서비스를 구현할 수 있습니다.
- 스트리밍 응답 대신 단일 JSON 응답을 원한다면 `json_response=True` 옵션을 사용해야 합니다.
만약 2025년의 Python용 MCP 튜토리얼을 따라했다면, 아마도 from mcp.server.fastmcp import FastMCP로 시작했을 것입니다. 공식 2.x SDK에서는 이 줄이 ModuleNotFoundError를 발생시킵니다. 클래스 이름이 이제 MCPServer로 바뀌었기 때문입니다. 그리고 독립 패키지인 fastmcp는 별개의 것이며, 여전히 유효합니다 (버전 4는 공식 2.x SDK를 기반으로 구축되었습니다).
본 문서는 더 긴 가이드의 일부입니다. 우리는 Nortia Logística(DevelopmentMCP 과정의 가상 회사)의 창고 재고를 조회하는 서버인 nortia-almacen을 공식 mcp 2.2.0 SDK와 Python 3.13을 사용하여, 프로토콜의 상태 비저장 버전인 2026-07-28 사양에 맞춰 작성했습니다.
Python의 장점: 동일한 엔드포인트에서 두 가지 프로토콜 버전 지원하기
2026-07-28에는 initialize 핸드셰이크나 세션이 없습니다. 모든 요청은 _meta 필드에 클라이언트의 버전과 기능을 담고 있습니다. mcp 2.x로 만든 서버는 설정 없이 두 가지 방식을 모두 처리합니다: 최신 클라이언트는 2026-07-28을 사용하고, 구형 클라이언트는 initialize를 수행하여 2025-11-25 또는 그 이전 버전을 협상합니다.
프로젝트
uv init --bare --name nortia-almacen --python 3.13
uv add "mcp[cli]==2.2.0"
uv add --dev pytest
...
버전을 고정하세요: 2026년 10월 2일 이후에는 버전 지정 없이 설치할 경우 2.3.0이 설치되는데, 우리는 이 버전으로 예제를 실행한 적이 없습니다.
스키마를 작성하지 않는 Tools
CodigoAlmacen = Annotated[
str, Field(pattern=r"^[A-Z]{3}-\d{2}$", description="창고 코드, 예: MAD-01")
]
...
SDK가 시그니처에서 모든 것을 추론합니다:
- **타입을 가진 매개변수(parámetros con tipos)**는
inputSchema를 생성합니다. 패턴과 설명은Field에서 나옵니다: 만약 모델이almacen: "madrid"를 전송하면, 함수는 실행되지 않습니다. - docstring은 툴의
description입니다. - **반환 타입(tipo de retorno)**은
outputSchema를 생성하며, 값은structuredContent에 실려 이동합니다. - **리스트와 스칼라(listas y los escalares)**는
result키를 가진 객체로 감싸집니다. 만약 직접 형식을 결정하고 싶다면,consultar_existencias와 같은 모델을 반환하세요.
예상되는 오류(존재하지 않는 창고)는 모델에게 어떤 값이 유효한지 알려주는 텍스트가 포함된 ToolError로 변환됩니다. 예상치 못한 오류는 포착되지 않습니다: 2.1.0 버전부터 SDK는 클라이언트에게 예외 처리 텍스트를 전송하지 않습니다.
스트리밍 가능한 HTTP 무상태(stateless)로 서비스하기
from servidor import mcp
if __name__ == "__main__":
...
자주 오해되는 두 가지 옵션:
- **
stateless_http=True**는 핸드셰이크 버전의 클라이언트를 처리하는 방식만 변경합니다: 세션을 할당하지 않습니다. 2026-07-28 트래픽은 세션 유무와 관계없이 절대 세션을 열지 않습니다. - **
json_response=True**는 SSE 스트림 대신 각 POST에 단일 JSON으로 응답합니다. 빠른 툴에는 적합하지만, 진행 상황 알림이 손실됩니다.
반드시 보게 될 세 가지 오류
- 괄호가 없는
@mcp.tool로 인한TypeError. 공식 SDK에서는 필수입니다:@mcp.tool(). - 생성자(constructor)에
port를 전달할 때의TypeError. 전송 옵션은MCPServer(...)가 아닌mcp.run(...)에 넣어야 합니다. - Inspector는 녹색으로 표시되지만, 2026-07-28을 테스트하지 않은 경우. 서버 입력 내부에
"protocolEra": "modern"이 없으면, Inspector는 핸드셰이크가 있는 버전을 사용합니다.
전체 서버(데이터, 모델, 리소스 및 프롬프트 포함), pytest를 사용한 메모리 테스트, Inspector 테스트, Claude Code를 사용한 테스트, 그리고 Claude Code에게 이를 구축하도록 요청하는 방법이 담긴 가이드가 **DesarrolloMCP: Python으로 MCP 서버 생성하기**에 있습니다.
만약 스페인어로 MCP를 배우고 있다면, DesarrolloMCP 과정에서 기본 레벨(Basic)을 무료로 제공합니다(14개 강의, 카드 없음). 이 과정은 2026-07-28 사양으로 업데이트되었으며 모든 테스트 코드가 포함되어 있습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기