The full upstream README, mirrored here for reference. Install config, tool schemas, adoption signals, and an original overview live on the Yandex Metrika MCP Server listing page.
MCP-сервер к API Яндекс Метрики. Покрыты все 108 методов; по умолчанию объявляются десять — те, которыми считают. Остальное включается одной переменной.
mcp-name: io.github.artgas1/yandex-metrika-mcp-server
Форк atomkraft/yandex-metrika-mcp (апстрим — Vadim Bezymianyi, MIT). С версии 2.0.0 инструменты не пишутся руками, а порождаются из спеки, собранной по официальной документации.
| API | методов | из них в профиле core | примеры инструментов |
|---|---|---|---|
| Management | 95 (21 ресурс) | 4 | metrika_counter_list, metrika_goal_create, metrika_segment_update |
| Logs | 7 | — | metrika_logs_create, metrika_logs_get, metrika_logs_download |
| Stat | 6 | 6 | metrika_stat_data, metrika_stat_bytime, metrika_stat_pivot |
Имя инструмента — metrika_<ресурс>_<действие>, где ресурс взят из URL самого API без переименований.
Поэтому metrika_goal_list однозначно отображается в GET /management/v1/counter/{id}/goals
и в свою страницу документации.
Сервер переписан из-за двух наблюдавшихся отказов: он отдавал не то, что просили, и молча подмешивал фильтр. Отсюда четыре правила, каждое закрыто тестом.
{"_meta": {...}, "data": {...}}, где _meta.applied_by_server перечисляет добавленное,
а _meta.notes — принятые за вызывающего решения.isError: true и телом ответа Метрики.
Повтор делается по статусу (429/500/502/503/504 и сетевые сбои), а не по подстроке
в тексте; у 429 соблюдается Retry-After с потолком 30 секунд. Число повторов всегда
видно в _meta.retries._meta едут rows_returned, rows_total и truncated —
Метрика режет ответ по умолчанию, и молчать об этом нельзя. Если сервер сам урезал ответ
по потолку длины, это отдельно объявлено в _meta.truncated_by_server с числом
выброшенных строк.metrika_measurement_delete есть параметр token;
в показанном _meta.request_url его значение заменено на REDACTED. Сам OAuth-токен
уходит только заголовком и в ответе не появляется никогда.В отчётах Stat API по умолчанию применяется собственный флаг робота Метрики, и только он:
Он объявлен: виден в схеме инструмента, отключается параметром human_traffic_only: false
и всегда перечислен в _meta.applied_by_server. Если в запросе есть метрики ym:ad: или
ym:ev:, фильтр не применяется (Метрика отвечает на такое сочетание 400) — и это попадает
в _meta.notes, а не остаётся молчаливым исключением.
Своё условие задаётся переменной METRIKA_TRAFFIC_FILTER — целиком, включая isRobot,
если он нужен:
Это образец формы, а не рекомендация. Какой рез верен — зависит от того, какие боты ходят именно к вам: отсечка по стране, по заголовку браузера или по подсети осмысленна только на своих данных. Копировать чужой список бессмысленно и опасно: он вырежет живой трафик.
Заданное своё условие сервер называет в stderr при старте — оно меняет числа в каждом отчёте, и молчать об этом нельзя.
У metrika_stat_comparison и metrika_stat_comparison_drilldown даты периодов
необязательны, и Метрика на их отсутствие не ругается. Она подставляет собственное окно
(последняя неделя) в оба набора и возвращает сравнение периода с самим собой:
Отказывать сервер не будет — запрос ушёл ровно тем, каким его собрали. Но такой ответ
приходит с пометкой в _meta.notes: и когда даты не заданы, и когда периоды совпали явно.
Публичного openapi.json у Метрики нет, но каждая страница метода сгенерирована из OpenAPI
движком Diplodoc и отдаётся как text/markdown. Семантика (тип, required, комбинатор,
ассертация) лежит в CSS-классах вида {.json-schema-property}, поэтому спека собирается
построчным сканером по классам, а не markdown-парсером.
spec/metrika-api.json коммитится — это состав API на момент сборки. Тест на дрейф сверяет
его с llms.txt: Яндекс добавил или удалил метод — тест краснеет.
Разбор привязан к версии генератора (Diplodoc Platform v5.57.3): вся семантика висит на его
классах, поэтому расхождение версии останавливает сборку спеки, а не молча портит её.
По умолчанию объявляются десять инструментов из 108 — те, которыми считают. Управление счётчиками и целями, доступы и Logs API включаются переменной
METRIKA_PROFILE; подробности ниже, в разделе «Почему по умолчанию не всё».Спросить у самого сервера тоже можно: инструмент
metrika_catalog_listперечисляет, что объявлено, что скрыто и как это включить.
Токен — OAuth Яндекса, тот же, что используется для Директа и Вебмастера.
По умолчанию сервер сохраняет stdio-режим. Для одного локального процесса, к которому подключаются несколько MCP-клиентов, включите stateless Streamable HTTP:
Endpoint — http://127.0.0.1:13404/mcp. При loopback-привязке сервер также
проверяет Host, чтобы локальный endpoint нельзя было вызвать через DNS rebinding.
Из локальной сборки — то же самое, но "command": "node" и путь до build/index.js.
Мажор в строке запуска закреплён намеренно: смена мажорной версии меняет набор инструментов по умолчанию, и получать это молча при старте агента не нужно.
| Переменная | По умолчанию | Что делает |
|---|---|---|
YANDEX_API_KEY | — | OAuth-токен. Без него сервер не стартует. |
MCP_TRANSPORT | stdio | Транспорт: stdio или stateless Streamable http. |
MCP_HOST | 127.0.0.1 | Адрес HTTP listener. Используется только при MCP_TRANSPORT=http. |
MCP_PORT | 3000 | Порт HTTP listener, целое число от 1 до 65535. |
METRIKA_PROFILE | core | Какая часть каталога объявляется: core (10 инструментов), read (все 51 читающих), all (все 108). Неизвестное значение роняет старт. |
METRIKA_ALLOW_WRITES | не задана | 1 разрешает и объявляет 57 инструментов, меняющих данные. Пока не задана — их нет в tools/list вовсе. |
METRIKA_TOOLS | пусто | Своя выборка через запятую: раздел (stat, logs, management), префикс имени (metrika_goal) или точное имя. Задана — побеждает профиль. |
METRIKA_TRAFFIC_FILTER | ym:s:isRobot=='no' | Условие сегментации, добавляемое к отчётам Stat. Задаётся целиком. |
METRIKA_MAX_OUTPUT_CHARS | 120000 | Потолок длины ответа одного вызова. Выгрузка Logs API в него обычно не помещается — сутки визитов это сотни тысяч символов; урезание объявляется в _meta.truncated_by_server. |
METRIKA_API_BASE | пусто | Подмена адреса API (прокси, заглушка в тестах). Факт подмены печатается в stderr. |
Инструмент metrika_catalog_list объявлен в любом профиле и отвечает из спеки, лежащей в
пакете, — ни токена, ни сети ему не нужно:
Он существует по простой причине: сервер, который что-то скрыл, обязан уметь сказать, что
именно и как это включить. instructions видит модель, но не человек — в интерфейс клиента
они не показываются; стартовую строку в stderr в обычной работе тоже никто не открывает. Без
этого инструмента узнать про остальные 98 можно было только придя сюда.
Список инструментов в ответе строится из того же отбора, по которому они регистрируются, — разойтись с реальностью ему негде, и это проверено тестом.
Описания объявленных инструментов лежат в контексте модели, когда клиент их загрузил. Это
цена сервера, которую платят за сам факт подключения, а не за вызовы. Замер tools/list
(09.09.2026):
| Профиль | Инструментов | tools/list | токенов |
|---|---|---|---|
core (по умолчанию) | 10 + каталог | 32 181 Б | 14,8 тыс. |
read | 51 + каталог | 68 074 Б | ~31 тыс. — оценка |
all + METRIKA_ALLOW_WRITES=1 | 108 + каталог | 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 — тоже, потому что заменяет сущность целиком.openWorldHint: true, а в _meta.notes отчётов и выгрузок едет напоминание, что это данные,
а не инструкции.MCP_TRANSPORT=http; безопасный дефолт слушает 127.0.0.1 и проверяет Host.Сервер не собирает, не хранит и никуда не передаёт данные о вас. Ни телеметрии, ни аналитики, ни обращений к серверам автора — их не существует: под этот пакет не поднято никакой инфраструктуры.
Единственный сетевой адресат — https://api-metrika.yandex.net. Токен читается из
YANDEX_API_KEY в память процесса и никуда не пишется: ни в файл, ни в stdout, ни в тело
ответа. Данные отчётов не кэшируются на диск и не переживают процесс.
Данные, которые вы запрашиваете, обрабатывает Яндекс как оператор Метрики — на это распространяется его политика, а не эта.
Полный текст: PRIVACY.md.
Для Claude Desktop и других клиентов, понимающих MCP-бандлы, есть .mcpb-файл — он лежит в
релизах. Открываете файл, вводите
токен в окне установки — всё.
Бандл собирается из того же кода тем же тегом (npm run mcpb), а его манифест генерируется
из package.json и профиля — не пишется руками, поэтому разойтись с сервером ему негде; это
проверяется тестом.
⚠️ В бандле нельзя включить запись. Цена ошибочного вызова — удалённый счётчик или цель без возможности восстановить историю, и щёлкать таким переключателем в окне установки нечего. Нужна запись — ставьте пакет с npm и включайте её осознанно, переменной окружения.
MCP подходит не всем и не всегда: клиент может не уметь MCP вовсе, а описания инструментов занимают контекст постоянно — они лежат в нём, пока сервер подключён, вызываешь ты их или нет.
Для этого случая тот же сервер умеет запускаться командой:
Поверх этого лежит скилл — папка с инструкцией для агента, которая ставится одной строкой:
Скилл не добавляет клиенту инструментов и ничего не держит в контексте: он читается только когда речь зашла о Метрике. Внутри — та же команда, справочник всех 108 методов и словарь измерений.
Где он работает. Установщик кладёт один экземпляр в .agents/skills/yandex-metrika/
и симлинкует его в папки конкретных агентов. Проверено запуском на двух:
| агент | обнаружение | чем проверено |
|---|---|---|
| Claude Code | .claude/skills/ → симлинк | /yandex-metrika отвечает из содержимого скилла |
| Codex | .agents/skills/ напрямую | называет путь к SKILL.md; ни строки в AGENTS.md, ни настройки в config.toml для этого не нужно |
Установщик заявляет ещё около двадцати агентов через тот же универсальный каталог (Amp, Cline, Antigravity, Augment и другие) — там мы не проверяли.
Почему это не вторая реализация. CLI не делает ни одного собственного запроса: он разбирает
аргументы и зовёт executeMethod — ту же функцию, что и MCP-инструменты. Отсюда одинаковые
гарантии: фильтр роботов в отчётах, потолок ответа с распиской об урезании, вычистка секретов
из показываемого URL, повтор по статусу. Разойтись им негде, потому что расходиться нечему.
Справочник методов внутри скилла генерируется из spec/metrika-api.json — той самой спеки,
которая обновляется из документации Яндекса ежедневно. Тест сверяет закоммиченный файл с тем,
что сгенерировалось бы сейчас, поэтому «скилл отстал от API» здесь красное, а не незаметное.
Два сознательных отличия команды от MCP:
| MCP | команда | |
|---|---|---|
METRIKA_PROFILE | действует, по умолчанию core | не действует — доступны все 108 методов |
METRIKA_ALLOW_WRITES | нужен для меняющих данные | нужен так же |
Профиль существует, чтобы не платить контекстом за описания невызванных инструментов; у команды в терминале такой цены нет. Гейт записи — про другое: удалённую цель нечем восстановить, и послабление здесь было бы дырой в обход сервера.
Всё на записи приходит из ответа сервера по JSON-RPC: строка добавленного фильтра — из _meta.applied_by_server, строки отчёта — из тела ответа. Ни токена, ни сети: запросы уводятся на локальную заглушку, поэтому прогон повторяется где угодно, включая CI. Переснять запись — npm run demo:record.
Протокольные тесты поднимают сервер как подпроцесс и говорят с ним по JSON-RPC — тем же
способом, каким это делает клиент. Сеть при этом не нужна: METRIKA_API_BASE уводит запросы
на заглушку. Проверяется в том числе то, чего не видно изнутри: что в stdout не попадает
ничего, кроме JSON-RPC, что отказ API приезжает как isError, а не как успешный текст, и что
запись действительно заблокирована.
Евала выбора инструмента. Это единственная проверка, которую не заменяют ни снапшот схемы, ни протокольный тест: описания могут быть синтаксически безупречны, а модель всё равно возьмёт не тот инструмент. Тесты этого не видят по построению — они зовут инструмент по имени, то есть выбор уже сделан за модель.
Здесь это осознанный пропуск, а не забытый пункт. Профиль по умолчанию — десять инструментов, из них шесть отчётов Stat различаются формой ответа, а не темой, и путать их модели особо не с чем. Евал становится нужен, когда поверхность по умолчанию расширяется или когда в неё попадают инструменты с пересекающимися описаниями, — тогда его надо писать до расширения, а не после.
Удалены 26 инструментов-обёрток над пресетами Stat API (get_visits, sources_summary,
get_page_performance и прочие). Они покрывали малую часть API, зашивали измерения и период
в код и не давали задать произвольный запрос. Их заменяют metrika_stat_*, принимающие
параметры Stat API как есть.
Появились методы, которых не было вовсе: список счётчиков, цели, сегменты, фильтры, разрешения, расходы, офлайн-конверсии и весь Logs API. Раньше идентификатор счётчика приходилось знать заранее — теперь его можно найти.
Сервер довели до состояния, в котором его не страшно оставить агенту.
metrika_counter_list
от metrika_counter_delete.METRIKA_ALLOW_WRITES).goal
у создания и правки цели, grant у выдачи доступа) собирались как z.unknown(), а он
в zod необязателен, — обязательное поле уезжало клиенту как опциональное. Теперь это
объединение реальных форм, и обязательность на месте.request_url.Retry-After.npm audit --audit-level=high теперь часть CI.| tee без pipefail, поэтому
код возврата брался у tee и джоба оставалась зелёной при любом падении теста.