Yandex Metrika

Cobertura completa de la API de Yandex Metrika (Stat, Management, Logs) con definiciones de herramientas generadas a partir de la documentación oficial de Yandex. Diez herramientas expuestas por defecto para no saturar el contexto; nunca reescribe tu consulta silenciosamente.

Documentación

Yandex Metrika MCP Server

MCP-сервер к API Яндекс Метрики. Покрыты все 108 методов; по умолчанию объявляются десять — те, которыми считают. Остальное включается одной переменной.

mcp-name: io.github.artgas1/yandex-metrika-mcp-server

npm CI License: MIT

English

Вопрос «Откуда приходили люди за неделю и сколько дошло до цели?» и ответ таблицей: Поиск — 12 480 визитов, 386 целей, конверсия 3,1%; Реклама — 2 140 и 5,5%; прямые заходы — 1 905 и 2,3%; переходы по ссылкам — 640 и 1,9%. Числа иллюстративные.
npx -y yandex-metrika-mcp-server

Форк atomkraft/yandex-metrika-mcp (апстрим — Vadim Bezymianyi, MIT). С версии 2.0.0 инструменты не пишутся руками, а порождаются из спеки, собранной по официальной документации.

Покрытие

APIметодовиз них в профиле coreпримеры инструментов
Management95 (21 ресурс)4metrika_counter_list, metrika_goal_create, metrika_segment_update
Logs7—metrika_logs_create, metrika_logs_get, metrika_logs_download
Stat66metrika_stat_data, metrika_stat_bytime, metrika_stat_pivot

Имя инструмента — metrika_<ресурс>_<действие>, где ресурс взят из URL самого API без переименований. Поэтому metrika_goal_list однозначно отображается в GET /management/v1/counter/{id}/goals и в свою страницу документации.

Контракт

Сервер переписан из-за двух наблюдавшихся отказов: он отдавал не то, что просили, и молча подмешивал фильтр. Отсюда четыре правила, каждое закрыто тестом.

  1. Никакой молчаливой подмены. Что попросили — то и уходит в API. Сервер не досочиняет ни измерений, ни периода, ни фильтров.
  2. Всё, что сервер добавил от себя, видно в ответе. Ответ приходит как {"_meta": {...}, "data": {...}}, где _meta.applied_by_server перечисляет добавленное, а _meta.notes — принятые за вызывающего решения.
  3. Отказ остаётся отказом. Ошибка API возвращается с isError: true и телом ответа Метрики. Повтор делается по статусу (429/500/502/503/504 и сетевые сбои), а не по подстроке в тексте; у 429 соблюдается Retry-After с потолком 30 секунд. Число повторов всегда видно в _meta.retries.
  4. Обрезание выдачи видно. В _meta едут rows_returned, rows_total и truncated — Метрика режет ответ по умолчанию, и молчать об этом нельзя. Если сервер сам урезал ответ по потолку длины, это отдельно объявлено в _meta.truncated_by_server с числом выброшенных строк.
  5. Секреты не уезжают в ответ. У metrika_measurement_delete есть параметр token; в показанном _meta.request_url его значение заменено на REDACTED. Сам OAuth-токен уходит только заголовком и в ответе не появляется никогда.

Фильтр роботов

В отчётах Stat API по умолчанию применяется собственный флаг робота Метрики, и только он:

ym:s:isRobot=='no'

Он объявлен: виден в схеме инструмента, отключается параметром human_traffic_only: false и всегда перечислен в _meta.applied_by_server. Если в запросе есть метрики ym:ad: или ym:ev:, фильтр не применяется (Метрика отвечает на такое сочетание 400) — и это попадает в _meta.notes, а не остаётся молчаливым исключением.

Своё условие задаётся переменной METRIKA_TRAFFIC_FILTER — целиком, включая isRobot, если он нужен:

METRIKA_TRAFFIC_FILTER="ym:s:isRobot=='no' AND ym:s:browserName!='HeadlessChrome'"

Это образец формы, а не рекомендация. Какой рез верен — зависит от того, какие боты ходят именно к вам: отсечка по стране, по заголовку браузера или по подсети осмысленна только на своих данных. Копировать чужой список бессмысленно и опасно: он вырежет живой трафик.

Заданное своё условие сервер называет в stderr при старте — оно меняет числа в каждом отчёте, и молчать об этом нельзя.

Сравнение периодов: ответ, который выглядит валидным

У metrika_stat_comparison и metrika_stat_comparison_drilldown даты периодов необязательны, и Метрика на их отсутствие не ругается. Она подставляет собственное окно (последняя неделя) в оба набора и возвращает сравнение периода с самим собой:

