seo-tools-mcp

Cinco servidores MCP somente leitura para SEO no mercado Google/Yandex (RU/CIS): SERP (XMLStock), Yandex Wordstat, Google Search Console, Yandex.Webmaster, Yandex.Metrica.

Documentação

seo-tools-mcp

seo-tools-mcp

CI License: MIT GitHub MCP Registry

Русский | English

Oito servidores MCP stdio universais para SEO: acesso a SERP, Wordstat, Google Search Console, Google Analytics 4, Yandex.Webmaster, Yandex.Metrica e A-Parser self-hosted diretamente do Claude Code (e de qualquer cliente MCP). Todas as ferramentas são read-only — nada é publicado ou alterado nas suas contas, a saída é JSON estrito. Isso é declarado de forma legível por máquina pela anotação readOnlyHint; ela está deliberadamente ausente em vinte ferramentas, cada chamada das quais consome um recurso pago (requisição ao XMLStock/XMLRiver, tráfego de proxy do A-Parser) — caso contrário, o cliente as consideraria inofensivas e pararia de pedir confirmação antes de executar em um grande pool. Não são vinculadas a um site específico: os padrões (propriedade GSC, propriedade GA4, host do Webmaster, contador da Metrica) são configurados em tempo real.

🛰 Usamos esses servidores em produção no PBN Workers — infraestrutura de topo de busca: semântica, PBN e satélites, automação de SEO. Precisa de tráfego orgânico estável — venha.

ServidorFerramentas de trabalhoAutenticação
xmlstockxmlstock_serp, xmlstock_images, xmlstock_news, xmlstock_video, xmlstock_wordstat, xmlstock_wordstat_dynamics, xmlstock_wordstat_regions, xmlstock_wordstat_regions_tree, xmlstock_balanceChave de API
xmlriverxmlriver_serp, xmlriver_images, xmlriver_news, xmlriver_maps, xmlriver_check_index, xmlriver_suggest, xmlriver_related_questions, xmlriver_balanceChave de API
wordstatwordstat_frequency, wordstat_dynamics, wordstat_regions, wordstat_regions_treeApi-Key Yandex Cloud
gscgsc_query, gsc_inspect_url, gsc_list_sites, gsc_get_site, gsc_list_sitemaps, gsc_get_sitemapOAuth (todas as propriedades da conta) / service account
ga4ga4_list_properties, ga4_property_details, ga4_metadata, ga4_check_compatibility, ga4_report, ga4_bytime, ga4_traffic_sources, ga4_geo, ga4_devices, ga4_top_pages, ga4_events, ga4_funnel, ga4_annotations, ga4_realtimeOAuth (todas as propriedades da conta) / service account
ywmywm_hosts, ywm_summary, ywm_search_queries, ywm_queries_history, ywm_recommended_queries, ywm_popular, ywm_indexing_history, ywm_sqi_history, ywm_external_links, ywm_broken_links, ywm_diagnostics, ywm_important_urls, ywm_sitemapsOAuth (auto-refresh)
metrikametrika_report, metrika_bytime, metrika_counters, metrika_goals, metrika_traffic_sources, metrika_geo, metrika_devices, metrika_landing_behavior, metrika_search_phrases, metrika_top_landingsOAuth (auto-refresh)
aparseraparser_ping, aparser_status, aparser_proxies, aparser_parsers, aparser_parser_fields, aparser_get_preset, aparser_serp_google, aparser_serp_yandex, aparser_suggest, aparser_request, aparser_bulk_requestA-Parser self-hosted (URL + senha da API)

Onde está publicado: npm (oito pacotes), MCP Registry oficial, GitHub MCP Registry (todos os oito servidores), marketplace de plugins do Claude Code (veja abaixo) e bundles .mcpb nos releases.

Cada servidor também possui ferramentas de autenticação <server>_auth_status e <server>_set_credentials (veja Autorização interativa).

Ferramentas por serviço

xmlstock — SERP Google/Yandex

  • xmlstock_serp — resultados web do Google/Yandex (orgânicos + destaques + recursos de SERP): região, dispositivo, safe search, ordenação (Yandex), período, blocos de anúncios; terceiro motor yandex_xml — Yandex XML oficial (groupby até 100 por 1 requisição, hlword em qualquer dispositivo, estatísticas found/found-docs; tarifa a partir de 24 ₽/1000)
  • xmlstock_images — busca de imagens do Google (url da página + url da imagem + título)
  • xmlstock_news — notícias do Google (título, fonte, data, snippet)
  • xmlstock_video — vídeos do Google (url, título, prévia, host, canal, duração)
  • xmlstock_wordstat — Yandex Wordstat: topo + consultas semelhantes com frequência (possível por região), operadores do Wordstat
  • xmlstock_wordstat_dynamics — dinâmica de frequência ao longo do tempo (dia/semana/mês)
  • xmlstock_wordstat_regions — demanda por regiões (count, share, affinity index + nomes das regiões)
  • xmlstock_wordstat_regions_tree — árvore de regiões do Wordstat (id + nome + caminho)
  • xmlstock_balance — saldo da conta / verificação de chave (grátis)

