Skip to main content
Glama
HumairaShaista

weather-learning-server

Weather MCP 학습

점진적 학습 프로젝트로, 일반 LLM 애플리케이션에서 시작하여 Model Context Protocol(MCP)을 통해 날씨 기능을 제공하는 경로를 보여줍니다.

학습 진행 단계

  1. 일반 LLM 애플리케이션 — Ollama를 통해 로컬 오픈소스 모델과 채팅

  2. 전통적인 날씨 API 앱 — Open-Meteo 클라이언트(2A 단계) + 직접 LLM 오케스트레이션(2B 단계)

  3. Weather MCP 서버 — stdio를 통해 MCP 도구로 날씨 노출(3단계)

  4. MCP 클라이언트/에이전트 — 명시적 도구 클라이언트(4A 단계) + 모델 선택 도구(4B 단계)

이 저장소는 현재 1단계부터 4B단계까지 구현되어 있습니다.

Related MCP server: MCP Weather Server Demo

요구 사항

  • Python 3.12 이상

  • Ollama (또는 OpenAI 호환 로컬 서버)

  • 도구 호출을 지원하는 로컬 오픈소스 모델(기본값: qwen2.5:7b)

OpenAI나 Gemini 계정이 필요하지 않습니다.

설정

1. Ollama 설치 및 시작

https://ollama.com에서 설치한 후, 모델을 가져옵니다:

ollama pull qwen2.5:7b

또는 이미 가지고 있는 Responses-API 도구 지원 모델(ollama list)을 사용하고, .env 파일에서 LLM_MODEL을 해당 이름으로 설정하세요.

Ollama가 실행 중인지 확인하세요(macOS에서는 설치 후 일반적으로 자동 실행됩니다):

ollama list

2. 가상 환경 생성

python3 -m venv .venv
source .venv/bin/activate

Windows에서:

python -m venv .venv
.venv\Scripts\activate

3. 의존성 설치

pip install -e ".[dev]"

4. 환경 변수 설정

cp .env.example .env

.env 파일의 기본값은 로컬 Ollama를 대상으로 합니다:

LLM_BASE_URL=http://localhost:11434/v1
LLM_API_KEY=ollama
LLM_MODEL=qwen2.5:7b
  • LLM_BASE_URL — OpenAI 호환 API URL(위에 Ollama 기본값 표시, Chat Completions 및 Responses에서 사용)

  • LLM_API_KEY — 클라이언트 라이브러리에서 필요; Ollama는 무시함(비어 있지 않은 값이면 작동)

  • LLM_MODELollama list의 로컬 모델 이름(4B 단계 도구 호출은 qwen2.5:7b에서 잘 작동)

다른 옵션: LM Studio, vLLM 또는 OpenAI 채팅 API를 지원하는 모든 서버 — LLM_BASE_URLLLM_MODEL만 변경하면 됩니다.

2A 단계: Open-Meteo 날씨 클라이언트

app/weather_client.py는 두 단계로 Open-Meteo와 통신합니다(LLM 없음, MCP 없음):

  1. 지오코딩GET https://geocoding-api.open-meteo.com/v1/search는 도시 이름(선택적 주/지역 및 국가 포함)을 위도, 경도, 정식 이름, 행정 구역, 국가 및 시간대로 변환합니다.

  2. 예보GET https://api.open-meteo.com/v1/forecast는 해당 좌표를 사용하여 현재 날씨(온도, 습도, 바람, WMO 날씨 코드)를 가져옵니다.

호출자는 원시 제공자 JSON이 아닌 타입이 지정된 모델(Location, CurrentWeather, WeatherResult)을 받습니다. WMO 날씨 코드 → 텍스트 변환은 한 곳(WMO_WEATHER_CODES / weather_condition_from_code)에 있습니다.

예시(비동기):

from app.weather_client import get_current_weather

result = await get_current_weather("Berlin")
print(result.location.name, result.current.temperature, result.current.condition)

2B 단계: 직접 날씨 + LLM 애플리케이션

app/direct_weather_app.py전통적인 LLM 앱입니다: 사용자 코드가 날씨 API를 호출할 시점을 결정한 다음, 해당 결과를 LLM에 전달하여 친근한 요약을 생성합니다.

User
  → direct_weather_app
      → Open-Meteo   (application-controlled)
      → LLM          (summarize only the supplied payload)
  → Response

실행 방법

가상 환경이 활성화되고, Ollama가 실행 중이며, Open-Meteo에 네트워크 접근이 가능한 상태에서:

python -m app.direct_weather_app "San Francisco"

선택적 명확화:

python -m app.direct_weather_app "Springfield" --state Illinois --country US

