CATEGORY

카테고리 (648)
AI (46)
Language & Specs (260)
FrameWork (36)
Library (20)
App (41)
Git (10)
Build & Dependency (2)
AWS (15)
DataBase (45)
OS (33)
Tool (17)
IT (120)
반응형
SEEMINGLY ONLINE

Seemingly
Online

이모저모 방방곡곡 두루두루 개발지식 저장소

RECENT POSTS

AI/Claude

mcp 서버 만들기 python — 15줄 코드와 연결 확인

반응형

파이썬으로 MCP 서버를 만드는 건 함수 두 개면 끝입니다. pip install "mcp[cli]" 로 공식 SDK를 깔고, MCPServer 객체를 만든 뒤 함수 위에 @mcp.tool() 을 붙이면 그게 곧 도구가 됩니다. 다만 지금 검색해서 나오는 예제 대부분은 그대로 붙여넣으면 실행조차 안 됩니다pip install mcp 가 이제 2.x를 설치하는데, 여기서 FastMCPMCPServer 로 이름이 바뀌었기 때문입니다. 아래는 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 FastMCP2.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에서 실제로 확인해 보니 영문 printInvalid 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에서 바뀐 FastMCPMCPServer, 그리고 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