Wordstat via XMLStock — com a mesma chave XMLSTOCK_* do SERP; não precisa de Yandex Cloud (diferente do servidor separado wordstat).

xmlriver — SERP Google/Yandex + verificação de indexação

  • xmlriver_serp — orgânicos do Google/Yandex (profundidade obtida por paginação: cada 10 posições = 1 requisição paga), flag de presença de AI Overview; opção includeAIOverview — texto completo do Resumo de IA + links citados (pago ai=1, apenas Google); includeAdditional — blocos SERP adicionais do Google de <addresults> (knowledge_graph, localresultsplace, rs e outros; o conteúdo depende das opções pagas do painel do XMLRiver, blocos não recebidos — em additional.unavailable); geo-targeting do Google — location (cidade → loc, «Moscow»/«1011969») e country (ISO/id numérico, inferido automaticamente da cidade); device — desktop/mobile/tablet, os (ios/android) enviado apenas com device=mobile
  • xmlriver_images — imagens do Google (página + url da imagem + título + fonte + dimensões); geo — location/country
  • xmlriver_news — notícias do Google (título, fonte, data, snippet), filtro por tempo; geo — location/country
  • xmlriver_maps — busca de estabelecimentos no Google Maps (setab=maps, obrigatórios zoom 1–15 e coords «latitude,longitude», count 5–50): nome, avaliação, endereço, telefone, serviços, coordenadas, place_id, número de avaliações. IMPORTANTE: formato conforme a documentação, não confirmado ao vivo (no conta de teste o endpoint responde consistentemente com código 500 — provavelmente é necessária uma opção paga do painel)
  • xmlriver_check_index — verificação de indexação de URL no Google/Yandex (inindex)
  • xmlriver_suggest — sugestões de busca do Google (até 50 frases por chamada, pago por cada frase); geo das sugestões — location/country
  • xmlriver_related_questions — bloco «Perguntas relacionadas» / People Also Ask do Google (perguntas sempre; respostas — apenas com a opção paga «Related Questions com respostas» ativada no painel)
  • xmlriver_balance — saldo da conta / verificação de chave (grátis)

wordstat — frequências do Yandex

  • wordstat_frequency — frequência ampla e exata, consultas de refinamento (related) e associações
  • wordstat_dynamics — frequência ao longo do tempo (dia/semana/mês)
  • wordstat_regions — distribuição por regiões com índice de afinidade e nomes das regiões
  • wordstat_regions_tree — árvore completa de regiões do Wordstat (id + nome)

gsc — Google Search Console

  • gsc_query — Search Analytics (cliques/impressões/CTR/posição), auto-paginação, dataState final/all, filtros arbitrários de dimensões (filters, semântica AND) e aggregationType (auto/byProperty/byPage)
  • gsc_inspect_url — URL Inspection: status de indexação, cobertura, canonical, último rastreamento, mobile usability, rich results
  • gsc_list_sites — propriedades disponíveis para a autorização
  • gsc_get_site — nível de acesso à propriedade
  • gsc_list_sitemaps — sitemaps enviados com status
  • gsc_get_sitemap — detalhes de um sitemap

Datas do Search Analytics — no fuso Pacific Time (não MSK); histórico de ~16 meses; dados finais atrasam ~2-3 dias (recentes — dataState=all); ctr na resposta — proporção 0..1.

ga4 — Google Analytics 4

  • ga4_list_properties — propriedades GA4 disponíveis para a autorização (daqui vem o propertyIdnão é o Measurement ID G-XXXXXXX)
  • ga4_metadata — quais dimensões e métricas estão disponíveis NESTA propriedade, incluindo personalizadas (customEvent:…); busca por substring, blockedReasons (por essa métrica o relatório retornará zeros) e type (inteiro/decimal para metricFilters)
  • ga4_check_compatibility — se a combinação de dimensões/métricas é compatível nesta propriedade, sem relatório pesado; se incompatível — quais campos remover
  • ga4_report — relatório arbitrário: quaisquer dimensões × métricas, filtros por dimensões, ordenação (Data API completo runReport)
  • ga4_bytime — dinâmica de métricas ao longo do tempo (dia/hora/semana/mês)
  • ga4_traffic_sources — fontes de tráfego: grupo de canais, source/medium, campanha; organicOnly — apenas orgânico
  • ga4_geo — país/região/cidade
  • ga4_devices — tipo de dispositivo/SO/navegador
  • ga4_top_pages — top de páginas por pagePath, página de entrada ou título; filtros organicOnly e pathContains
  • ga4_events — eventos por eventName; keyEventsOnly — apenas eventos-chave (antigas conversões)
  • ga4_realtime — relatório em tempo real (últimos 30 minutos)
  • ga4_funnel — funil (runFunnelReport): quantos chegaram a cada etapa e onde desistiram; etapa = evento e/ou condições por dimensões, detalhamento por dimensão. Dentro das etapas vale o esquema da Exploration API (pagePath indisponível lá), a cota é separada e a consulta é mais cara que um relatório comum
  • ga4_annotations — anotações da propriedade: marcações em datas, incluindo as criadas pela própria GA4 (systemGenerated) — explicação frequente para um salto inexplicável na dinâmica
  • ga4_property_details — cartão da propriedade: fuso horário dos relatórios, moeda, nível de serviço (STANDARD/360) e fluxos de dados com seus Measurement ID G-XXXXXXX

