# Implementing a Weather Information MCP Server in Python [Video Tutorial](https://www.bilibili.com/video/BV1zYGozgEHc) ## The Problem Scenario Before we begin, consider this common situation: I'm planning to attend the Arknights "Rusty Shadows" convention next Saturday in Hangzhou and want to check the weather forecast. When I ask an LLM about Saturday's weather, I get this response:
This "teach you to fish" approach isn't helpful for simple everyday queries. While there are many weather apps available, how can we integrate weather data directly into LLMs to get actionable answers? ## Introduction 👉 [Previous Guide](https://zhuanlan.zhihu.com/p/32593727614) In our last tutorial, we covered MCP fundamentals. Now, we'll develop our first MCP server to bridge existing applications/services with LLMs. For efficient development, we'll use OpenMCP - an integrated MCP testing tool I recently open-sourced: [OpenMCP Announcement](https://zhuanlan.zhihu.com/p/1894785817186121106) OpenMCP GitHub: https://github.com/LSTM-Kirigaya/openmcp-client (Stars appreciated! :D) ### Initial Setup First, install the UV tool (a Conda alternative): ```bash pip install uv uv # Verify installation ``` Create a new project: ```bash mkdir simple-mcp && cd simple-mcp uv init uv add mcp "mcp[cli]" ``` Install the OpenMCP plugin in VSCode:
### Basic MCP Server Create `simple_mcp.py`: ```python from mcp.server.fastmcp import FastMCP mcp = FastMCP('Weather MCP Server', version="1.0.0") @mcp.tool( name='weather', description='Get weather information for specified city' ) def get_weather(city: str) -> str: """Weather query protocol - returns formatted string""" return f"Weather in {city}: Sunny, 25°C" # Additional example tools/resources omitted for brevity ``` Test the server: ```bash uv run mcp run simple_mcp.py ``` ### Connecting with OpenMCP Click the purple OpenMCP icon in VSCode to launch the debugger. Verify connection status (green indicator):
## Developing the Weather Function ### Tool Debugging Our initial weather tool just returns static data. Let's test it in OpenMCP:
### Interactive Testing Configure your LLM API in OpenMCP:
Test without tools: ``` What's the temperature in Hangzhou? ``` Then with our weather tool enabled:
Notice the two-step process: 1. LLM calls our weather tool with `{"city": "Hangzhou"}` 2. Our server responds with formatted weather data 3. LLM generates final answer ## Production-Ready Implementation Here's a complete weather implementation using a real API: ```python import requests import json from typing import NamedTuple, Optional from mcp.server.fastmcp import FastMCP class CityWeather(NamedTuple): city_name_en: str city_name_cn: str city_code: str temp: str wd: str ws: str sd: str aqi: str weather: str def get_city_weather(city_code: str) -> Optional[CityWeather]: """Get weather by city code""" try: url = f"http://d1.weather.com.cn/sk_2d/{city_code}.html" headers = { "User-Agent": "Mozilla/5.0...", "Host": "d1.weather.com.cn", "Referer": "http://www.weather.com.cn/" } response = requests.get(url, headers=headers) response.raise_for_status() content = response.text.encode('latin1').decode('unicode_escape') json_str = content[content.find("{"):] weather_data = json.loads(json_str) return CityWeather( city_name_en=weather_data.get("nameen", ""), city_name_cn=weather_data.get("cityname", "").encode('latin1').decode('utf-8'), city_code=weather_data.get("city", ""), temp=weather_data.get("temp", ""), wd=weather_data.get("wd", "").encode('latin1').decode('utf-8'), ws=weather_data.get("ws", "").encode('latin1').decode('utf-8'), sd=weather_data.get("sd", ""), aqi=weather_data.get("aqi", ""), weather=weather_data.get("weather", "").encode('latin1').decode('utf-8') ) except Exception as e: print(f"Weather query failed: {str(e)}") return None mcp = FastMCP('Weather MCP', version="1.0.0") @mcp.tool( name='get_weather_by_city_code', description='Get weather by city code (integer)' ) def get_weather_by_code(city_code: int) -> str: weather_data = get_city_weather(str(city_code)) return str(weather_data) ``` Key Notes: 1. Use `int` type for numeric IDs to ensure proper JSON serialization 2. Follow Python naming conventions for tool names ### Final Test
Success! We've built a fully functional weather MCP service. For production deployments, consider using SSE connections for better scalability (covered in future tutorials). OpenMCP GitHub: https://github.com/LSTM-Kirigaya/openmcp-client