mcp 서버 만들기 python — 15줄 코드와 연결 확인
파이썬으로 MCP 서버를 만드는 건 함수 두 개면 끝입니다. pip install "mcp[cli]" 로 공식 SDK를 깔고, MCPServer 객체를 만든 뒤 함수 위에 @mcp.tool() 을 붙이면 그게 곧 도구가 됩니다. 다만 지금 검색해서 나오는 예제 대부분은 그대로 붙여넣으면 실행조차 안 됩니다 — pip install mcp 가 이제 2.x를 설치하는데, 여기서 FastMCP 가 MCPServer 로 이름이 바뀌었기 때문입니다. 아래는 2026년 8월 29일 기준 mcp 2.1.1 · Python 3.12.10 에서 직접 만들어 돌리고, 클로드 코드에 붙여 연결까지 확인한 과정입니다.
1. 준비 — 설치와 버전 확인
공식 MCP Python SDK는 Python 3.10 이상이 필요합니다. 프로젝트 폴더를 하나 만들고 가상환경에 설치합니다.
python -m venv .venv
.venv\Scripts\activate # macOS·리눅스: source .venv/bin/activate
pip install "mcp[cli]"
[cli] 를 붙이면 mcp 명령이 같이 깔립니다(mcp dev·mcp run·mcp install). SDK만 필요하면 pip install mcp 로 충분합니다. 깔린 버전을 확인해 둡니다.
> mcp version
MCP version 2.1.1
from mcp.server.fastmcp import FastMCP 는 2.x에서 없어진 경로입니다. 실제로 돌리면 이렇게 나옵니다.
ModuleNotFoundError: No module named 'mcp.server.fastmcp'. This is mcp 2.x,
where FastMCP was renamed to MCPServer (from mcp.server.mcpserver import MCPServer)
and other APIs changed; see the migration guide at
https://py.sdk.modelcontextprotocol.io/v2/migration/ or pin 'mcp<2' to keep running v1 code.
즉 선택지는 둘입니다. 새로 만든다면 2.x의 MCPServer 를 씁니다. 이미 v1으로 짜 둔 코드를 당장 고칠 수 없다면 pip install "mcp>=1.28,<2" 처럼 상한을 걸어 1.x에 묶어 둡니다(공식 README가 안내하는 방법입니다).
2. 15줄짜리 MCP 서버 만들기
server.py 파일 하나면 됩니다. 도구(tool) 하나와 리소스(resource) 하나를 가진 완전한 서버입니다.
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run()
여기서 안 쓴 것이 중요합니다. JSON 스키마를 손으로 적지 않았고, 요청 파싱·값 검증·프로토콜 처리 코드가 한 줄도 없습니다. a: int, b: int 라는 타입 힌트가 그대로 도구의 입력 스키마가 되고, 독스트링이 도구 설명이 되어 AI에게 전달됩니다. 그래서 독스트링을 대충 적으면 AI가 그 도구를 언제 써야 할지 모릅니다.
| 코드 | 역할 |
|---|---|
MCPServer("Demo") |
서버 본체. 따옴표 안은 서버 이름 |
@mcp.tool() |
AI가 호출하는 도구. 타입 힌트가 스키마, 독스트링이 설명 |
@mcp.resource("greeting://{name}") |
AI가 읽는 데이터. 주소 안 {name} 이 함수 인자로 들어옴 |
mcp.run() |
기본 통신 방식(stdio)으로 서버 실행 |
3. 진짜 도는지 먼저 확인한다
AI 도구에 붙이기 전에 서버 혼자 잘 도는지부터 봅니다. 같은 mcp 패키지가 클라이언트도 겸하기 때문에, 파이썬 파일 하나로 확인할 수 있습니다.
import asyncio
import sys
from mcp import Client, StdioServerParameters
async def main() -> None:
params = StdioServerParameters(command=sys.executable, args=["server.py"])
async with Client(params) as client:
tools = await client.list_tools()
print("tools:", [t.name for t in tools.tools])
result = await client.call_tool("add", {"a": 1, "b": 2})
print("call add(1,2) ->", result.structured_content)
res = await client.read_resource("greeting://claude")
print("read greeting://claude ->", res.contents[0].text)
asyncio.run(main())
실행하면 이렇게 나옵니다. (실제 출력 그대로입니다)
> python client_test.py
tools: ['add']
call add(1,2) -> {'result': 3}
read greeting://claude -> Hello, claude!
StdioServerParameters 는 서버를 자식 프로세스로 띄워 표준입출력으로 대화합니다. 서버를 미리 켜 둘 필요가 없습니다. 브라우저 화면으로 확인하고 싶다면 mcp dev server.py 로 MCP Inspector를 띄우는 방법도 있습니다.
4. 클로드 코드에 붙이기 — claude mcp add
이제 만든 서버를 실제 AI 도구에 연결합니다. 클로드 코드에서는 claude mcp add 한 줄입니다. -- 뒤가 서버를 실행하는 명령이고, 그 앞은 클로드 코드의 옵션입니다.
# 윈도우 (가상환경 파이썬을 그대로 지정)
claude mcp add demo --scope local -- .\.venv\Scripts\python.exe server.py
# macOS·리눅스
claude mcp add demo --scope local -- ./.venv/bin/python server.py
등록 위치(스코프)는 세 가지이고, 어디에 저장되는지가 다릅니다.
| 스코프 | 적용 범위 | 저장 위치 |
|---|---|---|
local (기본값) |
지금 프로젝트 · 나만 | ~/.claude.json |
project |
지금 프로젝트 · 팀 공유(깃에 커밋) | 프로젝트 루트의 .mcp.json |
user |
내 모든 프로젝트 | ~/.claude.json |
붙었는지는 claude mcp list 로 봅니다.
> claude mcp list
Checking MCP server health…
demo: .\.venv\Scripts\python.exe server.py - √ Connected
√ Connected 가 뜨면 끝입니다. 명령을 어떻게 등록했는지 다시 보고 싶으면 claude mcp get demo, 지울 때는 claude mcp remove demo -s local 입니다. 명령 자체를 더 자세히 보려면 클로드 코드 mcp 연결 — 추가·확인·삭제 명령 글에 정리해 두었고, 제미나이 쪽은 gemini cli mcp 설정 글이 따로 있습니다.
5. 안 붙을 때 — 상태 문구로 원인 가르기
claude mcp list 가 알려주는 상태만 봐도 원인이 갈립니다. 아래는 일부러 상황을 만들어 실제로 찍어 본 결과입니다.
| 상태 | 원인과 해결 |
|---|---|
⏸ Pending approval |
--scope project 로 넣은 서버는 승인 전까지 연결되지 않습니다. 그 폴더에서 claude 를 대화형으로 한 번 실행해 승인하면 붙습니다. 코드는 멀쩡한데 안 붙는다면 대개 이것입니다 |
× Failed to connect |
명령 자체가 실행되지 않는 경우입니다. 파일 경로 오타, 가상환경이 아닌 시스템 파이썬 지정, mcp 미설치가 대부분입니다. 등록한 명령을 터미널에 그대로 붙여넣어 돌려 보면 바로 드러납니다 |
| 붙긴 하는데 이상함 | 서버 코드에 print() 가 있는지 보세요. 아래에서 따로 설명합니다 |
print() 를 쓰지 마세요. 기본 통신 방식(stdio)은 표준출력을 프로토콜 통로로 쓰기 때문에, print 한 줄이 그 통로에 섞여 들어갑니다. mcp 2.1.1에서 실제로 확인해 보니 영문 print 는 Invalid JSON: expected value at line 1 column 1 로그만 남기고 세션은 이어졌지만, 한글을 print 하자 윈도우 콘솔 인코딩(cp949) 때문에 UnicodeDecodeError 가 나며 연결이 끊겼습니다. 로그가 필요하면 표준에러로 보냅니다: print("...", file=sys.stderr)
자주 묻는 질문 (FAQ)
Q. 꼭 uv를 써야 하나요?
아닙니다. 공식 문서가 uv 를 권할 뿐, pip install "mcp[cli]" 로도 똑같이 됩니다. 위 과정은 전부 venv + pip로 확인한 것입니다.
Q. 만든 서버를 다른 컴퓨터에서도 쓰려면요?
stdio 방식은 그 PC에서 프로세스를 띄우는 구조라 원격에는 맞지 않습니다. 원격으로 열려면 HTTP 방식으로 실행합니다 — mcp run server.py --transport streamable-http 로 띄우면 주소(http://localhost:8000/mcp)로 붙일 수 있습니다.
Q. 도구가 목록에는 보이는데 AI가 안 씁니다.
독스트링과 함수 이름을 먼저 보세요. AI는 그 둘로 "언제 쓰는 도구인지"를 판단합니다. def f(x) 에 설명이 없으면 목록에만 있고 실제로는 호출되지 않습니다.
Q. 기존 FastMCP 코드는 버려야 하나요?
아닙니다. 1.x는 별도 브랜치에서 보안·버그 수정을 계속 받습니다. 급하지 않으면 pip install "mcp>=1.28,<2" 로 묶어 두고, 시간이 될 때 마이그레이션 가이드를 보며 옮기면 됩니다.
마무리
정리하면 세 줄입니다. ① pip install "mcp[cli]" → ② MCPServer 에 @mcp.tool() 함수를 붙여 server.py 작성 → ③ claude mcp add 로 등록하고 claude mcp list 에서 √ Connected 확인. 막히는 지점은 대개 2.x에서 바뀐 FastMCP → MCPServer, 그리고 project 스코프의 승인 대기 둘입니다. 직접 만들기 전에 이미 있는 서버부터 붙여 보고 싶다면 claude mcp 서버 추천 글을 참고하세요. SDK가 빠르게 바뀌는 중이니, 버전이 다르면 공식 문서에서 한 번 더 확인하시길 권합니다.
📚 참고 출처 (2026년 8월 29일 확인 · mcp 2.1.1 · Python 3.12.10 · Claude Code 2.1.204)
· MCP Python SDK — Get started
· MCP Python SDK — v1 → v2 마이그레이션 가이드
· modelcontextprotocol/python-sdk (README)
· Claude Code — MCP

COMMENTS