Em todas as ferramentas de relatório há includeQuota — quantos «tokens» do Data API a consulta consumiu e quantos restam por hora/dia.

Unidades e datas: bounceRate/engagementRate o GA4 retorna como proporção 0..1 (não porcentagens); as datas são calculadas no fuso horário da propriedade — aceita YYYY-MM-DD e palavras-chave do GA4 (today, yesterday, 28daysAgo), o fuso real é retornado na resposta. Nas respostas há totalRows/truncated, e thresholded: true significa que parte dos dados está oculta pelo limite de confidencialidade do GA4.

ywm — Yandex.Webmaster

  • ywm_hosts — id do usuário + sites confirmados
  • ywm_summary — IKS, páginas na busca, excluídas, problemas do site por importância
  • ywm_search_queries — análise de consultas por URL (~2 semanas por padrão; sobrescrito por dateFrom/dateTo)
  • ywm_queries_history — impressões/cliques/posições totais ao longo do tempo
  • ywm_recommended_queries — consultas recomendadas aproximadas (demanda + déficit de cliques)
  • ywm_popular — consultas populares do host
  • ywm_indexing_history — páginas na busca ao longo do tempo
  • ywm_sqi_history — IKS ao longo do tempo
  • ywm_external_links — amostra de links externos + número total
  • ywm_broken_links — links internos/externos quebrados
  • ywm_diagnostics — problemas do site
  • ywm_important_urls — URLs monitoradas com status de indexação/busca
  • ywm_sitemaps — sitemaps com status

metrika — Yandex.Metrica

  • metrika_report — relatório arbitrário: quaisquer dimensions × metrics, filtros, ordenação (Stat API completo)
  • metrika_bytime — métricas ao longo do tempo (dia/semana/mês/hora)
  • metrika_traffic_sources — visitas/usuários/rejeições por fontes de tráfego
  • metrika_geo — visitas por país/região/cidade
  • metrika_devices — visitas por dispositivo/SO/navegador
  • metrika_goals — lista de metas (conversões)
  • metrika_counters — contadores disponíveis
  • metrika_landing_behavior — comportamento nas páginas de destino + alcance de metas
  • metrika_search_phrases — frases de busca (orgânico)
  • metrika_top_landings — top de páginas de destino orgânicas

aparser — ponte para o A-Parser self-hosted

  • aparser_ping — verificação de conexão com a instância e senha da API
  • aparser_status — veredito de prontidão: versão, parsers instalados, fila, proxies vivos
  • aparser_proxies — proxies vivos da instância (pode ser em lotes de proxy checkers; credenciais de proxy não são exibidas)
  • aparser_parsers — parsers instalados na instância
  • aparser_parser_fields — campos de resultado que o parser consegue retornar (flat + arrays)
  • aparser_get_preset — opções do preset de config do parser (valores sensíveis são mascarados)
  • aparser_serp_google — orgânico do Google (parser SE::Google); proxy padrão + preflight de proxies vivos
  • aparser_serp_yandex — orgânico do Yandex (SE::Yandex); região via lr
  • aparser_suggest — sugestões de busca do Google/Yandex
  • aparser_request — requisição síncrona universal para qualquer parser (oneRequest)
  • aparser_bulk_request — requisição em lote: um parser, muitas requisições em N threads (bulkRequest)

É necessário ter sua própria instância em execução do A-Parser (licença + servidor): a ponte gerencia, mas não hospeda nem faz proxy para ela. Proxies e proxy checkers (lotes) são configurados uma vez na GUI do A-Parser — a ponte os lê, verifica (preflight) e seleciona (checkers), mas não os cria. v1 é síncrono e somente leitura: fila de tarefas e grandes exportações assíncronas não estão conectadas.

Início rápido

Opção 1 — com um clique para Claude Desktop (.mcpb)