metrika_stat_comparison(ids, metrics)  →  totals a == b
                                          query  date1_a == date1_b

Отказывать сервер не будет — запрос ушёл ровно тем, каким его собрали. Но такой ответ приходит с пометкой в _meta.notes: и когда даты не заданы, и когда периоды совпали явно.

Как устроена спека

Публичного openapi.json у Метрики нет, но каждая страница метода сгенерирована из OpenAPI движком Diplodoc и отдаётся как text/markdown. Семантика (тип, required, комбинатор, ассертация) лежит в CSS-классах вида {.json-schema-property}, поэтому спека собирается построчным сканером по классам, а не markdown-парсером.

npm run spec:fetch   # скачать llms.txt и 108 страниц в .cache/docs/
npm run spec:build   # разобрать их в spec/metrika-api.json
npm test             # тесты спеки и схем инструментов
npm run smoke        # живые вызовы к API (нужен YANDEX_API_KEY)

spec/metrika-api.json коммитится — это состав API на момент сборки. Тест на дрейф сверяет его с llms.txt: Яндекс добавил или удалил метод — тест краснеет.

Разбор привязан к версии генератора (Diplodoc Platform v5.57.3): вся семантика висит на его классах, поэтому расхождение версии останавливает сборку спеки, а не молча портит её.

Запуск

По умолчанию объявляются десять инструментов из 108 — те, которыми считают. Управление счётчиками и целями, доступы и Logs API включаются переменной METRIKA_PROFILE; подробности ниже, в разделе «Почему по умолчанию не всё».

Спросить у самого сервера тоже можно: инструмент metrika_catalog_list перечисляет, что объявлено, что скрыто и как это включить.

npm install
npm run build
YANDEX_API_KEY=<OAuth-токен с scope direct:api / metrika> npm start

Токен — OAuth Яндекса, тот же, что используется для Директа и Вебмастера.

По умолчанию сервер сохраняет stdio-режим. Для одного локального процесса, к которому подключаются несколько MCP-клиентов, включите stateless Streamable HTTP:

YANDEX_API_KEY=<OAuth-токен> \
MCP_TRANSPORT=http MCP_HOST=127.0.0.1 MCP_PORT=13404 \
npm start

Endpoint — http://127.0.0.1:13404/mcp. При loopback-привязке сервер также проверяет Host, чтобы локальный endpoint нельзя было вызвать через DNS rebinding.

Подключение к клиенту

{
  "mcpServers": {
    "yandex-metrika-mcp": {
      "command": "npx",
      "args": ["-y", "yandex-metrika-mcp-server@3"],
      "env": { "YANDEX_API_KEY": "..." }
    }
  }
}

Из локальной сборки — то же самое, но "command": "node" и путь до build/index.js.

Мажор в строке запуска закреплён намеренно: смена мажорной версии меняет набор инструментов по умолчанию, и получать это молча при старте агента не нужно.

Переменные окружения

ПеременнаяПо умолчаниюЧто делает
YANDEX_API_KEY—OAuth-токен. Без него сервер не стартует.
MCP_TRANSPORTstdioТранспорт: stdio или stateless Streamable http.
MCP_HOST127.0.0.1Адрес HTTP listener. Используется только при MCP_TRANSPORT=http.
MCP_PORT3000Порт HTTP listener, целое число от 1 до 65535.
METRIKA_PROFILEcoreКакая часть каталога объявляется: core (10 инструментов), read (все 51 читающих), all (все 108). Неизвестное значение роняет старт.
METRIKA_ALLOW_WRITESне задана1 разрешает и объявляет 57 инструментов, меняющих данные. Пока не задана — их нет в tools/list вовсе.
METRIKA_TOOLSпустоСвоя выборка через запятую: раздел (stat, logs, management), префикс имени (metrika_goal) или точное имя. Задана — побеждает профиль.
METRIKA_TRAFFIC_FILTERym:s:isRobot=='no'Условие сегментации, добавляемое к отчётам Stat. Задаётся целиком.
METRIKA_MAX_OUTPUT_CHARS120000Потолок длины ответа одного вызова. Выгрузка Logs API в него обычно не помещается — сутки визитов это сотни тысяч символов; урезание объявляется в _meta.truncated_by_server.
METRIKA_API_BASEпустоПодмена адреса API (прокси, заглушка в тестах). Факт подмены печатается в stderr.

Как узнать, что скрыто, не открывая README

Инструмент metrika_catalog_list объявлен в любом профиле и отвечает из спеки, лежащей в пакете, — ни токена, ни сети ему не нужно:

