Yandex Metrika

Cobertura completa da API do Yandex Metrika (Stat, Management, Logs) com definições de ferramentas geradas a partir da documentação oficial do Yandex. Dez ferramentas expostas por padrão para não sobrecarregar o contexto; nunca reescreve silenciosamente sua consulta.

Documentação

Servidor MCP Yandex Metrika

Servidor MCP para a API do Yandex Metrika. Todos os 108 métodos são cobertos; por padrão, são declarados dez — aqueles usados para análise. O restante é ativado por uma única variável.

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

Fork de atomkraft/yandex-metrika-mcp (upstream — Vadim Bezymianyi, MIT). Desde a versão 2.0.0, as ferramentas não são escritas manualmente, mas geradas a partir da especificação, montada com base na documentação oficial.

Cobertura

APImétodosdos quais no perfil coreexemplos de ferramentas
Management95 (21 recursos)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

O nome da ferramenta é metrika_<ресурс>_<действие>, onde o recurso é retirado da URL da própria API sem renomeações. Portanto, metrika_goal_list é mapeado de forma inequívoca para GET /management/v1/counter/{id}/goals e para sua própria página de documentação.

Contrato

O servidor foi reescrito devido a duas falhas observadas: ele retornava algo diferente do solicitado e silenciosamente injetava um filtro. Daí quatro regras, cada uma coberta por teste.

  1. Sem substituição silenciosa. O que foi solicitado é exatamente o que vai para a API. O servidor não inventa dimensões, períodos ou filtros adicionais.
  2. Tudo o que o servidor adicionou por conta própria é visível na resposta. A resposta chega como {"_meta": {...}, "data": {...}}, onde _meta.applied_by_server lista o que foi adicionado, e _meta.notes — as decisões tomadas em nome do chamador.
  3. Uma recusa continua sendo uma recusa. Um erro da API é retornado com isError: true e o corpo da resposta do Metrika. A repetição é feita com base no status (429/500/502/503/504 e falhas de rede), não por substring no texto; para 429, o Retry-After é respeitado com um teto de 30 segundos. O número de tentativas é sempre visível em _meta.retries.
  4. O corte da saída é visível. Em _meta vão rows_returned, rows_total e truncated — o Metrika corta a resposta por padrão, e não se pode silenciar isso. Se o próprio servidor truncou a resposta devido ao limite de comprimento, isso é declarado separadamente em _meta.truncated_by_server com o número de linhas descartadas.
  5. Segredos não vão para a resposta. metrika_measurement_delete tem o parâmetro token; no _meta.request_url exibido, seu valor é substituído por REDACTED. O próprio token OAuth vai apenas no cabeçalho e nunca aparece na resposta.

Filtro de robôs

Nos relatórios da Stat API, por padrão, é aplicada a própria flag de robô do Metrika, e somente ela:

ym:s:isRobot=='no'

Ele é declarado: visível no esquema da ferramenta, desativado pelo parâmetro human_traffic_only: false e sempre listado em _meta.applied_by_server. Se a solicitação contém métricas ym:ad: ou ym:ev:, o filtro não é aplicado (o Metrika responde a essa combinação com 400) — e isso vai para _meta.notes, em vez de permanecer uma exceção silenciosa.

Sua própria condição é definida pela variável METRIKA_TRAFFIC_FILTER — completamente, incluindo isRobot, se necessário:

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

Isso é um exemplo de formato, não uma recomendação. Qual corte é correto depende de quais bots visitam exatamente o seu site: o corte por país, por cabeçalho do navegador ou por sub-rede só faz sentido com seus próprios dados. Copiar a lista de outra pessoa é inútil e perigoso: ela cortará tráfego real.

A condição personalizada definida é anunciada pelo servidor no stderr na inicialização — ela altera os números em cada relatório, e não se pode silenciar isso.

Comparação de períodos: uma resposta que parece válida

Em metrika_stat_comparison e metrika_stat_comparison_drilldown, as datas dos períodos são opcionais, e o Metrika não reclama da ausência delas. Ele insere sua própria janela (última semana) em ambos os conjuntos e retorna a comparação do período consigo mesmo:

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