A forma mais simples, sem precisar instalar nada manualmente: baixe o .mcpb desejado na página de releases e abra com duplo clique — o Claude Desktop instalará o servidor sozinho e pedirá as chaves no diálogo de instalação.

  • Servidores com chave de API (xmlstock, xmlriver, wordstat, aparser) — as chaves são inseridas diretamente no instalador.
  • Servidores com OAuth (gsc, ga4, ywm, metrika) não pedem nada: a autorização acontece no chat (<server>_oauth_start<server>_oauth_finish).

Os bundles são autossuficientes (~0,2 MB, dependências inclusas); Node.js 20+ é necessário apenas para a opção com npx. Para compilar você mesmo: pnpm build:mcpb.

Opção 2 — plugin para Claude Code (marketplace)

Equivalente ao .mcpb, mas para Claude Code: servidor, chaves e dicas são instalados com um único comando, as chaves são solicitadas via diálogo e os segredos vão para o armazenamento do sistema, não para um arquivo aberto.

claude plugin marketplace add antohins/seo-tools-mcp

Em seguida — apenas as fontes necessárias; cada plugin puxa exatamente um servidor:

claude plugin install xmlstock@seo-tools-mcp
claude plugin install gsc@seo-tools-mcp
claude plugin install ga4@seo-tools-mcp

Estão disponíveis xmlstock, xmlriver, wordstat, gsc, ga4, ywm, metrika, aparser — e o seo-tools, que instala todos os oito de uma vez. O bundle é conveniente, mas são ~100 ferramentas em cada sessão: se você trabalha apenas com Webmaster e Metrica, instale dois plugins em vez do bundle.

As chaves podem ser inseridas imediatamente (--config KEY=VALUE) ou depois via /plugin configure <плагин>@seo-tools-mcp:

claude plugin install xmlstock@seo-tools-mcp --config XMLSTOCK_USER=12345 --config XMLSTOCK_KEY=...

Campos marcados como secretos (chaves de API, segredos OAuth) são colocados pelo Claude Code no armazenamento do sistema; eles não aparecem no settings.json. Plugins com OAuth (gsc, ga4, ywm, metrika) pedem apenas client_id/secret na instalação — o login em si acontece no chat via <сервер>_oauth_start<сервер>_oauth_finish.

Junto com o servidor, o plugin traz habilidades — instruções procedurais sobre sua fonte: como não queimar o saldo ao coletar posições, por que o freq_broad infla o tráfego várias vezes, por que o GA4 retorna zeros silenciosamente, como a posição média do GSC difere da coletada na busca. No contexto, elas ocupam sempre ~110 tokens por habilidade e são expandidas apenas quando realmente necessárias.

Opção 3 — via npx (sem clonagem)

Cada servidor é um pacote npm autossuficiente seo-tools-mcp-<сервер>; instala-se com um único comando:

claude mcp add xmlstock --scope user -- npx -y seo-tools-mcp-xmlstock
claude mcp add xmlriver --scope user -- npx -y seo-tools-mcp-xmlriver
claude mcp add wordstat --scope user -- npx -y seo-tools-mcp-wordstat
claude mcp add gsc      --scope user -- npx -y seo-tools-mcp-gsc
claude mcp add ga4      --scope user -- npx -y seo-tools-mcp-ga4
claude mcp add ywm      --scope user -- npx -y seo-tools-mcp-ywm
claude mcp add metrika  --scope user -- npx -y seo-tools-mcp-metrika
claude mcp add aparser  --scope user -- npx -y seo-tools-mcp-aparser

Precisa de apenas um servidor?

Os servidores não são interligados: pegue um único pacote e ignore os demais. Cada um é autossuficiente — o código comum @seo-tools/shared está embutido no build, então não há dependências extras nem "cauda" do monorepo. Basta instalar o pacote desejado do npm — já vem tudo pronto (npx -y baixa e executa automaticamente):

Pacote (npm)Servidor
seo-tools-mcp-xmlstockSERP Google/Yandex + Wordstat
seo-tools-mcp-xmlriverSERP Google/Yandex + verificação de indexação
seo-tools-mcp-wordstatfrequências do Yandex (Yandex Cloud)
seo-tools-mcp-gscGoogle Search Console
seo-tools-mcp-ga4Google Analytics 4
seo-tools-mcp-ywmYandex.Webmaster
seo-tools-mcp-metrikaYandex.Metrica
seo-tools-mcp-aparserponte para o A-Parser self-hosted
# добавить один сервер в Claude Code
claude mcp add xmlstock --scope user -- npx -y seo-tools-mcp-xmlstock

# или запустить напрямую (ключи через env)
XMLSTOCK_USER=... XMLSTOCK_KEY=... npx -y seo-tools-mcp-xmlstock

Em qualquer cliente MCP (Claude Desktop, Cursor…) — basta adicionar um bloco no mcpServers:

{
  "mcpServers": {
    "xmlstock": {
      "command": "npx",
      "args": ["-y", "seo-tools-mcp-xmlstock"],
      "env": { "XMLSTOCK_USER": "...", "XMLSTOCK_KEY": "..." }
    }
  }
}

Instalação direta de um único pacote via link do GitHub (npm i github:antohins/seo-tools-mcp) não é suportada: é um monorepo pnpm, um subpacote separado não pode ser instalado assim. Para instalar a partir do código-fonte — opção B abaixo (clonar + compilar). Os pacotes prontos estão no npm.

Opção 4 — a partir do código-fonte

git clone https://github.com/antohins/seo-tools-mcp.git && cd seo-tools-mcp
pnpm install && pnpm build
ROOT=$(pwd)
for s in xmlstock xmlriver wordstat gsc ga4 ywm metrika aparser; do
  claude mcp add "$s" --scope user -- node "$ROOT/servers/$s/dist/index.js"
done

Em seguida (qualquer opção) — direto no diálogo do Claude Code: "configure acesso ao xmlstock" → o agente chamará xmlstock_auth_status, indicará quais chaves são necessárias e onde obtê-las, receberá via xmlstock_set_credentials e salvará. Depois disso, faça perguntas em linguagem natural: "colete o top-10 do Yandex para a consulta X", "frequência das frases …", "cliques/impressões do GSC no último mês". Chaves e OAuth são configurados uma única vez (veja Obtendo acessos).

Autorização interativa (em qualquer sessão)

Cada servidor possui ferramentas de auth — as chaves podem ser fornecidas diretamente no diálogo, sem editar arquivos ou reiniciar:

  • <server>_auth_status — chamado no início do trabalho: mostra quais chaves estão definidas (mascaradas), quais faltam e como obtê-las (etapas de registro).
  • <server>_set_credentials — salva os valores fornecidos no ~/.config/seo-tools-mcp/.env (permissões 600) e aplica imediatamente.
  • gsc_save_sa_json — aceita o conteúdo do JSON da chave da conta de serviço, coloca-o no diretório de config e retorna o email que precisa ser adicionado ao GSC.
  • ywm_oauth_start / metrika_oauth_start → link de autorização do Yandex; o usuário abre, permite, copia o código → *_oauth_finish troca o código por tokens access+refresh. Depois disso, o token é renovado automaticamente ao expirar (code flow, não implicit).

Cenário típico de nova sessão: "configure acesso ao xmlstock" → o agente chama xmlstock_auth_status → solicita as chaves ausentes → xmlstock_set_credentials → trabalha.

⚠ Chaves fornecidas pelo chat passam pelo contexto do modelo. Para máxima higiene, você ainda pode inseri-las manualmente no ~/.config/seo-tools-mcp/.env — os servidores carregam o arquivo sozinhos.

Multi-conta

Os sites dos clientes estão distribuídos em diferentes contas Google/Yandex — perfis nomeados são suportados:

  • Cada ferramenta de trabalho aceita um parâmetro opcional account ("clientX", "agency"...). Sem ele, o perfil principal é usado — compatibilidade total com versões anteriores.
  • As chaves do perfil ficam no mesmo config com sufixo: GSC_REFRESH_TOKEN__clientX, YANDEX_OAUTH_TOKEN__clientX, XMLSTOCK_KEY__clientX
  • Adicionar perfil: gsc_oauth_start(account="clientX") → o usuário autoriza com uma conta Google diferentegsc_oauth_finish(account="clientX"). Analogamente, ywm_oauth_start/finish(account=...) para Yandex; chaves de API — <server>_set_credentials(account="clientX", ...).
  • Os apps OAuth são compartilhados: um único Google-client e um único app Yandex atendem todos os perfis (o cliente é criado uma vez, autorizações — quantas forem necessárias). Apenas tokens são armazenados por conta; o refresh renova o token do próprio perfil.
  • Resolução estrita: account="clientX" sem chaves configuradas → erro com a lista de perfis configurados (sem fallbacks silenciosos para outra conta). Os padrões (GSC_SITE_URL__clientX, YWM_HOST_ID__clientX, METRIKA_COUNTER_ID__clientX) também são por conta.
  • <server>_auth_status mostra todos os perfis e suas chaves (mascaradas).
  • Alternativa para isolamento rígido: arquivo env separado via SEO_TOOLS_MCP_ENV (com caminho definido, o config doméstico NÃO é lido).

Instalação

cd seo-tools-mcp
pnpm install
pnpm build

Segredos