{
  "profile": "METRIKA_PROFILE=core",
  "api_methods_total": 108,
  "api_methods_declared": 10,
  "api_methods_hidden": 98,
  "writes_enabled": false,
  "declared_tools": { "Stat API — отчёты": ["metrika_stat_data", "…"] },
  "hidden_tools": { "Management API — …": ["metrika_goal_create", "…"] },
  "how_to_widen": ["METRIKA_PROFILE=read — …", "METRIKA_PROFILE=all вместе с METRIKA_ALLOW_WRITES=1 — …"]
}

Он существует по простой причине: сервер, который что-то скрыл, обязан уметь сказать, что именно и как это включить. instructions видит модель, но не человек — в интерфейс клиента они не показываются; стартовую строку в stderr в обычной работе тоже никто не открывает. Без этого инструмента узнать про остальные 98 можно было только придя сюда.

Список инструментов в ответе строится из того же отбора, по которому они регистрируются, — разойтись с реальностью ему негде, и это проверено тестом.

Почему по умолчанию не всё

Список из 108 инструментов сервера: десять оставлены, 98 вычеркнуты. Манифест по умолчанию — 32 181 байт против 158 301 у полного каталога.

Описания объявленных инструментов лежат в контексте модели, когда клиент их загрузил. Это цена сервера, которую платят за сам факт подключения, а не за вызовы. Замер tools/list (09.09.2026):

ПрофильИнструментовtools/listтокенов
core (по умолчанию)10 + каталог32 181 Б14,8 тыс.
read51 + каталог68 074 Б~31 тыс. — оценка
all + METRIKA_ALLOW_WRITES=1108 + каталог158 301 Б~73 тыс. — оценка

Замер core — 14,5 тысячи до появления каталога и 14,8 после: сам инструмент стоит около 670 байт схемы, примерно 2% набора. Его ответ не входит в эту цену — он платится только при вызове.

Байты точные, их воспроизведёт любой: сериализуй ответ tools/list и посчитай длину. С токенами сложнее, и здесь стоит сказать прямо.

⚠️ Замер честный только у core — его дал /context клиента, который считает собственным токенизатором. Две другие строки пересчитаны из байтов по калибровке 2,17 байта на токен, снятой с той же строки core.

Ходовая эвристика «4 символа на токен» здесь врёт почти вдвое: она выведена на английском тексте, а описания у этого сервера русские, и кириллица в BPE токенизируется примерно вдвое хуже латиницы. Первая редакция этой таблицы была построена именно на ней и называла для core 7,9k вместо 14,5k. Если считаешь бюджет контекста для сервера с не-английскими описаниями — считай токенизатором, а не делением на четыре.

Состав core выведен из замера реального использования, а не из вкуса: шесть отчётов Stat плюс справочники, без которых отчёт не собрать (metrika_counter_list, metrika_counter_get, metrika_goal_list, metrika_segment_list). Порог веса стоит тестом — манифест не может подорожать молча. Порог в тесте стоит на байтах: они не зависят ни от токенизатора, ни от языка описаний.

Безопасность

  • Запись выключена по умолчанию, и меняющие инструменты не объявляются вовсе. Среди методов четырнадцать DELETE и пять удаляющих POST (.../measurement/delete, .../expense/delete, .../logrequest/{id}/clean и т. д.). Цена ошибочного вызова — удалённый счётчик или цель без возможности восстановить историю. Модель не может позвать то, чего не видит в tools/list; как включить — сказано в instructions сервера.
  • Аннотации проставлены на всех инструментах (readOnlyHint, destructiveHint, idempotentHint, openWorldHint). Клиент по ним отличает чтение от удаления: удаление под глаголом POST помечено разрушающим, PUT — тоже, потому что заменяет сущность целиком.
  • Ответы Метрики — недоверенные данные. В отчётах лежат поисковые фразы, заголовки страниц, реферера и значения UTM, то есть строки, которые пишут посетители сайта. Любой может зайти на сайт по ссылке с текстом внутри и увидеть его в отчёте. У всех инструментов openWorldHint: true, а в _meta.notes отчётов и выгрузок едет напоминание, что это данные, а не инструкции.
  • stdio остаётся транспортом по умолчанию. HTTP включается только явно через MCP_TRANSPORT=http; безопасный дефолт слушает 127.0.0.1 и проверяет Host.

Политика приватности

Сервер не собирает, не хранит и никуда не передаёт данные о вас. Ни телеметрии, ни аналитики, ни обращений к серверам автора — их не существует: под этот пакет не поднято никакой инфраструктуры.

