Model Context Protocol (MCP): создание серверов с инструментами
1. Что такое MCP и зачем он нужен?
Model Context Protocol (MCP) — это открытый протокол, разработанный Anthropic, который стандартизирует подключение языковых моделей (LLM) к внешним данным и инструментам[reference:0]. Он решает проблему «информационных изолированных систем» (data silos), позволяя LLM безопасно и предсказуемо взаимодействовать с базами данных, API, файловыми системами и другими внешними сервисами[reference:1].
Ключевая идея: MCP отделяет логику предоставления контекста (данных и инструментов) от самой LLM. Это позволяет:
- Создавать переиспользуемые серверы контекста, которые могут работать с разными клиентами (Claude Desktop, VS Code, кастомные приложения).
- Обеспечивать безопасность — сервер контролирует свои ресурсы, не требуя передачи API‑ключей провайдерам LLM.
- Упрощать интеграцию — вместо написания отдельных плагинов для каждого инструмента вы создаёте один MCP‑сервер, который затем может использоваться любым MCP‑клиентом.
2. Архитектура MCP: клиент‑серверная модель
┌─────────────────┐ MCP (JSON‑RPC 2.0) ┌─────────────────┐ │ LLM-клиент │ ────────────────────────────────► │ MCP-сервер │ │ (Claude Desktop, │ ◄──────────────────────────────── │ (ваш сервер с │ │ VS Code, и т.д.)│ инструменты, ресурсы │ инструментами) │ └─────────────────┘ └─────────────────┘
Сервер MCP предоставляет три основных типа примитивов[reference:2]:
- Инструменты (Tools) — аналоги POST‑запросов в REST API. Выполняют действия, имеют побочные эффекты (запись в БД, отправка email, вызов API).
- Ресурсы (Resources) — аналоги GET‑запросов. Предоставляют данные для чтения (файлы, документы, конфигурации).
- Промпты (Prompts) — шаблоны взаимодействия с LLM, которые могут быть параметризованы.
В этом руководстве мы сосредоточимся на инструментах.
3. Создание MCP‑сервера с инструментами на Python
3.1 Установка Python SDK
Официальный Python SDK находится в активной разработке (v2 в pre‑alpha), но для production рекомендуется использовать ветку v1.x[reference:3].
# Создаём проект с помощью uv (рекомендуется) uv init mcp-server-demo cd mcp-server-demo # Устанавливаем MCP с CLI uv add "mcp[cli]" # Альтернативно, через pip pip install "mcp[cli]"
3.2 Базовый пример: сервер с двумя инструментами
Создайте файл server.py:
from mcp.server.mcpserver import MCPServer
# Создаём экземпляр сервера
mcp = MCPServer("DemoServer")
# Инструмент 1: калькулятор сложения
@mcp.tool()
def add(a: int, b: int) -> int:
"""Сложить два числа."""
return a + b
# Инструмент 2: получение погоды (заглушка)
@mcp.tool()
def get_weather(city: str, unit: str = "celsius") -> str:
"""Получить текущую погоду в указанном городе."""
# В реальном приложении здесь будет вызов внешнего API
return f"Погода в {city}: 22°{unit[0].upper()}"
# Запуск сервера на stdio (стандартный транспорт для Claude Desktop)
if __name__ == "__main__":
mcp.run(transport="stdio")
3.3 Запуск и подключение
-
Запустите сервер:
uv run server.py
Сервер будет ожидать подключений через стандартный ввод‑вывод (stdio).
-
Подключите к Claude Desktop:
claude mcp add --transport stdio my-server /путь/к/server.py
-
Используйте в Claude: Теперь в диалоге с Claude можно спросить "Сколько будет 5 + 3?" или "Какая погода в Москве?", и модель автоматически вызовет соответствующий инструмент.
4. Расширенные примеры инструментов
4.1 Инструмент с контекстом (Context)
Контекст автоматически инжектируется сервером и предоставляет доступ к сессии и состоянию приложения.
from mcp.server.mcpserver import Context, MCPServer
from mcp.server.session import ServerSession
import sqlite3
mcp = MCPServer("DatabaseServer")
@mcp.tool()
def query_db(
sql: str,
ctx: Context[ServerSession, None] # Контекст注入
) -> str:
"""Выполнить SQL‑запрос к базе данных."""
# В реальном приложении соединение с БД должно управляться через lifespan
conn = sqlite3.connect("example.db")
cursor = conn.cursor()
try:
cursor.execute(sql)
results = cursor.fetchall()
return str(results)
finally:
conn.close()
4.2 Инструмент с прогрессом (Progress Reporting)
Для длительных операций можно отправлять клиенту уведомления о прогрессе.
@mcp.tool()
async def long_task(
task_name: str,
steps: int = 5,
ctx: Context[ServerSession, None] = None
) -> str:
"""Выполняет длительную задачу с отчётом о прогрессе."""
await ctx.info(f"Начало задачи: {task_name}")
for i in range(steps):
progress = (i + 1) / steps
# Отправляем прогресс клиенту
await ctx.report_progress(
progress=progress,
total=1.0,
message=f"Шаг {i + 1}/{steps}"
)
# Имитация работы
import asyncio
await asyncio.sleep(1)
return f"Задача '{task_name}' завершена"
4.3 Инструмент со структурированным выводом (Structured Output)
Использование Pydantic моделей для типизированного ответа.
from pydantic import BaseModel, Field
class WeatherData(BaseModel):
"""Структура данных о погоде."""
temperature: float = Field(description="Температура в °C")
humidity: float = Field(description="Влажность в %")
condition: str
@mcp.tool()
def get_weather_structured(city: str) -> WeatherData:
"""Получить структурированные данные о погоде."""
# В реальном приложении — вызов API
return WeatherData(
temperature=22.5,
humidity=45.0,
condition="солнечно"
)
5. Лучшие практики и рекомендации
5.1 Безопасность
- Всегда проверяйте входные данные инструментов. Используйте Pydantic для валидации.
- Ограничивайте доступ к критичным операциям. MCP‑сервер должен работать с минимально необходимыми правами.
- Используйте lifespan‑контекст для управления ресурсами (открытие/закрытие соединений с БД).
5.2 Управление жизненным циклом (Lifespan)
from contextlib import asynccontextmanager
from mcp.server.mcpserver import MCPServer
# Пример lifespan для управления подключением к БД
@asynccontextmanager
async def app_lifespan(server: MCPServer):
# Инициализация при запуске сервера
db = await Database.connect()
try:
yield {"db": db} # Контекст, доступный в инструментах
finally:
# Очистка при остановке сервера
await db.disconnect()
mcp = MCPServer("MyApp", lifespan=app_lifespan)
5.3 Тестирование и отладка
- Используйте MCP Inspector для визуальной отладки сервера:
npx -y @modelcontextprotocol/inspector
- Пишите unit‑тесты для инструментов, используя mcp.testing.
- Логируйте вызовы инструментов для аудита и мониторинга.
5.4 Производительность
- Используйте асинхронные инструменты (async def) для операций ввода‑вывода.
- Кэшируйте часто запрашиваемые данные на уровне ресурсов.
- Ограничивайте время выполнения инструментов с помощью asyncio.timeout.
6. Полезные ресурсы
| Ресурс | Описание |
|---|---|
| Спецификация MCP | Официальная спецификация протокола (особенно раздел Tools)[reference:4] |
| Python SDK | Официальная Python‑библиотека для создания серверов и клиентов[reference:5] |
| Каталог MCP‑серверов (mcp.so) | Сообщество и Marketplace готовых серверов (более 17 500 серверов)[reference:6] |
| Anthropic Announcement | Официальное анонсирование MCP от Anthropic[reference:7] |
| Примеры серверов | Коллекция примеров серверов от сообщества |
7. Заключение
MCP предоставляет стандартизированный, безопасный и мощный способ расширения возможностей языковых моделей за счёт внешних инструментов. Создание MCP‑сервера с инструментами на Python становится простой задачей благодаря официальному SDK и чёткой спецификации.
Ключевые шаги для старта:
- Установите Python SDK (uv add "mcp[cli]").
- Создайте класс MCPServer и определите инструменты с помощью декоратора @mcp.tool().
- Реализуйте бизнес‑логику внутри инструментов.
- Запустите сервер (mcp.run()) и подключите его к MCP‑клиенту (Claude Desktop, Inspector).
Этот подход позволяет строить модульные, переиспользуемые и безопасные интеграции, которые могут работать с любым MCP‑совместимым клиентом, открывая новые возможности для AI‑приложений.