또는 콘솔 스크립트:

direct-weather "San Francisco"

stderr에서 오케스트레이션 단계를 볼 수 있습니다:

  1. 애플리케이션이 도시를 수신함

  2. 애플리케이션이 날씨 제공자를 호출함

  3. 애플리케이션이 구조화된 날씨를 수신함

  4. 애플리케이션이 날씨 컨텍스트를 LLM에 전송함

stdout은 구조화된 날씨 블록과 LLM 요약을 표시합니다.

일반 LLM 애플리케이션과의 차이점

1단계 plain_llm_app

2B단계 direct_weather_app

날씨 데이터

없음 — 모델에 실시간 날씨 없음

먼저 Open-Meteo에서 가져옴

누가 날씨를 호출?

아무도 안 함

애플리케이션 코드(명시적)

LLM 역할

자유 형식 프롬프트에 답변

권위 있는 페이로드 요약하기

MCP / 도구

아니요

아니요

중요한 학습 포인트: LLM은 날씨 도구를 발견하거나 호출하지 않습니다. 애플리케이션이 Open-Meteo를 오케스트레이션한 다음, LLM에게 결과를 표현하도록 요청합니다. 프롬프트는 모델에게 페이로드가 권위 있으며 누락된 사실을 지어내지 말라고 알려줍니다.

3단계: Weather MCP 서버

app/mcp_server.py는 기존 weather_client를 MCP 도구로 노출합니다. 서버는 기능만 제공합니다 — LLM과 통신하거나 대화를 관리하지 않습니다.

사용된 공식 SDK 버전 및 API

이 프로젝트 환경에서 검사됨:

항목

패키지

PyPI의 공식 mcp (modelcontextprotocol/python-sdk)

설치된 버전

2.0.0

서버 클래스

mcp.serverMCPServer

사용 안 함

타사 fastmcp 패키지; 이전 v1 FastMCP 가져오기 경로

from mcp.server import MCPServer

mcp = MCPServer("weather-learning-server")

서버 책임

  • MCP 클라이언트에 도구 광고(도구 검색)

  • get_current_weather 도구 호출 수락

  • app.weather_client에 위임(Open-Meteo 코드 중복 없음)

  • 구조화된 날씨 페이로드 반환(또는 안전한 도구 오류)

  • 이 로컬 학습 POC를 위해 stdio를 통해 MCP 통신

노출된 도구 계약: get_current_weather

인수

이름

유형

필수

설명

city

문자열

도시 또는 장소 이름

state_or_region

문자열

아니요

명확화를 위한 주/행정 구역

country

문자열

아니요

국가 이름 또는 ISO-3166-1 alpha-2 코드

구조화된 결과 필드

resolved_location, region, country, latitude, longitude, temperature, apparent_temperature(사용 가능한 경우), condition, wind_speed, observation_time, timezone, units

서버 시작 방법

python -m app.mcp_server

또는:

weather-mcp-server

stdio를 사용하면 프로세스는 stdin/stdout에서 MCP 호스트를 기다립니다. 터미널에서 단독으로 실행하면 "멈춘" 것처럼 보입니다 — 이는 정상입니다.

stdio 전송 작동 방식(개념적으로)

MCP host / Inspector
   ├── spawns: python -m app.mcp_server
   ├── writes JSON-RPC MCP messages → server stdin
   └── reads JSON-RPC MCP messages  ← server stdout
  • 이 POC에는 포트와 HTTP가 없음

  • stdout은 프로토콜 와이어입니다(일반 앱 출력을 print()로 출력하지 마세요)

  • 로그는 stderr에 속함

공식 MCP Inspector로 독립 테스트

다음에 대해 확인됨:

  • 공식 mcp 2.0.0 (MCPServer)

  • 공식 Inspector 패키지 @modelcontextprotocol/inspector

  • Node.js 22.19+ (현재 Inspector 문서에서 필요)

  • Open-Meteo에 대한 네트워크 접근

전제 조건

cd weather-mcp-learning
python3 -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"   # includes mcp[cli]

Node/npx 확인:

node --version   # need 22.19.0 or newer
npx --version

시스템 node/npx가 손상되었거나 너무 오래된 경우, nvm(또는 이에 상응하는 것)을 통해 최신 Node를 사용한 다음, npxPATH에서 먼저 오도록 하세요.

옵션 A — mcp dev를 통한 웹 UI(공식 SDK 도우미)

venv가 활성화된 프로젝트 루트에서(mcp devuv run을 통해 서버를 시작하므로 uv도 필요):

mcp dev app/mcp_server.py --with-editable .

