https://modelcontextprotocol.io/docs/2026-07-28/develop/build-server#python
https://www.youtube.com/watch?v=mrKwifmqtWc
uv - инструмент для установки разных версий питона для разных проектов
Для начала давайте установим uv и настроим наш проект и среду Python:
Код: Выделить всё
curl -LsSf https://astral.sh/uv/install.sh | shКод: Выделить всё
uv --versionКод: Выделить всё
uv python install 3.11Теперь давайте создадим и настроим наш проект:
Код: Выделить всё
# Создать новый каталог для нашего проекта
uv init weather
cd weather
# Создать виртуальную среду и активировать её
uv venv
source .venv/bin/activate
# Установить зависимости
uv add «mcp[cli]»
# Создать файл сервера
touch weather.py
Настройка сервера
Импорт пакетов и настройка экземпляра
Добавьте следующий код в начало файла weather.py:
Код: Выделить всё
from typing import Any
import httpx2
from mcp.server import MCPServer
# Initialize MCPServer
mcp = MCPServer("weather")
# Constants
NWS_API_BASE = "https://api.weather.gov"
USER_AGENT = "weather-app/1.0"Класс MCPServer использует подсказки типов и docstrings в Python для автоматической генерации определений инструментов, что упрощает создание и сопровождение инструментов MCP.
Вспомогательные функции
Далее добавим наши вспомогательные функции для запроса и форматирования данных из API Национальной метеорологической службы:
Код: Выделить всё
async def make_nws_request(url: str) -> dict[str, Any] | None:
"""Make a request to the NWS API with proper error handling."""
headers = {"User-Agent": USER_AGENT, "Accept": "application/geo+json"}
async with httpx2.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
def format_alert(feature: dict) -> str:
"""Format an alert feature into a readable string."""
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")}
"""Обработчик выполнения инструмента отвечает за фактическое выполнение логики каждого инструмента. Добавим его:
Код: Выделить всё
@mcp.tool()
async def get_alerts(state: str) -> str:
"""Get weather alerts for a US state.
Args:
state: Two-letter US state code (e.g. CA, NY)
"""
url = f"{NWS_API_BASE}/alerts/active/area/{state}"
data = await make_nws_request(url)
if not data or "features" not in data:
return "Unable to fetch alerts or no alerts found."
if not data["features"]:
return "No active alerts for this state."
alerts = [format_alert(feature) for feature in data["features"]]
return "\n---\n".join(alerts)
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
# First get the forecast grid endpoint
points_url = f"{NWS_API_BASE}/points/{latitude},{longitude}"
points_data = await make_nws_request(points_url)
if not points_data:
return "Unable to fetch forecast data for this location."
# Get the forecast URL from the points response
forecast_url = points_data["properties"]["forecast"]
forecast_data = await make_nws_request(forecast_url)
if not forecast_data:
return "Unable to fetch detailed forecast."
# Format the periods into a readable forecast
periods = forecast_data["properties"]["periods"]
forecasts = []
for period in periods[:5]: # Only show next 5 periods
forecast = f"""
{period["name"]}:
Temperature: {period["temperature"]}°{period["temperatureUnit"]}
Wind: {period["windSpeed"]} {period["windDirection"]}
Forecast: {period["detailedForecast"]}
"""
forecasts.append(forecast)
return "\n---\n".join(forecasts)Запуск сервера
И, наконец, инициализируем и запустим сервер:
Код: Выделить всё
if __name__ == "__main__":
mcp.run(transport="stdio")Теперь давайте протестируем ваш сервер с помощью существующего хоста MCP — Claude for Desktop.
Тестирование вашего сервера с помощью Claude for Desktop
Сначала убедитесь, что у вас установлен Claude for Desktop. Установить последнюю версию можно здесь. Если у вас уже есть Claude for Desktop, убедитесь, что он обновлен до последней версии.
Нам нужно настроить Claude for Desktop для тех серверов MCP, которые вы хотите использовать. Для этого откройте файл конфигурации приложения Claude for Desktop по адресу ~/Library/Application Support/Claude/claude_desktop_config.json в текстовом редакторе. Если файл отсутствует, обязательно создайте его.
Например, если у вас установлен VS Code:
Код: Выделить всё
code ~/.config/Claude/claude_desktop_config.jsonВ данном случае мы добавим наш единственный сервер погоды следующим образом:
Код: Выделить всё
{
"mcpServers": {
"weather": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/TO/PARENT/FOLDER/weather",
"run",
"weather.py"
]
}
}
}Убедитесь, что вы передаете абсолютный путь к вашему серверу. Его можно узнать, выполнив команду `pwd` в macOS/Linux или `cd` в командной строке Windows. В Windows не забудьте использовать двойные обратные косые черты (\\) или прямые косые черты (/) в пути JSON.
Это сообщает Claude for Desktop:
Существует сервер MCP с именем «weather»
Запустить его можно с помощью команды `uv --directory /ABSOLUTE/PATH/TO/PARENT/FOLDER/weather run weather.py`
Сохраните файл и перезапустите Claude for Desktop.
Проверка с помощью команд
Убедимся, что Claude for Desktop обнаруживает два инструмента, которые мы сделали доступными на нашем сервере погоды. Для этого найдите значок «Добавить файлы, коннекторы и другое /»: