Skip to main content
Glama
mlenkov

Yandex MCP Server

by mlenkov

Yandex MCP Server

License: MIT Python MCP Docker

MCP-сервер для API Яндекса: Direct, Metrika, Audience, Webmaster, AdMetrica + Admin Panel.

Архитектура: FastMCP + apiforge async + SQLAlchemy (Dual DB: SQLite/MySQL) + FastAPI Admin

Быстрый старт (локально, SQLite)

# 1. Клонировать и перейти в директорию
cd yandex-mcp-server

# 2. Установить зависимости
uv sync --no-dev

# 3. Скопировать .env
cp .env.example .env

# 4. Сгенерировать Fernet-ключ (если не задан в .env)
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# Вставь ключ в .env: FERNET_KEY=...

# 5. Применить миграции
uv run alembic upgrade head

# 6. Запустить сервер
uv run python -m app.main

Сервер будет доступен на http://localhost:8000/mcp (Streamable HTTP).

Related MCP server: Yandex Direct MCP

Production-деплой

SQLite (рекомендуется для MVP)

# 0. Создать внешнюю Docker-сеть (только первый раз)
docker network create mais-bifrost-net

# 1. Скопировать production env
cp .env.example .env.prod
# Заполнить: FERNET_KEY, YANDEX_CLIENT_ID, YANDEX_CLIENT_SECRET

# 2. Запустить стек (сборка + запуск)
docker compose -f docker-compose.prod.sqlite.yml up -d --build

# 3. Применить миграции
docker exec mais-yandex-mcp uv run alembic upgrade head

# 4. Проверить
docker exec mais-yandex-mcp curl http://127.0.0.1:8000/ping

MySQL (для высоких нагрузок)

# 0. Создать внешнюю Docker-сеть (только первый раз)
docker network create mais-bifrost-net

# 1. Скопировать production env
cp .env.prod.example .env.prod
# Заполнить: MYSQL_ROOT_PASSWORD, MYSQL_PASSWORD, FERNET_KEY, YANDEX_CLIENT_ID, YANDEX_CLIENT_SECRET

# 2. Запустить стек (сборка + запуск)
docker compose -f docker-compose.prod.yml up -d --build

# 3. Применить миграции
docker exec mais-yandex-mcp uv run alembic upgrade head

# 4. Проверить
curl http://localhost:8000/ping

Admin Panel

Web UI для управления интеграциями с Яндексом. Доступен после деплоя.

Route

Описание

/admin/

Dashboard — список интеграций, статус токенов

/admin/integrations/add

Добавить интеграцию (Direct, Metrika и т.д.)

/admin/oauth/callback

OAuth callback для Yandex

Стек: FastAPI + Jinja2 + общая БД с MCP-сервером.

Настройка Bifrost

Bifrost должен проксировать заголовок X-Bifrost-User-Id при подключении к MCP-серверу. MCP-сервер слушает на /mcp (Streamable HTTP).

