← Назад к курсу

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]:

  1. Инструменты (Tools) — аналоги POST‑запросов в REST API. Выполняют действия, имеют побочные эффекты (запись в БД, отправка email, вызов API).
  2. Ресурсы (Resources) — аналоги GET‑запросов. Предоставляют данные для чтения (файлы, документы, конфигурации).
  3. Промпты (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 Запуск и подключение

  1. Запустите сервер:

    uv run server.py
    

    Сервер будет ожидать подключений через стандартный ввод‑вывод (stdio).

  2. Подключите к Claude Desktop:

    claude mcp add --transport stdio my-server /путь/к/server.py
    
  3. Используйте в 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 и чёткой спецификации.

Ключевые шаги для старта:

  1. Установите Python SDK (uv add "mcp[cli]").
  2. Создайте класс MCPServer и определите инструменты с помощью декоратора @mcp.tool().
  3. Реализуйте бизнес‑логику внутри инструментов.
  4. Запустите сервер (mcp.run()) и подключите его к MCP‑клиенту (Claude Desktop, Inspector).

Этот подход позволяет строить модульные, переиспользуемые и безопасные интеграции, которые могут работать с любым MCP‑совместимым клиентом, открывая новые возможности для AI‑приложений.