MCP Python 개발 스킬
mcp SDK(FastMCP 포함)를 사용하여 Python으로 MCP 서버와 클라이언트를 구축합니다.
빠른 개요
- 패키지: PyPI의
mcp(FastMCP 포함). 설치:pip install "mcp[cli]" - LangChain/LangGraph 통합:
pip install langchain-mcp-adapters - 스펙 버전:
2024-11-05,2025-03-26,2025-06-18,2025-11-25 - 임포트:
from mcp.server.fastmcp import FastMCP, Context, Image
코딩 시작 전에
사용자의 필요에 따라 이 스킬의 references/ 디렉토리에서 적절한 참조 파일을 읽으십시오:
| 사용자가 원하는 작업 | 읽을 파일 |
|---|---|
| MCP 서버 생성 (도구, 리소스, 프롬프트) | references/server.md |
| MCP 클라이언트 또는 멀티 서버 에이전트 생성 | references/client.md |
| 컨텍스트 사용 (로깅, 진행률, 샘플링, elicitation) | references/context.md |
| 전송, 인증, 보안, 생명주기 이해 | references/protocol.md |
코드를 작성하기 전에 항상 관련 참조 파일을 읽으십시오. 참조 파일에는 정확한 가져오기 경로, API 서명, 반환 타입 매핑 및 중요한 주의사항이 포함되어 있습니다.
아키텍처 개요
호스트 (Claude Desktop / IDE / 사용자 정의 에이전트)
├── MCP 클라이언트 1 ──► MCP 서버 A (로컬, STDIO)
├── MCP 클라이언트 2 ──► MCP 서버 B (원격, Streamable HTTP)
└── MCP 클라이언트 3 ──► MCP 서버 C (원격, OAuth 2.1)
- 호스트: 클라이언트를 생성하는 AI 애플리케이션
- 클라이언트: 단일 서버에 대한 1:1 연결
- 서버: 도구, 리소스, 프롬프트 노출
세 가지 프리미티브: 도구(모델 제어 함수), 리소스(앱 제어 읽기 전용 데이터), 프롬프트(사용자 제어 메시지 템플릿).
두 가지 전송 방식: STDIO(로컬 서브프로세스, 단일 클라이언트) 및 Streamable HTTP(네트워크, 다중 클라이언트, 기본 엔드포인트 /mcp).
최소 서버 템플릿 (복사-붙여넣기 스타터)
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("MyServer")
@mcp.tool()
def my_tool(param: str) -> str:
"""이 도구가 무엇을 하는지 설명합니다."""
return f"결과: {param}"
@mcp.resource("data://config")
def get_config() -> str:
"""서버 설정."""
return '{"key": "value"}'
if __name__ == "__main__":
mcp.run() # 기본값 STDIO; HTTP를 사용하려면 mcp.run(transport="streamable-http")
최소 클라이언트 템플릿
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
import asyncio
async def main():
params = StdioServerParameters(command="python", args=["server.py"])
async with stdio_client(params) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
result = await session.call_tool("my_tool", {"param": "hello"})
print(result.content[0].text)
asyncio.run(main())
핵심 규칙 및 주의사항
- docstring은 필수입니다 —
@mcp.tool()함수의 docstring은 LLM에 전달되는 도구 설명이 됩니다. docstring이 없으면 LLM이 도구의 기능을 알 수 없습니다. - 타입 힌트는 필수입니다 — FastMCP는 타입 힌트로 JSON 스키마를 생성합니다. 풍부한 매개변수 문서를 위해
Annotated[str, Field(description="...")]를 사용하십시오. - 컨텍스트는 타입 힌트로 주입됩니다 —
ctx: Context를 매개변수로 추가하면 도구의 입력 스키마에서 자동으로 제외됩니다. - 반환 타입이 중요합니다:
str→ TextContent,dict→ JSON TextContent,bytes→ BlobResourceContents,Image→ ImageContent,list→ 여러 콘텐츠 블록. - 오류: 도구에서 예외 발생 →
isError=True와 함께 LLM에 반환됩니다. 오류 문자열을 정상 출력으로 반환하지 마십시오. - STDIO 서버는 절대 stdout에 출력해서는 안 됩니다 — 모든 비MCP 출력은 stderr로 전송됩니다. stderr 핸들러를 사용한
logging또는ctx.info()를 사용하십시오. - I/O를 수행하는 도구에는 async가 선호됩니다. 동기 및 비동기 핸들러가 모두 지원됩니다.
- 도구 어노테이션은 힌트이지 강제가 아닙니다:
readOnlyHint,destructiveHint,idempotentHint,openWorldHint. - **MultiServerMCPClient (v0.1.0+)**는 async 컨텍스트 관리자가 아닙니다. 직접 인스턴스화:
client = MultiServerMCPClient({...}). - InMemorySaver는 개발 전용입니다 — 프로덕션에서는 PostgresSaver 또는 SqliteSaver를 사용하십시오.
개발 워크플로우
mcp dev server.py # MCP Inspector로 실행 (디버깅 UI)
mcp dev server.py --with pandas # 추가 종속성 포함
mcp install server.py # Claude Desktop에 등록
mcp install server.py -e API_KEY=x # 환경 변수 포함
mcp run server.py # 직접 실행
전송 방식 선택 기준
| 시나리오 | 전송 방식 | 이유 |
|---|---|---|
| 로컬 CLI 도구 / 데스크톱 통합 | STDIO | 네트워크 없음, 마이크로초 지연시간 |
| 프로덕션 API, 다중 클라이언트 | Streamable HTTP | 확장 가능, 로드 밸런싱 |
| 서버리스 (Lambda, Cloud Run) | Streamable HTTP + stateless_http=True | 요청별 상태 비저장 |
| 기존 FastAPI/Starlette에 내장 | Streamable HTTP (마운트) | ASGI 앱 공유 |