Back to Blog
BlogApril 6, 20262

첫 번째 MCP 서버 구축 방법: 단계별 튜토리얼

첫 번째 MCP 서버 구축 방법: 단계별 튜토리얼

필수 조건

시작하기 전에 다음 사항을 준비하세요:

  • Python 3.10 이상이 설치되어 있어야 합니다.
  • Python 함수와 비동기 코드에 대한 기본적인 이해가 필요합니다.
  • uv (빠른 Python 패키지 관리자) – curl -LsSf https://astral.sh/uv/install.sh | sh 명령으로 설치하세요.
  • Claude Desktop과 같은 MCP 클라이언트 (claude.ai/download에서 다운로드하고 최신 상태로 유지하세요).
  • 텍스트 편집기 또는 IDE.

MCP 사전 경험은 필요하지 않습니다. 실용적인 날씨 MCP 서버를 만들어 AI가 National Weather Service API를 통해 미국의 실시간 날씨 경보 및 예보를 조회할 수 있도록 합니다.

단계 1: 환경 설정

새로운 프로젝트 디렉토리를 생성하고 uv로 초기화하세요:

mkdir weather-mcp-server
cd weather-mcp-server
uv init
uv venv
source .venv/bin/activate  # Windows에서: .venv\Scripts\activate
uv add "mcp[cli]" httpx

이렇게 하면 공식 MCP Python SDK(FastMCP)와 API 호출용 httpx가 설치됩니다. 이제 프로젝트에 pyproject.toml 파일과 가상 환경이 생성되었습니다.

예상 출력: 새로운 .venv 폴더와 uv.lock 파일에 나열된 종속성.

단계 2: MCP 서버 코드 작성

주요 파일을 생성하세요:

touch weather.py

다음의 완전하고 바로 실행 가능한 코드를 weather.py에 붙여넣으세요:

from typing import Any
import httpx
from mcp.server.fastmcp import FastMCP

# MCP 서버 초기화
mcp = FastMCP("weather")

NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"

# NWS API를 안전하게 호출하는 헬퍼 함수
async def make_nws_request(url: str) -> dict[str, Any] | None:
    headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
    async with httpx.AsyncClient() as client:
        try:
            response = await client.get(url, headers=headers, timeout=30.0)
            response.raise_for_status()
            return response.json()
        except Exception:
            return None

# AI를 위해 날씨 경보를 보기 좋게 포맷팅
def format_alert(feature: dict) -> str:
    props = feature["properties"]
    return f"""
Event: {props.get("event", "Unknown")}
Area: {props.get("areaDesc", "Unknown")}
Severity: {props.get("severity", "Unknown")}
Description: {props.get("description", "No description available")}
Instructions: {props.get("instruction", "No specific instructions provided")}
"""

# 도구 1: 미국 주의 활성화된 날씨 경보 가져오기
@mcp.tool()
async def get_alerts(state: str) -> str:
    """미국 주의 현재 날씨 경보 가져오기 (예: "CA" 또는 "TX")."""
    url = f"{NWS_API_BASE}/alerts/active/area/{state.upper()}"
    data = await make_nws_request(url)
    if not data or "features" not in data:
        return "경보를 가져올 수 없거나 경보가 없습니다."
    if not data["features"]:
        return f"{state.upper()}에 활성화된 경보가 없습니다."
    alerts = [format_alert(f) for f in data["features"]]
    return "\n---\n".join(alerts)

도구 2: 위도/경도 기반 5일 예보 가져오기

