14. 첫 서버: FastMCP로 처음부터
- 환경을 세팅하고(
uv/pip,mcp[cli]) 15줄 이내의 동작하는 서버를 만든다 @mcp.tool/@mcp.resource/@mcp.prompt데코레이터로 세 primitive를 등록한다mcp dev로 Inspector를 띄워 서버를 눈으로 확인한다
지금까지 4부에 걸쳐 "MCP가 무엇이고 어떻게 동작하는가"를 봤습니다. 이제 직접 만듭니다. 5부는 Python 위주(공식 mcp SDK 내장 FastMCP 기준)로, 실제로 돌아가는 코드를 짭니다.
mcp SDK는 v1.x가 production 권장이며 유지보수 모드로 핵심 버그·보안 패치를 받습니다. v2(stable)는 2026-07-27 목표로 진행 중입니다. 패키지가 mcp에 의존한다면 mcp>=1.27,<2 처럼 상한을 두라는 게 공식 권고입니다. 아래 코드는 v1.x 기준이며, v2 전환 시 마이그레이션 가이드를 확인하세요.환경 세팅
Python 3.10+ 가 필요합니다. 패키지 매니저는 uv(빠름, 공식 권장)나 pip 둘 다 됩니다. 패키지 매니저는 라이브러리를 내려받아 설치·관리해 주는 도구로, pip은 파이썬 표준 도구이고 uv는 훨씬 빠른 신형입니다. CLI extra([cli]) 를 꼭 포함하세요 — mcp dev/mcp run/mcp install 같은 개발 도구가 거기 들어 있습니다. 여기서 extra는 "선택적 추가 구성요소"를 뜻하며, mcp[cli]는 "mcp 패키지에 cli 추가분까지 함께 설치"라는 표기입니다.
# uv (권장) uv init mcp-server-demo cd mcp-server-demo uv add "mcp[cli]" # 또는 pip + 가상환경 (가상환경=프로젝트별 독립된 패키지 공간) python -m venv .venv source .venv/bin/activate # Windows: .venv\Scripts\activate pip install "mcp[cli]"
pip install mcp만 하면 기본 패키지만 깔리고 CLI 도구(mcp dev·mcp run)가 빠집니다. 반드시 mcp[cli]로 설치하세요.requirements.txt나 pyproject.toml에 버전을 고정하세요(예: mcp>=1.27,<2).15줄 서버 — 세 primitive 한 번에
server.py 하나로 도구·리소스·프롬프트를 모두 노출해 봅니다.
# server.py — 공식 mcp SDK (mcp.server.fastmcp) from mcp.server.fastmcp import FastMCP # 1) 서버 인스턴스 생성 (이름은 클라이언트가 서버를 식별하는 데 쓰임) mcp = FastMCP("Demo") # 2) Tool — 모델이 호출하는 행동 @mcp.tool() def add(a: int, b: int) -> int: """두 정수를 더한다""" # 이 독스트링이 곧 도구 description return a + b # 3) Resource — 읽기 전용 데이터 (URI 템플릿) @mcp.resource("greeting://{name}") def get_greeting(name: str) -> str: """이름에 맞춘 인사말을 돌려준다""" return f"안녕하세요, {name}님!" # 4) Prompt — 사용자가 고르는 재사용 템플릿 @mcp.prompt() def greet_user(name: str, style: str = "friendly") -> str: """인사 프롬프트를 생성한다""" styles = { "friendly": "따뜻하고 친근한 인사를", "formal": "정중하고 격식 있는 인사를", } return f"{styles.get(style, styles['friendly'])} {name}님에게 써 주세요." if __name__ == "__main__": mcp.run() # transport 생략 → stdio가 기본 (07장 참고)
여기서 일어나는 일을 4부와 연결해 봅시다:
| 데코레이터 | 등록되는 primitive | 자동 생성되는 것 |
|---|---|---|
@mcp.tool() | Tool (tools/list, tools/call) | 타입 힌트 → inputSchema, 독스트링 → description |
@mcp.resource("uri://{x}") | Resource (resources/list/read, 템플릿) | URI의 {x} → 함수 인자 매핑 |
@mcp.prompt() | Prompt (prompts/list, prompts/get) | 인자 → prompt arguments |
a: int라고 쓰면 FastMCP가 inputSchema에 "a": {"type": "integer"}를 넣어 줍니다. 그래서 모든 파라미터에 타입 힌트를 다는 게 중요합니다. (스키마·검증은 15장에서 깊이.)실행하는 세 가지 방법
# (a) 그냥 파이썬으로 — stdio 서버. 보통 호스트가 자식 프로세스로 띄움 python server.py # (b) mcp CLI로 실행 — 파일에서 mcp/app/server 이름의 객체를 찾음 mcp run server.py # 커스텀 객체명: mcp run server.py:my_server # (c) 개발 모드 — Inspector를 함께 띄움 (가장 자주 씀) mcp dev server.py
07장에서 본 대로, stdio 서버는 "스스로 실행"보다 클라이언트(호스트)가 띄우는 구조입니다. 그래서 개발 중 단독 점검은 (c) mcp dev로 합니다.
MCP Inspector — 서버를 눈으로 보기
MCP Inspector는 서버를 띄워 도구·리소스·프롬프트를 브라우저 UI에서 직접 호출해 보는 공식 디버깅 도구입니다. 표준 웹 개발에서 curl·Postman으로 HTTP 서버를 찌르듯, Inspector는 대리 클라이언트 역할을 해 stdio 너머의 서버를 테스트하게 해줍니다.
mcp dev server.py # → 터미널이 stdio 전송으로 서버를 띄우고, # Inspector 웹 UI(보통 http://localhost:6274)를 엽니다.
flowchart LR
B["브라우저\n(Inspector UI)"] <-->|"UI 동작 ↔ JSON-RPC"| INS["Inspector\n(대리 클라이언트)"]
INS <-->|"stdio"| S["server.py"]
classDef ui fill:#fde68a,stroke:#b45309,color:#000;
classDef ins fill:#bfdbfe,stroke:#1d4ed8,color:#000;
classDef srv fill:#5eead4,stroke:#0f766e,color:#000;
class B ui;
class INS ins;
class S srv;
Inspector에서 할 수 있는 것:
- Tools 탭: "List Tools" → 등록된 도구 목록 확인 → 인자를 넣어 호출, 결과·
isError확인 - Resources 탭: 리소스/템플릿 목록, URI를 채워 읽기. 텍스트는 text, 이진은 base64 blob로 보임
- Prompts 탭: 프롬프트 선택, 인자 입력, 생성된 messages 확인
- 상세 로그·에러 메시지, 환경 변수 설정, 전송 방식 선택
개발 의존성을 함께 주입하거나 실시간 리로드를 켤 수도 있습니다:
mcp dev server.py --with pandas --with numpy # 의존성 추가 mcp dev server.py --with-editable . # 로컬 코드 마운트(라이브 업데이트)
mcp dev로 Inspector에서 동작을 확인하세요. 도구 설명이 명확한지, 인자 스키마가 맞는지, 응답이 유용한지를 여기서 먼저 잡으면 통합 단계의 디버깅이 훨씬 쉬워집니다.호스트에 등록하기 (맛보기)
Inspector로 검증했으면 실제 호스트에 붙입니다. mcp install로 데스크톱 앱 설정에 등록하거나, 설정 파일을 직접 편집합니다.
mcp install server.py --name "내 데모 서버" mcp install server.py -e API_KEY=abc123 # 환경 변수 mcp install server.py -f .env # 파일에서 환경 변수
설정 파일 형태(호스트마다 다름)는 07장에서 본 그대로 "이 명령으로 서버를 실행하라"입니다:
{
"mcpServers": {
"demo": { "command": "uv", "args": ["--directory", "/path/to/proj", "run", "server.py"] }
}
}
(클라이언트·호스트 관점은 6부에서 더 다룹니다.)
🔒 보안 — 비밀값은 코드 밖으로: API 키·토큰을 소스에 하드코딩하지 말고 환경 변수(-e/-f)로 주입하세요. stdio 서버는 사용자 권한으로 도니, 그 환경 변수가 로그나 stdout으로 새지 않게 주의합니다(07장).
이 장에서 배운 것
uv add "mcp[cli]"(또는pip install "mcp[cli]")로 설치하고, CLI extra를 빠뜨리지 않는다. v1.x가 현재 production 권장.@mcp.tool/@mcp.resource("uri://{x}")/@mcp.prompt로 세 primitive를 등록한다. 타입 힌트 → 스키마, 독스트링 → description 이 자동.- 실행은
python server.py/mcp run/mcp dev(Inspector 포함). - Inspector는 대리 클라이언트로 도구·리소스·프롬프트를 호출해 보는 필수 디버깅 도구다. 호스트 연결 전에 여기서 검증한다.
✍️ 확인 문제
pip install mcp로 설치한 뒤mcp dev가 "command not found"라 나온다. 원인과 해결은?@mcp.tool()을 붙인 함수의 타입 힌트와 독스트링은 각각 무엇으로 변환되나?- 호스트에 붙이기 전에
mcp dev(Inspector)로 먼저 확인하면 어떤 이점이 있나? 한 가지 들어 보자.
다음 장: 15. 도구/리소스/프롬프트 등록과 입력 스키마·검증