Единственный сетевой адресат — https://api-metrika.yandex.net. Токен читается из YANDEX_API_KEY в память процесса и никуда не пишется: ни в файл, ни в stdout, ни в тело ответа. Данные отчётов не кэшируются на диск и не переживают процесс.

Данные, которые вы запрашиваете, обрабатывает Яндекс как оператор Метрики — на это распространяется его политика, а не эта.

Полный текст: PRIVACY.md.

Установка одним файлом (MCPB)

Para Claude Desktop y otros clientes que entienden los paquetes MCP, hay un archivo .mcpb — está en los releases. Abres el archivo, introduces el token en la ventana de instalación — listo.

El paquete se compila desde el mismo código con la misma etiqueta (npm run mcpb), y su manifiesto se genera a partir de package.json y del perfil — no se escribe a mano, por lo que no hay forma de que diverja del servidor; esto se verifica con una prueba.

⚠️ En el paquete no se puede habilitar la grabación. El costo de una llamada errónea es un contador o una meta eliminados sin posibilidad de recuperar el historial, y no hay nada que alternar en la ventana de instalación. ¿Necesitas grabación? Instala el paquete con npm y actívala conscientemente mediante una variable de entorno.

Sin MCP: skill y línea de comandos

MCP no es adecuado para todos ni siempre: el cliente puede no soportar MCP en absoluto, y las descripciones de las herramientas ocupan contexto constantemente — permanecen en él mientras el servidor está conectado, las llames o no.

Para este caso, el mismo servidor puede ejecutarse con el comando:

npx -y yandex-metrika-mcp-server catalog --search goal
npx -y yandex-metrika-mcp-server describe metrika_stat_data
npx -y yandex-metrika-mcp-server call metrika_stat_data \
  --ids <ID счётчика> --dimensions ym:s:trafficSource \
  --metrics ym:s:visits,ym:s:users --date1 7daysAgo --date2 today

Sobre esto se encuentra un skill — una carpeta con instrucciones para el agente que se instala con una sola línea:

npx skills add artgas1/yandex-metrika-mcp        # в текущий проект
npx skills add artgas1/yandex-metrika-mcp -g     # глобально, во все проекты

El skill no agrega herramientas al cliente ni mantiene nada en el contexto: se lee solo cuando se menciona Metrika. Dentro está el mismo comando, la referencia de los 108 métodos y el diccionario de dimensiones.

Dónde funciona. El instalador coloca una instancia en .agents/skills/yandex-metrika/ y crea un enlace simbólico en las carpetas de agentes específicos. Verificado ejecutándolo en dos:

agentedeteccióncómo se verificó
Claude Code.claude/skills/ → enlace simbólico/yandex-metrika responde desde el contenido del skill
Codex.agents/skills/ directamentenombra la ruta a SKILL.md; no se necesitan ni líneas en AGENTS.md ni configuración en config.toml para esto

El instalador declara unos veinte agentes más a través del mismo catálogo universal (Amp, Cline, Antigravity, Augment y otros) — allí no lo hemos verificado.

Por qué esto no es una segunda implementación. La CLI no hace ninguna solicitud propia: analiza los argumentos y llama a executeMethod — la misma función que usan las herramientas MCP. De ahí las mismas garantías: filtro de robots en los informes, límite de respuesta con aviso de truncamiento, limpieza de secretos de la URL mostrada, reintento según el estado. No hay forma de que diverjan, porque no hay nada que diverja.

La referencia de métodos dentro del skill se genera a partir de spec/metrika-api.json — la misma especificación que se actualiza diariamente desde la documentación de Yandex. Una prueba compara el archivo confirmado con lo que se generaría ahora, por lo que «el skill está desactualizado respecto a la API» aquí es algo visible, no imperceptible.

Dos diferencias conscientes del comando respecto a MCP:

MCPcomando
METRIKA_PROFILEactivo, por defecto coreno activo — los 108 métodos están disponibles
METRIKA_ALLOW_WRITESnecesario para operaciones que modifican datosnecesario igualmente

El perfil existe para no pagar con contexto las descripciones de herramientas no invocadas; el comando en la terminal no tiene ese costo. La restricción de grabación es otra cosa: una meta eliminada no se puede restaurar, y una flexibilización aquí sería un agujero que elude el servidor.

Verificaciones

No es una maqueta — pruébalo tú mismo

npm run demo
Запись прогона в терминале: запрос metrika_stat_data с измерением по источникам трафика и периодом в неделю, ответ с объявленным фильтром роботов и тремя строками отчёта.

Todo lo grabado proviene de la respuesta del servidor por JSON-RPC: la línea del filtro agregado — de _meta.applied_by_server, las líneas del informe — del cuerpo de la respuesta. Ni token ni red: las solicitudes se redirigen a un stub local, por lo que la ejecución se puede repetir en cualquier lugar, incluido CI. Regrabar — npm run demo:record.