O servidor não recusará — a solicitação foi enviada exatamente como foi montada. Mas essa resposta vem com uma marcação em _meta.notes: tanto quando as datas não são definidas quanto quando os períodos coincidem explicitamente.

Como a especificação é estruturada

O Metrika não tem um openapi.json público, mas cada página de método é gerada a partir do OpenAPI pelo mecanismo Diplodoc e é entregue como text/markdown. A semântica (tipo, required, combinador, asserção) está em classes CSS do tipo {.json-schema-property}, portanto a especificação é montada por um scanner linha a linha baseado nas classes, não por um parser de 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 é commitado — é a composição da API no momento da compilação. Um teste de derivação compara com llms.txt: se o Yandex adicionou ou removeu um método, o teste fica vermelho.

A análise está vinculada à versão do gerador (Diplodoc Platform v5.57.3): toda a semântica depende de suas classes, portanto uma divergência de versão interrompe a compilação da especificação, em vez de corrompê-la silenciosamente.

Execução

Por padrão, dez ferramentas de 108 são declaradas — aquelas usadas para análise. O gerenciamento de contadores e metas, acessos e a Logs API são ativados pela variável METRIKA_PROFILE; detalhes abaixo, na seção «Por que nem tudo por padrão».

Também é possível perguntar ao próprio servidor: a ferramenta metrika_catalog_list lista o que está declarado, o que está oculto e como ativar.

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

O token é o OAuth do Yandex, o mesmo usado para Direct e Webmaster.

Por padrão, o servidor mantém o modo stdio. Para um único processo local, ao qual vários clientes MCP se conectam, ative o 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. Com bind em loopback, o servidor também verifica Host, para que o endpoint local não possa ser chamado via DNS rebinding.

Conexão ao cliente

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

A partir de uma compilação local — o mesmo, mas com "command": "node" e o caminho até build/index.js.

A versão principal na linha de execução é fixada intencionalmente: uma mudança de versão principal altera o conjunto de ferramentas padrão, e não se deve receber isso silenciosamente na inicialização do agente.

Variáveis de ambiente

VariávelPadrãoO que faz
YANDEX_API_KEY—Token OAuth. Sem ele, o servidor não inicia.
MCP_TRANSPORTstdioTransporte: stdio ou stateless Streamable http.
MCP_HOST127.0.0.1Endereço do listener HTTP. Usado apenas com MCP_TRANSPORT=http.
MCP_PORT3000Porta do listener HTTP, inteiro de 1 a 65535.
METRIKA_PROFILEcoreQual parte do catálogo é declarada: core (10 ferramentas), read (todas as 51 de leitura), all (todas as 108). Um valor desconhecido derruba a inicialização.
METRIKA_ALLOW_WRITESnão definida1 permite e declara 57 ferramentas que alteram dados. Enquanto não definida — elas não existem em tools/list de forma alguma.
METRIKA_TOOLSvazioSeleção própria separada por vírgulas: seção (stat, logs, management), prefixo do nome (metrika_goal) ou nome exato. Se definida — vence o perfil.
METRIKA_TRAFFIC_FILTERym:s:isRobot=='no'Condição de segmentação adicionada aos relatórios Stat. Definida por completo.
METRIKA_MAX_OUTPUT_CHARS120000Teto de comprimento da resposta de uma única chamada. A exportação da Logs API geralmente não cabe nele — um dia de visitas são centenas de milhares de caracteres; o corte é declarado em _meta.truncated_by_server.
METRIKA_API_BASEvazioSubstituição do endereço da API (proxy, stub em testes). O fato da substituição é impresso no stderr.

Como descobrir o que está oculto sem abrir o README

A ferramenta metrika_catalog_list é declarada em qualquer perfil e responde a partir da especificação contida no pacote — não precisa de token nem de rede:

{
  "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 — …"]
}

Ela existe por um motivo simples: um servidor que ocultou algo deve ser capaz de dizer o quê exatamente e como ativar. instructions vê o modelo, mas não o humano — elas não aparecem na interface do cliente; a linha de inicialização no stderr também não é aberta por ninguém no trabalho normal. Sem essa ferramenta, só seria possível descobrir sobre as outras 98 vindo até aqui.

A lista de ferramentas na resposta é construída a partir da mesma seleção usada para registrá-las — não há como divergir da realidade, e isso é verificado por teste.

Por que nem tudo por padrão

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

As descrições das ferramentas declaradas ficam no contexto do modelo quando o cliente as carrega. Esse é o custo do servidor, pago pelo próprio fato da conexão, não pelas chamadas. Medição tools/list (09.09.2026):

PerfilFerramentastools/listtokens
core (padrão)10 + catálogo32 181 B14,8 mil
read51 + catálogo68 074 B~31 mil — estimativa
all + METRIKA_ALLOW_WRITES=1108 + catálogo158 301 B~73 mil — estimativa

Medição core — 14,5 mil antes do catálogo e 14,8 depois: a própria ferramenta custa cerca de 670 bytes de esquema, aproximadamente 2% do conjunto. Sua resposta não entra nesse custo — ela é paga apenas na chamada.

Os bytes são exatos, qualquer um pode reproduzi-los: serialize a resposta de tools/list e calcule o comprimento. Com tokens é mais complicado, e aqui vale ser direto.

⚠️ A medição é honesta apenas para core — foi fornecida pelo /context do cliente, que calcula com seu próprio tokenizador. As outras duas linhas foram recalculadas de bytes pela calibração 2,17 bytes por token, obtida da mesma linha de core.

A heurística comum «4 caracteres por token» aqui erra quase pela metade: ela foi derivada de texto em inglês, e as descrições deste servidor são em russo, e o cirílico na tokenização BPE é aproximadamente duas vezes pior que o latim. A primeira edição desta tabela foi construída exatamente com ela e chamava para core 7,9k em vez de 14,5k. Se você calcula o orçamento de contexto para um servidor com descrições não-inglesas — use um tokenizador, não divisão por quatro.

A composição de core foi derivada da medição de uso real, não de gosto: seis relatórios Stat mais diretórios, sem os quais o relatório não pode ser montado (metrika_counter_list, metrika_counter_get, metrika_goal_list, metrika_segment_list). O limite de peso é protegido por teste — o manifesto não pode ficar mais caro silenciosamente. O limite no teste é em bytes: eles não dependem nem do tokenizador, nem do idioma das descrições.

Segurança

  • Escrita desativada por padrão, e ferramentas que alteram dados não são declaradas de forma alguma. Entre os métodos, há quatorze DELETE e cinco de exclusão POST (.../measurement/delete, .../expense/delete, .../logrequest/{id}/clean etc.). O custo de uma chamada errônea — um contador ou meta removido sem possibilidade de restaurar o histórico. O modelo não pode chamar o que não vê em tools/list; como ativar — está dito em instructions do servidor.
  • Anotações estão presentes em todas as ferramentas (readOnlyHint, destructiveHint, idempotentHint, openWorldHint). O cliente distingue leitura de exclusão por elas: exclusão sob o verbo POST é marcada como destrutiva, PUT — também, porque substitui a entidade por completo.
  • As respostas do Metrika são dados não confiáveis. Nos relatórios estão frases de busca, títulos de páginas, referers e valores de UTM, ou seja, strings escritas pelos visitantes do site. Qualquer pessoa pode acessar o site por um link com texto dentro e vê-lo no relatório. Todas as ferramentas têm openWorldHint: true, e em _meta.notes de relatórios e exportações há um lembrete de que são dados, não instruções.
  • stdio continua sendo o transporte padrão. HTTP é ativado apenas explicitamente via MCP_TRANSPORT=http; o padrão seguro escuta em 127.0.0.1 e verifica Host.

Política de privacidade

O servidor não coleta, não armazena e não transmite dados sobre você para lugar nenhum. Sem telemetria, sem análise, sem chamadas aos servidores do autor — elas não existem: nenhuma infraestrutura foi montada para este pacote.

O único destinatário de rede é https://api-metrika.yandex.net. O token é lido de YANDEX_API_KEY para a memória do processo e não é escrito em lugar nenhum: nem em arquivo, nem em stdout, nem no corpo da resposta. Os dados dos relatórios não são armazenados em cache no disco e não sobrevivem ao processo.

Os dados que você solicita são processados pelo Yandex como operador do Metrika — a isso se aplica a política dele, não esta.

Texto completo: PRIVACY.md.

Instalação em um único arquivo (MCPB)

Para Claude Desktop e outros clientes que entendem bundles MCP, existe um arquivo .mcpb — ele está nos releases. Você abre o arquivo, insere o token na janela de instalação — pronto.

O bundle é compilado a partir do mesmo código com a mesma tag (npm run mcpb), e seu manifesto é gerado a partir de package.json e do perfil — não é escrito manualmente, portanto não há como divergir do servidor; isso é verificado por teste.

⚠️ No bundle, não é possível habilitar a gravação. O custo de uma chamada equivocada é um contador ou objetivo removido sem possibilidade de recuperar o histórico, e não há o que alternar nesse interruptor na janela de instalação. Precisa de gravação? Instale o pacote via npm e habilite-a conscientemente, por variável de ambiente.

Sem MCP: skill e linha de comando

MCP não serve para todos nem sempre: o cliente pode não suportar MCP, e as descrições das ferramentas ocupam contexto constantemente — elas ficam nele enquanto o servidor está conectado, você as chame ou não.

Para esse caso, o mesmo servidor pode ser iniciado por 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 isso, existe um skill — uma pasta com instruções para o agente, instalada com uma única linha:

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

O skill não adiciona ferramentas ao cliente nem mantém nada no contexto: ele só é lido quando o assunto é Metrika. Dentro dele estão o mesmo comando, o guia de referência de todos os 108 métodos e o dicionário de dimensões.

Onde ele funciona. O instalador coloca uma instância em .agents/skills/yandex-metrika/ e cria symlinks para as pastas de agentes específicos. Verificado executando em dois:

agentedetecçãocomo foi verificado
Claude Code.claude/skills/ → symlink/yandex-metrika responde com base no conteúdo do skill
Codex.agents/skills/ diretamenteinforma o caminho para SKILL.md; nenhuma linha em AGENTS.md, nem configuração em config.toml é necessária para isso

O instalador declara suporte a cerca de vinte outros agentes pelo mesmo catálogo universal (Amp, Cline, Antigravity, Augment e outros) — nesses, não verificamos.

Por que isso não é uma segunda implementação. A CLI não faz nenhuma requisição própria: ela analisa argumentos e chama executeMethod — a mesma função usada pelas ferramentas MCP. Daí as mesmas garantias: filtro de robôs nos relatórios, teto de resposta com aviso de truncamento, limpeza de segredos da URL exibida, repetição por status. Não há como divergirem, porque não há o que divergir.

O guia de referência de métodos dentro do skill é gerado a partir de spec/metrika-api.json — a mesma spec que é atualizada diariamente pela documentação do Yandex. Um teste compara o arquivo commitado com o que seria gerado agora, então "skill desatualizado em relação à API" aqui é algo visível, não imperceptível.

Duas diferenças conscientes do comando em relação ao MCP:

MCPcomando
METRIKA_PROFILEativo, por padrão coreinativo — todos os 108 métodos disponíveis
METRIKA_ALLOW_WRITESnecessário para operações que alteram dadosigualmente necessário

O perfil existe para não pagar com contexto pelas descrições de ferramentas não chamadas; o comando no terminal não tem esse custo. O bloqueio de gravação é outra coisa: um objetivo remoto não tem como ser restaurado, e uma flexibilização aqui seria uma brecha contornando o servidor.

Verificações

Não é maquete — execute você mesmo

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

Tudo na gravação vem da resposta do servidor via JSON-RPC: a linha do filtro adicionado vem de _meta.applied_by_server, as linhas do relatório vêm do corpo da resposta. Sem token, sem rede: as requisições são direcionadas a um stub local, então a execução pode ser repetida em qualquer lugar, inclusive no CI. Para regravar — npm run demo:record.

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