@mcp.tool() async def get_forecast(latitude: float, longitude: float) -> str: """특정 위도와 경도의 날씨 예보를 가져옵니다.""" points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}" points_data = await make_nws_request(points_url) if not points_data: return "이 위치의 예보 데이터를 가져올 수 없습니다." forecast_url = points_data["properties"]["forecast"] forecast_data = await make_nws_request(forecast_url) if not forecast_data: return "상세 예보를 가져올 수 없습니다." periods = forecast_data["properties"]["periods"][:5] forecasts = [] for period in periods: forecast = f""" {period["name"]}: 기온: {period["temperature"]}°{period["temperatureUnit"]} 바람: {period["windSpeed"]} {period["windDirection"]} 예보: {period["detailedForecast"]} """ forecasts.append(forecast) return "\n---\n".join(forecasts)

def main(): mcp.run(transport="stdio")

if name == "main": main()


**핵심 개념 설명:**
- `@mcp.tool()` 데코레이터는 일반 비동기 함수를 AI가 탐색하고 호출할 수 있는 MCP 도구로 변환합니다.
- 서버는 **stdio**(표준 입출력)를 통해 실행됩니다 – 로컬 MCP 서버의 기본 설정입니다.
- 모든 로깅은 stderr로 전송되어야 합니다(FastMCP가 자동으로 처리합니다).

## 3단계: 서버 로컬 테스트

서버 실행:

```bash
uv run weather.py

예상 출력: 터미널은 열린 채로 조용히 유지됩니다(stdio 서버의 정상적인 현상). MCP 클라이언트가 연결될 때만 JSON-RPC 메시지가 표시됩니다.

다음 단계를 위해 이 터미널을 실행 상태로 유지하세요.

4단계: MCP 서버를 Claude Desktop에 연결

  1. Claude Desktop을 엽니다.
  2. 다음 위치에 있는 설정 파일을 생성하거나 편집합니다:
    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json

다음 항목을 정확히 추가합니다(/ABSOLUTE/PATH/TO/weather-mcp-server를 실제 폴더 경로로 대체하세요):

{
  "mcpServers": {
    "weather": {
      "command": "uv",
      "args": [
        "--directory",
        "/ABSOLUTE/PATH/TO/weather-mcp-server",
        "run",
        "weather.py"
      ]
    }
  }
}
  1. Claude Desktop을 완전히 종료(macOS에서는 Cmd+Q, Windows에서는 시스템 트레이에서 닫기)하고 재시작합니다.
  2. Claude에서 "파일, 커넥터 등 추가"커넥터 위에 마우스를 올리면 → **"weather"**가 목록에 표시되어야 합니다.

5단계: AI와 함께 MCP 서버 사용하기

Claude Desktop에서 다음 프롬프트를 시도해보세요:

  • "텍사스의 활성 날씨 경보는 무엇인가요?"
  • "샌프란시스코의 예보를 알려주세요(위도 37.77, 경도 -122.41 사용)."
  • "캘리포니아의 경보를 확인하고 대비가 필요한지 알려주세요."

Claude는 자동으로 도구를 탐색하고, 처음 사용 시 승인을 요청하며, 서식이 지정된 결과를 반환합니다.

예상 동작: AI는 백그라운드에서 도구를 호출하고 자연어 응답을 표시합니다.

일반적인 문제 해결 방법

  • Claude에서 서버가 표시되지 않는 경우:

    • JSON이 유효한지 재확인하세요 (후행 쉼표가 없어야 합니다).
    • 설정에서 절대 경로를 사용하세요.
    • Claude를 완전히 재시작하세요.
    • 로그를 확인하세요: ~/Library/Logs/Claude/mcp*.log (macOS) 또는 Windows에서 해당 경로.
  • API 오류 또는 데이터가 없는 경우:

    • NWS API는 미국 위치에만 작동합니다.
    • 두 글자 주 코드를 사용하세요 (CA, TX 등).
    • 좌표는 유효한 위도/경도여야 합니다.
  • "명령어를 찾을 수 없음":

    • uv가 PATH에 있고 가상 환경이 활성화되었는지 확인하세요.
    • uv --version을 실행하여 설치를 확인하세요.

— — 타임아웃 또는 느린 응답:

  • 필요한 경우 make_nws_request에서 타임아웃을 늘리세요.

  • NWS에는 속도 제한이 있으므로 프로덕션 환경에서 과도한 요청을 피하세요.

  • 권한 문제:

    • macOS에서는 시스템 설정 → 개인 정보 보호 및 보안에서 Claude Desktop에 전체 디스크 접근 권한을 부여하세요.

다음 단계

.

  • 더 많은 도구 추가하기: 동일한 @mcp.tool() 패턴을 사용하여 데이터베이스, GitHub, Slack 또는 사용자 정의 API용 도구를 만드세요.
  • 리소스와 프롬프트 추가하기: 파일과 같은 데이터와 재사용 가능한 지침을 위해 mcp.resource()mcp.prompt()를 사용하세요.

원격으로 배포하기: HTTP/SSE 전송 방식으로 전환하고 AWS Lambda, Vercel 또는 모든 서버에 호스팅하세요 (FastMCP는 stateless_http=True를 지원합니다).

  • 여러 언어 지원하기: 동일한 기능을 위해 공식 TypeScript, Go 또는 Rust SDK를 시도해 보세요.
  • 서버 공유하기: 저장소를 공개하여 다른 사용자가 npx나 Docker를 통해 추가할 수 있게 하세요.

이제 호환 가능한 모든 AI 클라이언트가 사용할 수 있는 완전히 기능적인 MCP 서버가 준비되었습니다. 실험해보고, 도구를 확장하며, 강력한 AI 통합을 오늘부터 구축해 보세요!

Share this article