FastMCP: 몇 분 만에 MCP 서버 구축하기 (2026)
AI 어시스턴트를 위한 맞춤형 MCP 서버를 구축하는 가장 빠른 방법
Hypereal로 구축 시작하기
단일 API를 통해 Kling, Flux, Sora, Veo 등에 액세스하세요. 무료 크레딧으로 시작하고 수백만으로 확장하세요.
신용카드 불필요 • 10만 명 이상의 개발자 • 엔터프라이즈 지원
FastMCP: 몇 분 만에 구축하는 MCP 서버 (2026)
Model Context Protocol (MCP)는 AI 어시스턴트를 외부 도구 및 데이터에 연결하기 위한 새로운 표준으로 떠오르고 있습니다. 하지만 MCP 서버를 처음부터 구축하는 과정은 전송 계층 관리, 직렬화, 프로토콜 세부 사항 처리 등 번거로운 작업이 많아 정작 중요한 기능 구현에 집중하기 어렵게 만듭니다.
FastMCP는 이 문제를 해결합니다. FastMCP는 Flask나 FastAPI 앱을 만드는 것과 유사하게 데코레이터를 사용하여 완벽하게 작동하는 MCP 서버를 구축할 수 있게 해주는 고수준 Python 프레임워크입니다. 이 가이드에서는 단 몇 분 만에 기본 상태에서 실제 작동하는 MCP 서버를 구축하는 방법을 보여줍니다.
FastMCP란 무엇인가요?
FastMCP는 MCP SDK를 개발자 친화적인 API로 감싼 오픈 소스 Python 라이브러리입니다. 프로토콜 메시지와 전송 계층을 수동으로 처리하는 대신, 데코레이터를 사용하여 간단한 Python 함수를 작성하기만 하면 됩니다.
| 기능 | 순수 MCP SDK | FastMCP |
|---|---|---|
| 서버 설정 | 약 30줄의 상형문구(Boilerplate) | 2줄 |
| 도구(Tool) 정의 | 수동 스키마 + 핸들러 | @mcp.tool() 데코레이터 |
| 리소스(Resource) 정의 | 수동 URI + 핸들러 | @mcp.resource() 데코레이터 |
| 타입 처리 | 수동 JSON Schema 작성 | 타입 힌트(Type hints)를 통한 자동 생성 |
| 테스트 | 수동 전송 모킹(Mock) | 내장 테스트 클라이언트 |
| 코드 줄 수 (간단한 서버 기준) | 80-100줄 | 15-20줄 |
설치
pip install fastmcp
FastMCP는 Python 3.10 이상 버전을 요구합니다.
첫 번째 MCP 서버 구축하기
단 15줄의 코드로 완성된 MCP 서버 예시입니다:
# server.py
from fastmcp import FastMCP
mcp = FastMCP("my-tools")
@mcp.tool()
def add(a: int, b: int) -> int:
"""두 숫자를 더합니다."""
return a + b
@mcp.tool()
def get_weather(city: str) -> str:
"""특정 도시의 현재 날씨를 가져옵니다."""
# 프로덕션 환경에서는 실제 날씨 API를 호출하세요.
return f"{city}의 날씨는 72F이며 맑습니다."
if __name__ == "__main__":
mcp.run()
이것으로 끝입니다. FastMCP는 다음 작업을 자동으로 수행합니다:
- 타입 힌트를 기반으로 JSON 스키마를 생성합니다.
- MCP 프로토콜(도구 목록 조회, 도구 호출, 에러 처리)을 관리합니다.
- Claude Code, Claude Desktop 및 기타 MCP 클라이언트와의 호환성을 위해 stdio 전송 방식을 설정합니다.
서버 실행
python server.py
Claude Code에 연결하기
.mcp.json 또는 Claude Code 구성 파일에 다음을 추가하세요:
{
"mcpServers": {
"my-tools": {
"command": "python",
"args": ["/path/to/server.py"]
}
}
}
또는 Claude Code CLI를 사용할 수도 있습니다:
claude mcp add my-tools python /path/to/server.py
핵심 개념
Tools (도구)
도구는 AI가 호출할 수 있는 함수입니다. 특정 작업을 수행하고 결과를 반환합니다.
from fastmcp import FastMCP
import httpx
mcp = FastMCP("dev-tools")
@mcp.tool()
def search_npm(query: str, limit: int = 5) -> str:
"""npm 레지스트리에서 패키지를 검색합니다."""
response = httpx.get(
f"https://registry.npmjs.org/-/v1/search",
params={"text": query, "size": limit}
)
results = response.json()["objects"]
lines = []
for pkg in results:
p = pkg["package"]
lines.append(f"- {p['name']} (v{p['version']}): {p.get('description', '설명 없음')}")
return "\n".join(lines)
@mcp.tool()
def run_sql(query: str, database: str = "main.db") -> str:
"""SQLite 데이터베이스에 대해 읽기 전용 SQL 쿼리를 실행합니다."""
import sqlite3
conn = sqlite3.connect(database)
conn.execute("PRAGMA query_only = ON")
cursor = conn.execute(query)
columns = [desc[0] for desc in cursor.description] if cursor.description else []
rows = cursor.fetchall()
conn.close()
if not rows:
return "결과가 없습니다."
header = " | ".join(columns)
separator = " | ".join(["---"] * len(columns))
data = "\n".join([" | ".join(str(cell) for cell in row) for row in rows])
return f"{header}\n{separator}\n{data}"
Resources (리소스)
리소스는 AI가 읽을 수 있는 데이터를 노출합니다. URI를 통해 식별됩니다.
@mcp.resource("config://app")
def get_app_config() -> str:
"""애플리케이션 구성을 반환합니다."""
import json
with open("config.json") as f:
return json.dumps(json.load(f), indent=2)
@mcp.resource("file://{path}")
def read_file(path: str) -> str:
"""프로젝트 디렉토리에서 파일을 읽습니다."""
with open(path) as f:
return f.read()
@mcp.resource("db://schema")
def get_database_schema() -> str:
"""데이터베이스 스키마를 반환합니다."""
import sqlite3
conn = sqlite3.connect("main.db")
cursor = conn.execute(
"SELECT sql FROM sqlite_master WHERE type='table'"
)
schemas = [row[0] for row in cursor.fetchall()]
conn.close()
return "\n\n".join(schemas)
Prompts (프롬프트)
프롬프트는 AI가 사용할 수 있는 재사용 가능한 프롬프트 템플릿입니다.
@mcp.prompt()
def code_review(code: str, language: str = "python") -> str:
"""코드 리뷰 프롬프트를 생성합니다."""
return f"""다음 {language} 코드를 아래 항목에 대해 리뷰해 주세요:
1. 보안 취약점
2. 성능 문제
3. 코드 스타일 및 모범 사례
4. 잠재적 버그
코드:
```{language}
{code}
수정 사항에 대한 코드 예시와 함께 구체적이고 실행 가능한 피드백을 제공해 주세요."""
@mcp.prompt() def explain_error(error_message: str, stack_trace: str = "") -> str: """에러 설명 프롬프트를 생성합니다.""" prompt = f"이 에러를 설명하고 해결 방법을 제안해 주세요:\n\n에러: {error_message}" if stack_trace: prompt += f"\n\n스택 트레이스:\n{stack_trace}" return prompt
## 실전 예제: GitHub MCP 서버
GitHub 저장소 도구를 제공하는 보다 완성도 높은 MCP 서버 예제입니다:
```python
# github_mcp.py
from fastmcp import FastMCP
import httpx
import os
mcp = FastMCP("github-tools")
GITHUB_TOKEN = os.environ.get("GITHUB_TOKEN", "")
HEADERS = {"Authorization": f"Bearer {GITHUB_TOKEN}"} if GITHUB_TOKEN else {}
@mcp.tool()
def search_repos(query: str, limit: int = 5) -> str:
"""GitHub 저장소를 검색합니다."""
response = httpx.get(
"https://api.github.com/search/repositories",
params={"q": query, "per_page": limit},
headers=HEADERS
)
repos = response.json().get("items", [])
lines = []
for repo in repos:
lines.append(
f"- [{repo['full_name']}]({repo['html_url']}) "
f"({repo['stargazers_count']} stars): {repo['description'] or '설명 없음'}"
)
return "\n".join(lines) or "저장소를 찾을 수 없습니다."
@mcp.tool()
def get_repo_readme(owner: str, repo: str) -> str:
"""GitHub 저장소의 README 내용을 가져옵니다."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/readme",
headers={**HEADERS, "Accept": "application/vnd.github.raw+json"}
)
if response.status_code == 200:
return response.text
return f"에러: README를 가져올 수 없습니다 ({response.status_code})"
@mcp.tool()
def list_issues(owner: str, repo: str, state: str = "open", limit: int = 10) -> str:
"""GitHub 저장소의 이슈 목록을 조회합니다."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/issues",
params={"state": state, "per_page": limit},
headers=HEADERS
)
issues = response.json()
lines = []
for issue in issues:
labels = ", ".join([l["name"] for l in issue.get("labels", [])])
lines.append(f"- #{issue['number']}: {issue['title']} [{labels}]")
return "\n".join(lines) or "이슈가 없습니다."
@mcp.tool()
def get_file_contents(owner: str, repo: str, path: str, ref: str = "main") -> str:
"""GitHub 저장소에서 파일 내용을 가져옵니다."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}/contents/{path}",
params={"ref": ref},
headers={**HEADERS, "Accept": "application/vnd.github.raw+json"}
)
if response.status_code == 200:
return response.text
return f"에러: 파일을 가져올 수 없습니다 ({response.status_code})"
@mcp.resource("github://repos/{owner}/{repo}/info")
def get_repo_info(owner: str, repo: str) -> str:
"""GitHub 저장소에 대한 기본 정보를 가져옵니다."""
response = httpx.get(
f"https://api.github.com/repos/{owner}/{repo}",
headers=HEADERS
)
repo_data = response.json()
return (
f"이름: {repo_data['full_name']}\n"
f"별점: {repo_data['stargazers_count']}\n"
f"언어: {repo_data['language']}\n"
f"설명: {repo_data['description']}\n"
f"URL: {repo_data['html_url']}"
)
if __name__ == "__main__":
mcp.run()
등록 방법:
{
"mcpServers": {
"github": {
"command": "python",
"args": ["/path/to/github_mcp.py"],
"env": {
"GITHUB_TOKEN": "ghp_your_token"
}
}
}
}
MCP 서버 테스트하기
FastMCP에는 내장 테스트 클라이언트가 포함되어 있습니다:
# test_server.py
import asyncio
from fastmcp import Client
async def test():
async with Client("python server.py") as client:
# 사용 가능한 도구 목록 조회
tools = await client.list_tools()
print(f"사용 가능한 도구: {[t.name for t in tools]}")
# 도구 호출
result = await client.call_tool("add", {"a": 5, "b": 3})
print(f"5 + 3 = {result}")
# 리소스 목록 조회
resources = await client.list_resources()
print(f"사용 가능한 리소스: {[r.uri for r in resources]}")
asyncio.run(test())
FastMCP vs. 순수 MCP SDK
다음은 두 가지 방식으로 정의된 동일한 도구의 비교입니다:
순수 MCP SDK
from mcp.server import Server
from mcp.types import Tool, TextContent
import json
server = Server("my-server")
@server.list_tools()
async def list_tools():
return [
Tool(
name="add",
description="Add two numbers",
inputSchema={
"type": "object",
"properties": {
"a": {"type": "integer", "description": "First number"},
"b": {"type": "integer", "description": "Second number"}
},
"required": ["a", "b"]
}
)
]
@server.call_tool()
async def call_tool(name, arguments):
if name == "add":
result = arguments["a"] + arguments["b"]
return [TextContent(type="text", text=str(result))]
FastMCP
from fastmcp import FastMCP
mcp = FastMCP("my-server")
@mcp.tool()
def add(a: int, b: int) -> int:
"""두 숫자를 더합니다."""
return a + b
FastMCP 버전은 25줄 이상의 코드를 4줄로 줄여줍니다. 도구가 많은 서버의 경우, 이 차이는 비약적으로 커집니다.
MCP 서버 구축을 위한 팁
- 작게 시작하세요. 한두 개의 도구를 먼저 만들고 테스트한 다음 확장하세요.
- 타입 힌트를 사용하세요. FastMCP는 타입 힌트에서 자동으로 JSON 스키마를 생성합니다.
- 설명을 잘 작성하세요(Docstrings). AI는 도구의 설명을 읽고 언제 사용할지 결정합니다.
- 예외 처리를 부드럽게 하세요. 예외를 발생시키기보다는 에러 메시지를 문자열로 반환하는 것이 좋습니다.
- 도구의 역할을 집중시키세요. 하나의 도구는 한 가지 일을 잘 수행해야 합니다. 복잡한 작업은 AI가 도구들을 조합하여 해결하게 하세요.
- 환경 변수를 활용하세요. API 키와 설정값은 MCP 구성의
env를 통해 전달하세요.
마무리하며
FastMCP는 MCP 서버 구축 시 발생하는 반복적인 작업을 제거하여 개발자가 실제 기능 구현에 집중할 수 있게 해줍니다. API를 래핑하거나, 데이터베이스를 연결하거나, 커스텀 개발 도구를 구축할 때 아이디어를 단 몇 분 만에 실제 작동하는 MCP 서버로 구현할 수 있습니다.
이미지, 비디오, 오디오 또는 아바타와 같은 미디어 생성이 필요한 MCP 도구를 구축 중이라면, Hypereal AI를 무료로 체험해 보세요. 카드 등록 없이 35 크레딧을 제공합니다. Hypereal AI의 REST API는 모든 MCP 서버에 쉽게 통합되어 AI 기반 미디어 생성을 지원합니다.