Arquivo env único: ~/.config/seo-tools-mcp/.env (permissões 600). Todos os servidores o leem na inicialização, e *_set_credentials/*_oauth_finish gravam nele automaticamente — edição manual não é obrigatória. Modelo — .env.example. Variáveis do ambiente do processo têm prioridade sobre o arquivo. Caminho alternativo para o arquivo — SEO_TOOLS_MCP_ENV (assim um host pode manter vários perfis independentes: diferentes claude mcp add com diferentes SEO_TOOLS_MCP_ENV).

Registro no Claude Code

ROOT=/path/to/seo-tools-mcp
claude mcp add xmlstock --scope user -- node $ROOT/servers/xmlstock/dist/index.js
claude mcp add wordstat --scope user -- node $ROOT/servers/wordstat/dist/index.js
claude mcp add gsc      --scope user -- node $ROOT/servers/gsc/dist/index.js
claude mcp add ga4      --scope user -- node $ROOT/servers/ga4/dist/index.js
claude mcp add ywm      --scope user -- node $ROOT/servers/ywm/dist/index.js
claude mcp add metrika  --scope user -- node $ROOT/servers/metrika/dist/index.js

--scope user — disponível em todas as sessões/projetos. Para compartilhar com a equipe — --scope project (criará .mcp.json no repositório; segredos devem ser inseridos apenas via ${VAR}).

Obtendo acessos (por serviço)

Tudo nesta seção está duplicado nas respostas do <server>_auth_status — o agente indicará os passos sozinho. Abaixo — para leitura humana.

XMLStock (prioridade 1) — SERP Google + Yandex

  1. Registro: https://xmlstock.com → painel pessoal, adicione saldo (Google XML e Yandex Live — a partir de 12 ₽/1000 requisições).
  2. Pegue o ID do usuário e a chave de API → XMLSTOCK_USER, XMLSTOCK_KEY (ou via xmlstock_set_credentials).
  3. Verificação: xmlstock_balance.

Nuances (descobertas em respostas reais):

  • destaques da busca (text_bolds) — parâmetro hlword=1, tag <hlword> no XML aninhado (parseado via stopNodes, palavras vizinhas são unidas em frases); PAA e related searches — related=1 (PAA apenas no Google);
  • a busca mobile não retorna hlword/PAA/related — o snapshot mobile traz apenas posições+snippets; destaques devem ser coletados no desktop;
  • páginas com 0 em ambos os mecanismos; orgânico por página pode ser <10 — o servidor completa com mais uma página (+1 requisição paga);
  • lr aceita IDs de regiões do Yandex para ambos os mecanismos (XMLStock mapeia para o Google automaticamente);
  • erros HTTP 200 + <error code>: 20–25/101/110/111/500 são repetidos, 55 — rate-limit com pausa, 15 = resultado vazio (dinheiro debitado), 31/42 — fatais (autorização);
  • XMLStock NÃO tem Wordstat — frequências via servidor separado (API oficial do Wordstat do Yandex).

Wordstat (prioridade 1) — frequências do Yandex

Wordstat API v2 oficial (parte do Yandex Cloud Search API) — gratuito, sem solicitações nem OAuth. Uma vez no https://console.yandex.cloud:

  1. Crie um diretório (folder) ou use um existente → o ID dele no WORDSTAT_FOLDER_ID.
  2. Crie uma conta de serviço com o papel search-api.webSearch.user.
  3. Emita para ela uma chave de API com escopo yc.search-api.executeWORDSTAT_API_KEY.
  4. Verificação: wordstat_frequency com qualquer frase.

Nuances: frequência exata = operadores "!слово !слово" (suportados em topRequests/regions; em dynamics — apenas com period=daily); dados de topRequests — dos últimos 30 dias; count chega como strings (parseado); cotas 10 rps / 100 requisições por hora (429 é repetido, mas para coleta em massa planeje throttling); associations no máximo 20.

Google Search Console (prioridade 1)

Dois caminhos; o recomendado — OAuth: o token herda o acesso da sua conta Google e vê todas as propriedades GSC dela de uma vez (incluindo futuras), sem precisar adicionar usuário em cada propriedade.

Caminho A — OAuth (uma vez):

  1. https://console.cloud.google.com → projeto → APIs & Services → Library → ativar Google Search Console API.
  2. OAuth consent screen: tipo External; inclua você em Test users. (Para refresh-token durar mais de 7 dias — clique em Publish app; o aviso "unverified" na autorização é normal para uso pessoal.)
  3. Credentials → Create credentials → OAuth client ID → Desktop app → pegue o client ID + secret.
  4. No chat: gsc_oauth_start (informe clientId+secret) → abra o link → permita → o navegador redirecionará para localhost:8585, o código será capturado automaticamente → gsc_oauth_finish.
  5. Verificação: gsc_list_sites — mostrará todas as propriedades da conta. Caminho B — conta de serviço (para cron headless): IAM → Service Accounts → chave JSON → gsc_save_sa_json (ou caminho em GSC_SA_JSON) → adicionar o e-mail da conta em cada propriedade necessária do GSC (Configurações → Usuários e permissões, "Total").

Se ambos forem definidos — OAuth tem prioridade.

Google Analytics 4 (prioridade 1)

A autorização é a mesma do GSC, e o aplicativo OAuth é compartilhado (GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET são reutilizados). Mas o escopo do GA4 é próprio, então é necessária uma autorização separada — uma única vez.

  1. No mesmo projeto console.cloud.google.com → APIs & Services → Library → ativar Google Analytics Data API e Google Analytics Admin API.
  2. No chat: ga4_oauth_start (se client ID/secret já estiverem salvos para GSC — sem argumentos) → abrir o link → permitir → o navegador redireciona para localhost:8586 (a porta difere do GSC, para os servidores não conflitarem), o código é capturado automaticamente → ga4_oauth_finish.
  3. Verificação: ga4_list_properties — mostrará todas as propriedades da conta e seus propertyId.
  4. É conveniente salvar a propriedade padrão: ga4_set_credentialsGA4_PROPERTY_ID (id numérico do item 3), caso contrário, passar propertyId em cada chamada.

Caminho B — conta de serviço: chave JSON → ga4_save_sa_json → adicionar o e-mail da conta na propriedade GA4 (Administrador → Gerenciamento de acesso ao recurso, função "Visualização").

Yandex OAuth (Webmaster + Metrica — um aplicativo, um token)

  1. Uma única vez: https://oauth.yandex.ru/client/new → "Serviços web", Redirect URI: https://oauth.yandex.ru/verification_code. Permissões (escopo): Yandex.Webmaster — "Obter informações sobre sites" (webmaster:hostinfo) + "Gerenciar sites" (webmaster:verify); Yandex.Metrica — "Obter estatísticas" (metrika:read). Pegar ClientID e Client secret.
  2. Depois — interativamente no chat: ywm_oauth_start (passar ClientID + secret, serão salvos) → abrir o link na conta proprietária do site/contador → copiar o código → ywm_oauth_finish. Serão obtidos tokens access+refresh, compartilhados entre ywm e metrika; são atualizados automaticamente.
  3. Padrões: YWM_HOST_ID (lista — ywm_hosts), METRIKA_COUNTER_ID (lista — metrika_counters) — definir via *_set_credentials, ou passar em cada chamada.
  4. Alternativa manual: obter token via implicit-flow (response_type=token) e salvar em YANDEX_OAUTH_TOKEN — mas sem refresh ele expira (Webmaster ~6 meses, Metrica ~1 ano).

Limitações da API do Yandex (não são bugs dos servidores): filtro por URL no Webmaster existe apenas em query-analytics (dados ~2 semanas); endpoint de "consultas recomendadas" na API v4 não existe — ywm_recommended_queries aproxima via demanda (DEMAND) + déficit de cliques; frases de busca na Metrica são majoritariamente "Não definido" (criptografia).

A-Parser (self-hosted) — SERP e centenas de parsers através da sua própria instância

  1. Sua própria instância em execução do A-Parser (licença + servidor) — o bridge gerencia, mas não hospeda nem faz proxy.
  2. No A-Parser: Settings → API — ativar o servidor API, anotar a porta (geralmente 9091) e a senha.
  3. APARSER_URL = http://<IP-инстанса>:<порт>/API (obrigatoriamente com o caminho /API), APARSER_PASSWORD = senha do mesmo local → aparser_set_credentials.
  4. Verificação: aparser_ping, depois aparser_status (prontidão da instância + proxies vivos).

Nuances: proxies e verificadores de proxy (lotes) são configurados uma única vez na GUI — sem proxies vivos, Google/Yandex banem rapidamente, então as ferramentas serp/suggest fazem preflight e avisam (use_proxy=false — por sua conta e risco); presets e lotes padrão são definidos via env (APARSER_GOOGLE_PRESET, APARSER_YANDEX_PRESET, APARSER_PROXY_CHECKERS, APARSER_USE_PROXY); v1 é síncrono e somente leitura — fila de tarefas e métodos mutantes da API não estão conectados.

Formato de datas e regiões

Datas — YYYY-MM-DD (MSK). Regiões: nome da lista embutida de regiões frequentes ("Moscou", "spb", "Cazaquistão"…) ou id numérico da região do Yandex (213, 225…) — o id numérico sempre funciona. Várias regiões separadas por vírgula são suportadas apenas pelo servidor wordstat; ferramentas SERP xmlstock_*/xmlriver_* aceitam UMA região. Referência completa de ids — ferramenta wordstat_regions_tree.

