콘텐츠로 이동

02-구조

FastMCP는 Python SDK의 고수준 API다. 데코레이터로 도구·리소스·프롬프트를 선언한다 — mcp-python-sdk.

from mcp.server.fastmcp import FastMCP
mcp = FastMCP("acme-erp")
@mcp.tool()
def get_invoice(invoice_id: str) -> dict:
"""청구서 ID로 청구서를 조회한다.
Args:
invoice_id: 8자리 청구서 번호 (예: "INV-0042")
"""
# ... 사내 API 호출
return {"id": invoice_id, "amount": 1234.56, "status": "paid"}
@mcp.resource("erp://customer/{customer_id}")
def customer_profile(customer_id: str) -> str:
"""고객 프로필을 마크다운으로 반환."""
return f"# Customer {customer_id}\n..."
@mcp.prompt()
def monthly_report_template(month: str) -> str:
"""월간 보고서 작성 프롬프트."""
return f"다음 형식으로 {month}월 매출 보고서를 작성하라: ..."
if __name__ == "__main__":
mcp.run(transport="stdio")

핵심 포인트:

  • 타입 힌트가 곧 입력 스키마다. SDK가 JSON Schema를 자동 생성.
  • docstring이 곧 도구 설명이다. LLM이 이걸 보고 호출 여부를 판단.
  • 리소스 URI는 템플릿 변수를 가질 수 있다({customer_id}).
  • mcp.run(transport="stdio") — Streamable HTTP는 transport="streamable-http".
import sys, logging
# 절대 stdout으로 로깅하지 말 것
logging.basicConfig(stream=sys.stderr, level=logging.INFO)

복잡한 상태(DB 커넥션, HTTP 세션)는 lifespan 컨텍스트로 관리한다 — mcp-python-sdk.

import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({ name: "acme-erp", version: "0.1.0" });
server.tool(
"get_invoice",
"청구서 ID로 청구서를 조회한다",
{ invoice_id: z.string().describe("8자리 청구서 번호") },
async ({ invoice_id }) => ({
content: [{ type: "text", text: JSON.stringify({ invoice_id, amount: 1234.56 }) }],
})
);
const transport = new StdioServerTransport();
await server.connect(transport);

핵심: Zod 스키마가 입력 검증과 JSON Schema 생성을 동시에. — mcp-typescript-sdk

도구는 content 배열을 반환한다. 가장 흔한 형식:

{ "content": [{ "type": "text", "text": "결과 텍스트" }] }

이미지(type: "image"), 리소스 참조(type: "resource")도 가능. 큰 결과는 요약 + 페이지네이션.

도구가 실패하면 예외를 던지지 말고 isError: true로 반환하는 게 안전하다(SDK가 자동 처리). 이유: LLM이 에러 메시지를 읽고 다음 행동을 결정할 수 있어야 한다.

샘플링(Sampling) — 서버가 LLM을 부를 때

섹션 제목: “샘플링(Sampling) — 서버가 LLM을 부를 때”

고급 기능: 서버가 클라이언트에 “이 텍스트를 LLM으로 요약해줘”를 요청할 수 있다 — mcp-sampling. 호스트는 사용자 동의 후 모델을 호출. 첫 서버에는 필요 없음, 에이전트형 서버를 만들 때 검토.