예상:

  1. 터미널에 MCP Inspector Web is up and running at: http://localhost:6274?MCP_INSPECTOR_API_TOKEN=...와 같은 내용이 출력됨

  2. 브라우저가 Inspector를 염

  3. Inspector가 로컬 stdio 서버(weather-learning-server)를 시작/연결

  4. 세션이 초기화됨(서버 이름/지침 표시)

  5. 도구 열기 → 목록에 get_current_weather 표시

  6. 도구 선택 → UI에 스키마의 docstring/설명 및 입력 필드 표시(city 필수; state_or_region / country 선택 사항)

  7. city = San Francisco 설정 → 도구 실행

  8. 결과 창에 resolved_location, region, temperature, condition, units 등과 같은 구조화된 콘텐츠 표시

--with-editable .는 이 프로젝트를 mcp dev가 빌드하는 임시 환경에 설치하여 import app...이 작동하도록 합니다.

옵션 B — Inspector + 프로젝트 구성을 통한 웹 UI

저장소 루트의 mcp-inspector.json은 Inspector를 로컬 stdio 서버로 안내합니다:

npx -y @modelcontextprotocol/inspector --config ./mcp-inspector.json --server weather-learning-server

출력된 http://localhost:6274?... URL을 열고, 세션이 연결되었는지 확인한 다음, 옵션 A와 같이 도구 탭을 사용합니다.

옵션 C — 스크립트 가능한 CLI 검사(브라우저 없음)

이는 터미널에서 동일한 프로토콜 단계를 증명하는 데 유용합니다. venv가 활성화되고 작동하는 Node 22.19+ npxPATH에 있는 프로젝트 루트에서 실행:

# 1–2. Start/connect over stdio + initialize session
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method initialize \
  --format json

예상 JSON에는 result.serverInfo 아래에 "name": "weather-learning-server"가 포함됩니다.

# 3–4. List tools; confirm description + input schema
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method tools/list \
  --format json

예상: get_current_weather라는 하나의 도구, inputSchema.requiredcity 포함, 실시간/현재 날씨 설명 포함.

# 5–6. Invoke with city = San Francisco; display structured result
npx -y @modelcontextprotocol/inspector --cli \
  --config ./mcp-inspector.json \
  --server weather-learning-server \
  --method tools/call \
  --tool-name get_current_weather \
  --tool-arg 'city=San Francisco' \
  --format json

예상: "isError": false 및 다음과 같은 필드가 있는 structuredContent:

{
  "resolved_location": "San Francisco",
  "region": "California",
  "country": "United States",
  "latitude": 37.77493,
  "longitude": -122.41942,
  "temperature": 13.8,
  "apparent_temperature": 12.1,
  "condition": "Fog",
  "wind_speed": 19.1,
  "observation_time": "2026-08-12T22:45",
  "timezone": "America/Los_Angeles",
  "units": {
    "temperature": "°C",
    "wind_speed": "km/h",
    "apparent_temperature": "°C"
  }
}

숫자 날씨 값은 시간이 지남에 따라 변경됩니다. 중요한 것은 필드 이름과 "isError": false입니다.

공식 Inspector 문서: MCP Inspector · SDK 실행 문서: 서버 실행

4A 단계: 기본 MCP 클라이언트(명시적 도구 호출)

app/basic_mcp_client.py비-LLM MCP 클라이언트입니다. 로컬 날씨 MCP 서버를 stdio를 통해 실행하고, 도구를 검색한 다음, 명시적으로 get_current_weather를 호출합니다.

basic_mcp_client
    → list_tools
    → get_current_weather   (hardcoded by this app — not chosen by an LLM)
    → MCP server (app.mcp_server via stdio)
    → Open-Meteo

중요: 이 클라이언트는 여전히 날씨 도구를 명시적으로 호출합니다. LLM은 아직 도구를 선택하지 않았습니다. 이는 이후 단계에서 다룹니다.

실행 방법

가상 환경이 활성화된 상태에서(MCP 서버를 직접 시작할 필요 없음 — 이 클라이언트가 생성합니다):

python -m app.basic_mcp_client "San Francisco"

선택적 필터:

python -m app.basic_mcp_client "Springfield" --state Illinois --country US

또는:

basic-mcp-client "San Francisco"

다음을 볼 수 있습니다:

  1. weather-learning-server에 대한 연결/프로토콜 정보

  2. 검색된 각 도구의 이름, 설명 및 입력 스키마

  3. get_current_weather에 대한 명시적 호출

  4. 구조화된 MCP 도구 결과 JSON

프로세스를 종료하면 MCP 세션과 하위 서버 프로세스가 정리됩니다.

4B 단계: OpenAI Responses 에이전트(모델 선택 MCP 도구)

app/mcp_agent.py는 날씨 MCP 서버에 연결하고, 런타임에 도구를 검색하고, 해당 정의를 공식 OpenAI Responses API를 통해 모델에 제공하고, MCP를 통해 모델이 요청한 모든 도구 호출을 실행하고, 도구 결과를 모델에 반환하고, 최종 답변을 출력합니다.

user question
  → mcp_agent
      → MCP list_tools          (discovery)
      → OpenAI Responses API    (question + tool schemas)
      → model may request tool(s)
      → MCP tools/call          (only discovered names)
      → Responses function_call_output
      → final natural-language answer

if "weather" in question, 도시 정규식 또는 하드코딩된 get_current_weather 호출이 없습니다. 모델이 도구 사용 여부를 선택합니다.

에이전트 루프(세부)

  1. MCP 세션 시작 — stdio를 통해 python -m app.mcp_server 생성; 클라이언트 초기화

  2. 도구 검색list_tools; 각 도구 이름/설명 기록

  3. 스키마 변환 — MCP 도구 → Responses type: "function" 도구

  4. 모델 턴client.responses.create(..., tools=..., tool_choice="auto")

  5. 출력 검사function_call 항목이 있는 경우:

    • 검색된 세트에 대해 도구 이름 검증

    • JSON 인수 구문 분석/검증

    • MCP 호출; 구조화된 결과 보존

    • previous_response_id와 함께 function_call_output 제출

  6. 반복 모델이 최종 텍스트 메시지를 반환할 때까지(또는 최대 반복 횟수에 도달)

  7. 최종 답변 출력 및 MCP 세션/하위 프로세스 종료

실행 방법

ollama pull qwen2.5:7b   # once, if needed
source .venv/bin/activate
python -m app.mcp_agent "What is the current weather in San Francisco?"
python -m app.mcp_agent "Explain what dependency injection is."

예상:

  • 날씨 질문 → 로그에 get_current_weather에 대한 model_requested_tools / tool_call 표시, 그 다음 날씨 답변

  • 의존성 주입 질문 → 로그에 도구 호출 없이 최종 응답 표시

stderr에서 [mcp-agent] 줄을 확인하세요: 검색, 모델 출력 유형, 도구 이름/인수/기간/결과. API 키는 절대 기록되지 않습니다.

일반 애플리케이션 실행

가상 환경이 활성화되고 Ollama가 실행 중인 상태에서:

python -m app.plain_llm_app

또는 사용자 정의 프롬프트 사용:

python -m app.plain_llm_app "What is the Model Context Protocol in one sentence?"

설치된 콘솔 스크립트를 사용할 수도 있습니다:

plain-llm "Hello!"

테스트 실행

pytest

프로젝트 구조

weather-mcp-learning/
  README.md
  .env.example
  .gitignore
  pyproject.toml
  mcp-inspector.json
  app/
    __init__.py
    config.py
    llm_client.py
    plain_llm_app.py
    weather_client.py
    direct_weather_app.py
    mcp_server.py
    basic_mcp_client.py
    mcp_agent.py
  tests/

참고 사항

  • 공식 openai Python 패키지는 OpenAI-호환 클라이언트로 사용됩니다 (이전에는 Chat Completions, Stage 4B에서는 Responses API). 요청은 설정된 LLM_BASE_URL(기본값은 Ollama)로 전송됩니다.

  • 날씨 조회는 httpx를 통해 Open-Meteo를 사용합니다 (app/weather_client.py).

  • Stage 2B (direct_weather_app.py)는 날씨 → LLM을 명시적으로 조정합니다. MCP나 도구 호출은 없습니다.

  • Stage 3은 공식 mcp 2.0.0 SDK (mcp.serverMCPServer)를 stdio를 통해 사용합니다. 타사 fastmcp 패키지는 사용하지 마십시오.

  • Stage 4A (basic_mcp_client.py)는 여전히 날씨 도구를 명시적으로 호출합니다 (LLM 도구 선택 없음).

  • Stage 4B (mcp_agent.py)는 모델이 Responses API를 통해 MCP 검색 후 도구를 선택하도록 합니다.

Install Server
F
license - not found
A
quality
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • OpenWeather MCP — wraps the OpenWeatherMap API (openweathermap.org)

  • Open-Meteo MCP — weather forecast + historical reanalysis + sister APIs

  • WeatherAPI.com MCP — wraps WeatherAPI.com (api.weatherapi.com)

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/HumairaShaista/Weather-MCP-Learning'

If you have feedback or need assistance with the MCP directory API, please join our Discord server