npm test          # 87 тестов: спека, схемы, протокол MCP, поверхность, бандл, демо
npm run protocol  # только протокольные: stdio, tools/list, tools/call, отказы
npm run smoke     # живые вызовы к API (нужен YANDEX_API_KEY)

Las pruebas de protocolo levantan el servidor como subproceso y se comunican con él por JSON-RPC — de la misma manera que lo hace el cliente. No se necesita red: METRIKA_API_BASE redirige las solicitudes al stub. Se verifica también lo que no se ve desde dentro: que en stdout no llegue nada más que JSON-RPC, que un fallo de la API llegue como isError, no como texto de éxito, y que la grabación esté realmente bloqueada.

Lo que NO está en las verificaciones

Evaluación de selección de herramienta. Esta es la única verificación que no se reemplaza ni con una instantánea del esquema ni con una prueba de protocolo: las descripciones pueden ser sintácticamente impecables, pero el modelo aun así puede elegir la herramienta equivocada. Las pruebas no ven esto por construcción — llaman a la herramienta por nombre, es decir, la selección ya está hecha por el modelo.

Aquí es una omisión consciente, no un punto olvidado. El perfil por defecto — diez herramientas, de las cuales seis informes de Stat se diferencian por la forma de la respuesta, no por el tema, y los modelos no tienen mucho con qué confundirlas. La evaluación se vuelve necesaria cuando la superficie por defecto se amplía o cuando entran herramientas con descripciones superpuestas — entonces hay que escribirla antes de la ampliación, no después.

Qué cambió en 2.0.0

Se eliminaron 26 herramientas envoltorio sobre los ajustes predefinidos de la API Stat (get_visits, sources_summary, get_page_performance y otras). Cubrían una pequeña parte de la API, fijaban dimensiones y período en el código y no permitían especificar una solicitud arbitraria. Las reemplazan metrika_stat_*, que aceptan los parámetros de la API Stat tal cual.

Aparecieron métodos que no existían en absoluto: lista de contadores, metas, segmentos, filtros, permisos, gastos, conversiones offline y todo el Logs API. Antes había que conocer el identificador del contador de antemano — ahora se puede encontrar.

Qué cambió en 2.1.0

El servidor se llevó a un estado en el que no da miedo dejarlo a un agente.

  • Anotaciones en los 108 instrumentos. Antes el cliente no distinguía metrika_counter_list de metrika_counter_delete.
  • Grabación desactivada por defecto (METRIKA_ALLOW_WRITES).
  • Se encontró y corrigió un defecto en el análisis de la documentación. Las aserciones están marcadas con una línea donde el valor está después del paréntesis de cierre de la clase — el reconocedor de propiedades está anclado al final de la línea y no coincidía con esas líneas. Como resultado, a la especificación no llegaba ningún ejemplo, valor por defecto o límite, y parte de ellos caía en la descripción del campo vecino. Ahora la especificación tiene 288 ejemplos, 69 valores por defecto y 155 límites; los límites se trasladan al esquema de la herramienta, los ejemplos y valores por defecto — a las descripciones de parámetros.
  • Se encontró y corrigió la pérdida de obligatoriedad. Los parámetros del tipo «uno de N tipos» (goal en la creación y edición de metas, grant en la concesión de acceso) se recopilaban como z.unknown(), y este es opcional en zod — el campo obligatorio llegaba al cliente como opcional. Ahora es una unión de formas reales, y la obligatoriedad está en su lugar.
  • Las referencias a entidades se expanden un nivel: en 23 parámetros del cuerpo, en lugar de un objeto libre, se ven los campos reales.
  • Flexibilizaciones en la entrada donde son inofensivas. Número como cadena, booleano como palabra, lista separada por comas en la cadena de consulta — se aceptan; en el cuerpo de la solicitud, donde importa un JSON exacto, no se aceptan.
  • Límite de longitud de respuesta con truncamiento declarado: la descarga del Logs API puede tener cientos de megabytes.
  • Limpieza de secretos del request_url mostrado.
  • Reintento en 429 respetando Retry-After.
  • SDK actualizado a 1.30 — en 1.17 había tres vulnerabilidades publicadas, dos altas; npm audit --audit-level=high ahora es parte de CI.
  • Se corrigió el trabajo de deriva en CI. Ejecutaba las pruebas a través de | tee sin pipefail, por lo que el código de retorno se tomaba de tee y el trabajo permanecía verde ante cualquier fallo de prueba.