Onde e como usar

Os servidores são processos stdio comuns, sem vínculo com a máquina. Quatro cenários:

1. Claude Code, localmente

Registrar via claude mcp add --scope user (bloco "Registro no Claude Code" acima) — disponível em todos os projetos e sessões.

2. Claude Code, outra máquina

git clone https://github.com/antohins/seo-tools-mcp.git && cd seo-tools-mcp
pnpm install && pnpm build
# зарегистрировать серверы (блок «Регистрация в Claude Code» выше)
# ключи: скопировать ~/.config/seo-tools-mcp/.env со старой машины (chmod 600)
# ЛИБО выдать в диалоге через <server>_auth_status → <server>_set_credentials

3. Claude Desktop (local)

Em claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/):

{
  "mcpServers": {
    "xmlstock": { "command": "node", "args": ["/ABS/PATH/seo-tools-mcp/servers/xmlstock/dist/index.js"] },
    "wordstat": { "command": "node", "args": ["/ABS/PATH/seo-tools-mcp/servers/wordstat/dist/index.js"] }
  }
}

As chaves serão capturadas de ~/.config/seo-tools-mcp/.env automaticamente.

4. Remotamente: claude.ai / Claude Code de qualquer lugar

claude.ai (web/mobile) suporta apenas remote MCP (Streamable HTTP via HTTPS público). Nossos servidores stdio são expostos em um VPS através do bridge supergateway:

# на сервере: клонировать/собрать как в сценарии 2, ключи в ~/.config/seo-tools-mcp/.env
npx -y supergateway --stateful --outputTransport streamableHttp --port 8801 \
  --stdio "node /opt/seo-tools-mcp/servers/xmlstock/dist/index.js"   # и так для каждого сервера, порты 8801–8805

Depois nginx: TLS + proxy_pass para 127.0.0.1:880X sob caminho secreto (por exemplo /mcp-<длинный-случайный-токен>/xmlstock/) — supergateway deve escutar apenas em localhost. Conexão:

  • Claude Code: claude mcp add --transport http xmlstock https://host/<секретный-путь>/xmlstock/mcp
  • claude.ai: Settings → Connectors → Add custom connector → mesma URL.

⚠ Caminho secreto — gate mínimo (custom connectors do claude.ai não transmitem cabeçalhos de autorização arbitrários). Atrás do endpoint — todas as chaves dos serviços, portanto: apenas HTTPS, token longo no caminho, access-log separado.

Alternativa para Claude Code sem bridge HTTP — stdio via ssh:

claude mcp add xmlstock --scope user -- ssh root@SERVER node /opt/seo-tools-mcp/servers/xmlstock/dist/index.js

Desenvolvimento

pnpm build        # собрать все воркспейсы
pnpm typecheck    # только типы
pnpm test         # юнит-тесты (vitest, без сети)
pnpm test:live    # лайв-смоук по реальным API (нужны креды в конфиге; free-эндпоинты)
node servers/xmlstock/dist/index.js   # ручной запуск (stdio)

Testes unitários cobrem a lógica pura: mascaramento de segredos, classificação de erros OAuth, paginação da Metrica/GSC (deduplicação, truncated), filtros, parser SERP, regiões. Live-smoke sobe cada servidor e aciona uma ferramenta gratuita (xmlstock_balance, xmlriver_balance, wordstat_frequency, gsc_list_sites, ywm_hosts, metrika_counters, aparser_ping) — verificação de autorização end-to-end.

Código comum (shared/): cliente HTTP com retries em 429/5xx (3 tentativas, backoff exponencial, Retry-After), carregador de env + config persistente, fábrica de ferramentas de auth, Yandex-OAuth com auto-refresh, helpers JSON MCP, contador de consumo de chamadas pagas. XMLStock adicionalmente faz retry dos seus códigos "temporários" no corpo do XML; código 15 ("nada encontrado") é tratado como resultado vazio.

Build dos servidores — tsup: shared/ é embutido no dist/index.js único de cada servidor (dependências de runtime permanecem externas), portanto o pacote npm é autossuficiente.

Publicação no npm (para mantenedores)

Cada servidor é publicado como um pacote separado seo-tools-mcp-<сервер>; shared/ é privado e não vai para o npm (embutido nos servidores). Mantemos as versões de todos os servidores sincronizadas.

npm login
pnpm -r build                 # shared (tsc) → серверы (tsup-бандл)
pnpm -r publish --access public   # публикует 8 серверов; private-пакеты (shared, корень) пропускаются

pnpm publish substitui automaticamente as versões reais no lugar de workspace:* e não permite publicar com árvore de trabalho suja.

Bump de versão — apenas via package.json raiz: edite a versão lá e execute pnpm version:sync, que distribui para todos os 42 locais (package.json e server.json de cada servidor, literal em new McpServer({ version }), manifestos de plugins). pnpm -r exec npm version patch NÃO serve para isso: atualizará apenas os pacotes dos servidores, o restante ficará na versão antiga, e pnpm version:check no CI falhará. Verificar sem gravar — pnpm version:check.

Contribuição

PRs são bem-vindos — veja CONTRIBUTING.md. Histórico de alterações — CHANGELOG.md. Vulnerabilidades — de forma privada via Security Advisories (detalhes — SECURITY.md).

Licença

MIT © antohins