Os testes de protocolo iniciam o servidor como subprocesso e falam com ele via JSON-RPC — da mesma forma que um cliente faz. Rede não é necessária: METRIKA_API_BASE direciona as requisições para um stub. Verifica-se inclusive o que não é visível internamente: que nada além de JSON-RPC aparece no stdout, que uma falha da API chega como isError, e não como texto de sucesso, e que a gravação está realmente bloqueada.

O que NÃO está nas verificações

Eval de seleção de ferramenta. Esta é a única verificação que nem o snapshot do schema nem o teste de protocolo substituem: as descrições podem estar sintaticamente impecáveis, mas o modelo ainda assim pode escolher a ferramenta errada. Os testes não enxergam isso por construção — eles chamam a ferramenta pelo nome, ou seja, a seleção já foi feita pelo modelo.

Aqui, isso é uma omissão consciente, não um item esquecido. O perfil padrão tem dez ferramentas, das quais seis relatórios Stat diferem pela forma da resposta, não pelo tema, e não há muito com o que o modelo possa confundir. O eval se torna necessário quando a superfície padrão se expande ou quando entram ferramentas com descrições sobrepostas — nesse caso, ele deve ser escrito antes da expansão, não depois.

O que mudou na 2.0.0

Foram removidas 26 ferramentas-wrapper sobre presets da Stat API (get_visits, sources_summary, get_page_performance e outras). Elas cobriam uma pequena parte da API, fixavam dimensões e período no código e não permitiam fazer uma consulta arbitrária. Elas são substituídas por metrika_stat_*, que aceitam os parâmetros da Stat API como estão.

Surgiram métodos que não existiam: lista de contadores, objetivos, segmentos, filtros, permissões, gastos, conversões offline e todo o Logs API. Antes, o identificador do contador precisava ser conhecido de antemão — agora ele pode ser encontrado.

O que mudou na 2.1.0

O servidor foi levado a um estado em que não é arriscado deixá-lo com um agente.

  • Anotações em todas as 108 ferramentas. Antes, o cliente não distinguia metrika_counter_list de metrika_counter_delete.
  • Gravação desativada por padrão (METRIKA_ALLOW_WRITES).
  • Defeito de parsing da documentação encontrado e corrigido. As asserções eram marcadas por uma linha em que o valor vem depois do parêntese de fechamento da classe — o reconhecedor de propriedades estava ancorado no fim da linha e não correspondia a essas linhas. Como resultado, nenhum exemplo, valor padrão ou limite chegava à spec, e parte deles caía na descrição do campo vizinho. Agora a spec tem 288 exemplos, 69 valores padrão e 155 limites; os limites são transferidos para o schema da ferramenta, e exemplos e valores padrão — para as descrições dos parâmetros.
  • Perda de obrigatoriedade encontrada e corrigida. Parâmetros do tipo "um de N tipos" (goal na criação e edição de objetivo, grant na concessão de acesso) eram montados como z.unknown(), que é opcional no zod — o campo obrigatório ia para o cliente como opcional. Agora é uma união das formas reais, e a obrigatoriedade está no lugar.
  • Referências a entidades são expandidas em um nível: em 23 parâmetros de corpo, em vez de um objeto livre, os campos reais ficam visíveis.
  • Flexibilizações na entrada onde são inofensivas. Número como string, booleano como palavra, lista separada por vírgula na query string — são aceitos; no corpo da requisição, onde o JSON exato importa, não são aceitos.
  • Teto de tamanho de resposta com truncamento declarado: uma exportação do Logs API pode ter centenas de megabytes.
  • Limpeza de segredos do request_url exibido.
  • Repetição em 429 respeitando Retry-After.
  • SDK atualizado para 1.30 — na 1.17 havia três vulnerabilidades publicadas, duas graves; npm audit --audit-level=high agora faz parte do CI.
  • Job de drift no CI corrigido. Ela executava os testes via | tee sem pipefail, então o código de retorno era obtido de tee e o job permanecia verde em qualquer falha de teste.