Back to Blog
BlogApril 6, 202683

첫 번째 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

Referenced Tools

Browse entries that are adjacent to the topics covered in this article.

Explore directory