app.mais.agency {
    # Admin panel (protected by Yandex OAuth)
    @admin path /admin/*
    handle @admin {
        forward_auth auth:4180 {
            uri /auth
        }
        reverse_proxy mais-yandex-admin:8100
    }

    # MCP endpoint
    handle @mcp {
        reverse_proxy /mcp/* yandex-mcp:8000 {
            header_up X-Bifrost-User-Id {http.request.header.X-Bifrost-User-Id}
        }
    }

    # Bifrost UI
    reverse_proxy /api/* mais-bifrost:8080
}

Доступные MCP-инструменты (14)

Инструмент

Описание

ping

Health check

list_yandex_accounts

Список аккаунтов пользователя

get_direct_campaigns

Кампании Яндекс Директа

get_metrika_counters

Счётчики Яндекс Метрики

get_webmaster_hosts

Хосты Яндекс Вебмастера

get_audience_segments

Сегменты Яндекс Аудитории

get_admetrica_campaigns

Кампании Яндекс AdMetrica

get_direct_stats

Статистика кампании (Impressions, Clicks, CTR, CPC, Cost, Conversions)

get_direct_keywords

Ключевые слова кампании

get_direct_ads

Объявления кампании (Title, Text, Status, State)

get_wordstat_stats

Частотность ключевых слов (Wordstat)

get_account_context

Получить контекст аккаунта (бизнес-правила, заметки)

update_account_context

Обновить контекст аккаунта

submit_feedback

Отправить обратную связь о работе сервера

MCP Resources (5)

LLM может запросить документацию по API прямо во время диалога — без галлюцинаций:

Resource

Описание

yandex://direct/docs

Яндекс.Директ API: структура, статусы, ограничения, best practices

yandex://metrika/docs

Яндекс.Метрика API

yandex://webmaster/docs

Яндекс.Вебмастер API

yandex://audience/docs

Яндекс.Аудитории API

yandex://admetrica/docs

Яндекс.AdMetrica API

Пример: ReadResource(yandex://direct/docs) → возвращает ~1000 символов документации.

MCP Prompts (3)

Готовые сценарии для LLM с типизированными аргументами:

Prompt

Аргументы

Описание

analyze_campaign_performance

campaign_id (int), days (int, default 7)

Детальный анализ кампании с шагами и форматом отчёта

suggest_budget_optimization

account_id (int, optional)

Перераспределение бюджета на основе ROI

find_underperforming_ads

account_id (int, optional)

Выявление объявлений с CTR < 1%, CPC > avg, 0 конверсий

Пример: GetPrompt(analyze_campaign_performance, campaign_id=12345, days=7) → возвращает message с инструкцией для LLM: "Проанализируй эффективность кампании 12345 за последние 7 дней. ШАГИ: 1. Получи контекст аккаунта... 2. Получи статистику..."

Отладка с MCP Inspector

Используй MCP Inspector для тестирования инструментов без LLM.

Локальный запуск

# 1. Убедись, что в .env указан SQLite
# DATABASE_URL=sqlite+aiosqlite:///./data/yandex-mcp.db

# 2. Запусти сервер
uv run python -m app.main

# 3. В другом терминале запусти Inspector
npx @modelcontextprotocol/inspector

# 4. В браузере (http://localhost:5173) выбери:
#    Transport: Streamable HTTP
#    URL: http://localhost:8000/mcp

# 5. Перейди во вкладку Tools → List Tools → протестируй ping

Тестирование ошибок

Если apiforge получает 400/401/429 от Яндекса, сервер возвращает структурированный JSON:

{
  "status": "error",
  "yandex_api_error": true,
  "message": "Yandex API returned 401: Authentication failed",
  "suggestion": "Re-authorize the Yandex account via OAuth."
}

Ошибки выводятся в ответе инструмента (Response tab) и в терминале сервера (stdout).

Benchmark

Подключение: POST http://localhost:8000/mcp (Streamable HTTP, Accept: application/json, text/event-stream)

1. ListTools → get_direct_stats_tool (inputSchema + description)

{
  "name": "get_direct_stats_tool",
  "description": "Получить статистику по кампании Яндекс.Директа за период.\n\n    КОГДА ИСПОЛЬЗОВАТЬ:\n    - Нужно проанализировать эффективность кампании\n    - Получить показы, клики, CTR, CPC, расходы, конверсии\n\n    ПАРАМЕТРЫ:\n    - campaign_id: ID кампании из get_direct_campaigns\n    - date_from: Начало периода в формате YYYY-MM-DD\n    - date_to: Конец периода в формате YYYY-MM-DD\n    - account_id: ID аккаунта (опционально)\n\n    ВОЗВРАЩАЕТ: метрики Impressions, Clicks, CTR, CPC, Cost, Conversions.",
  "inputSchema": {
    "properties": {
      "campaign_id": {"type": "integer"},
      "date_from": {"type": "string"},
      "date_to": {"type": "string"},
      "account_id": {"anyOf": [{"type": "integer"}, {"type": "null"}], "default": null}
    },
    "required": ["campaign_id", "date_from", "date_to"]
  }
}

2. ListResources

{
  "resources": [
    {"name": "direct_docs",    "uri": "yandex://direct/docs",    "mimeType": "text/plain"},
    {"name": "metrika_docs",   "uri": "yandex://metrika/docs",   "mimeType": "text/plain"},
    {"name": "webmaster_docs", "uri": "yandex://webmaster/docs", "mimeType": "text/plain"},
    {"name": "audience_docs",  "uri": "yandex://audience/docs",  "mimeType": "text/plain"},
    {"name": "admetrica_docs", "uri": "yandex://admetrica/docs", "mimeType": "text/plain"}
  ]
}

3. ReadResource → yandex://direct/docs

# Яндекс.Директ API — Полная документация

## Структура данных
- Кампания (Campaign) → Группы (AdGroups) → Объявления (Ads) + Фразы (Keywords)
- Каждая кампания имеет: Id, Name, Status, StartDate, DailyBudget

## Статусы кампаний
- DRAFT — черновик, не запущена
- MODERATION — на проверке
- ACCEPTED — принята, готова к запуску
- RUNNING — активна, показываются объявления
- STOPPED — остановлена вручную
- ENDED — завершена (закончился бюджет или дата)

## Ограничения API
- Максимум 10000 объектов ...

Полная длина: 1003 символа.

4. ListPrompts

{
  "prompts": [
    {
      "name": "analyze_campaign_performance",
      "description": "Анализ эффективности рекламной кампании за последние N дней.",
      "arguments": [
        {"name": "campaign_id", "required": true},
        {"name": "days", "required": false}
      ]
    },
    {
      "name": "suggest_budget_optimization",
      "description": "Предложения по оптимизации бюджета рекламных кампаний.",
      "arguments": [{"name": "account_id", "required": false}]
    },
    {
      "name": "find_underperforming_ads",
      "description": "Поиск неэффективных объявлений для оптимизации.",
      "arguments": [{"name": "account_id", "required": false}]
    }
  ]
}

5. GetPrompt → analyze_campaign_performance(campaign_id=12345, days=7)

{
  "description": "Анализ эффективности рекламной кампании за последние N дней.",
  "messages": [{
    "role": "user",
    "content": {
      "type": "text",
      "text": "Проанализируй эффективность кампании 12345 за последние 7 дней.\n\nШАГИ:\n1. Получи контекст аккаунта через get_account_context\n2. Получи статистику кампании за период (используй get_direct_stats)\n3. Получи статистику за предыдущий аналогичный период для сравнения\n4. Рассчитай ключевые метрики: CTR, CPC, CR, CPA, ROI\n5. Выяви аномалии (резкие падения/росты)\n6. Предложи конкретные оптимизации\n\nФОРМАТ ОТВЕТА:\n- Краткое резюме (1-2 предложения)\n- Ключевые метрики (таблица)\n- Сравнение с предыдущим периодом\n- Выявленные проблемы\n- Рекомендации (приоритизированные)"
    }
  }]
}

Полезные команды

# Проверить health
curl http://localhost:8000/ping

# Прямой запрос к MCP (JSON-RPC)
curl -X POST http://localhost:8000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Contributing

См. CONTRIBUTING.md.

License

MIT License — см. LICENSE.

Seed-данные для тестирования

Наполни SQLite тестовым пользователем с аккаунтом Директа (токен истёк вчера — триггернет auto-refresh):

uv run python -m scripts.seed

После этого в Inspector при вызове get_direct_campaigns:

  1. Сервер получит 401 от Яндекса

  2. Попробует обновить токен через refresh_account_token

  3. Вернёт структурированную ошибку с "yandex_api_error": true

Структура проекта

app/
├── main.py                 # FastMCP + регистрация инструментов/ресурсов/промптов
├── config.py               # Pydantic Settings (Dual DB, Fernet, OAuth)
├── database.py             # SQLAlchemy async engine
├── models.py               # ORM: mcp_users, mcp_yandex_accounts (+ account_context)
├── crypto.py               # TokenCrypto (Fernet)
├── context_parser.py       # X-Bifrost-User-Id из контекста
├── apiforge_async.py       # AsyncYandexClient + auto-refresh + ctx.logging
├── rate_limiter.py         # In-memory per-user/per-tool rate limiter (30 req/min)
├── services/
│   └── account_service.py  # AccountService (DB + refresh OAuth + context)
├── tools/
│   ├── accounts.py         # list_yandex_accounts
│   ├── direct.py           # get_direct_campaigns | stats | keywords | ads
│   ├── metrika.py          # get_metrika_counters
│   ├── webmaster.py        # get_webmaster_hosts
│   ├── audience.py         # get_audience_segments
│   ├── admetrica.py        # get_admetrica_campaigns
│   ├── account_management.py  # get/update_account_context
│   ├── wordstat.py         # get_wordstat_stats
│   └── feedback.py         # submit_feedback
├── resources/
│   └── yandex_docs.py      # MCP Resources: 5 API documentation endpoints
├── prompts/
│   └── yandex_scenarios.py # MCP Prompts: 3 analysis scenarios
├── yandex_configs/         # JSON-конфиги для apiforge
admin/
├── app.py                  # FastAPI admin panel
├── templates/              # Jinja2 HTML шаблоны
└── static/                 # CSS
docs/                       # Документация и JSON-RPC дампы
├── yandex-mcp-connection.md
├── yandex-tools-dump.json
├── yandex-resources-dump.json
├── yandex-prompts-dump.json
└── ...
A
license - permissive license
-
quality - not tested
B
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

  • F
    license
    -
    quality
    B
    maintenance
    Russian-market marketing & ops MCP toolkit. 7 unified servers for Yandex.Direct, Yandex.Webmaster, Google Search Console (RU), YouTube Data API, VK Wall, Telegram publishing, and Click.ru (Telegram Ads + VK Ads + Yandex.Direct unified). The only complete RU-platform bundle for AI agents.
    1
  • A
    license
    A
    quality
    A
    maintenance
    Enables managing Yandex Direct PPC campaigns, ad groups, ads, and keywords, plus pulling performance statistics via the Yandex Direct API v5.
    40
    570
    1
    MIT
  • A
    license
    B
    quality
    B
    maintenance
    MCP server for managing Yandex Direct advertising, Yandex Metrica analytics, Wordstat keyword research, and Yandex Webmaster SEO tools, with self-configuring OAuth; provides 153 tools for complete ad and search workflows from AI assistants.
    100
    15
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    MCP server for Yandex Direct, Metrika, Wordstat, and Webmaster APIs, providing 132 tools to manage advertising campaigns, analytics, keyword research, and reporting through any MCP-compatible client.
    57
    MIT

View all related MCP servers

Related MCP Connectors

  • MCP for Yandex Direct: manage ad campaigns & analytics from Claude or ChatGPT

  • Read-only Yandex Metrika MCP. Query visits, sources, geo, devices and more in plain language.

  • OpenAI Ads MCP for ChatGPT Ads campaigns, creatives, audiences, insights, and conversions.

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/mlenkov/yandex-mcp-server'

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