seo-tools-mcp
Cinco servidores MCP de solo lectura para SEO en el mercado de Google/Yandex (RU/CIS): SERP (XMLStock), Yandex Wordstat, Google Search Console, Yandex.Webmaster, Yandex.Metrica.
Documentación
seo-tools-mcp
Русский | English
Ocho universales servidores MCP stdio para SEO: acceso a SERP, Wordstat, Google Search Console, Google Analytics 4, Yandex.Webmaster, Yandex.Metrica y A-Parser autoalojado directamente desde Claude Code (y cualquier cliente MCP). Todas las herramientas son de solo lectura: no publican ni modifican nada en tus cuentas; la salida es JSON estricto. Esto se declara de forma legible por máquina mediante la anotación readOnlyHint; deliberadamente no está presente en veinte herramientas, cada una de cuyas llamadas consume un recurso de pago (solicitud a XMLStock/XMLRiver, tráfico proxy de A-Parser); de lo contrario, el cliente las consideraría inofensivas y dejaría de pedir confirmación antes de ejecutarlas sobre un gran conjunto. No están vinculadas a un sitio específico: los valores predeterminados (propiedad GSC, propiedad GA4, host de Webmaster, contador de Metrica) se configuran sobre la marcha.
🛰 Estos servidores los usamos en producción en PBN Workers — infraestructura para el top de búsqueda: semántica, PBN y satélites, automatización SEO. ¿Necesitas tráfico orgánico estable? Ven.
| Servidor | Herramientas operativas | Autorización |
|---|---|---|
xmlstock | xmlstock_serp, xmlstock_images, xmlstock_news, xmlstock_video, xmlstock_wordstat, xmlstock_wordstat_dynamics, xmlstock_wordstat_regions, xmlstock_wordstat_regions_tree, xmlstock_balance | Clave API |
xmlriver | xmlriver_serp, xmlriver_images, xmlriver_news, xmlriver_maps, xmlriver_check_index, xmlriver_suggest, xmlriver_related_questions, xmlriver_balance | Clave API |
wordstat | wordstat_frequency, wordstat_dynamics, wordstat_regions, wordstat_regions_tree | Api-Key de Yandex Cloud |
gsc | gsc_query, gsc_inspect_url, gsc_list_sites, gsc_get_site, gsc_list_sitemaps, gsc_get_sitemap | OAuth (todas las propiedades de la cuenta) / cuenta de servicio |
ga4 | ga4_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_realtime | OAuth (todas las propiedades de la cuenta) / cuenta de servicio |
ywm | ywm_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_sitemaps | OAuth (auto-refresh) |
metrika | metrika_report, metrika_bytime, metrika_counters, metrika_goals, metrika_traffic_sources, metrika_geo, metrika_devices, metrika_landing_behavior, metrika_search_phrases, metrika_top_landings | OAuth (auto-refresh) |
aparser | aparser_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_request | A-Parser autoalojado (URL + contraseña API) |
Dónde está publicado: npm (ocho paquetes), MCP Registry oficial, GitHub MCP Registry (los ocho servidores), el marketplace de plugins de Claude Code (ver más abajo) y paquetes .mcpb en los lanzamientos.
Cada servidor tiene además herramientas de autenticación <server>_auth_status y <server>_set_credentials (ver Autorización interactiva).
Herramientas por servicios
xmlstock — SERP de Google/Yandex
xmlstock_serp— resultados web de Google/Yandex (orgánicos + destacados + funciones SERP): región, dispositivo, búsqueda segura, ordenación (Yandex), período, bloques publicitarios; el tercer motoryandex_xml— Yandex XML oficial (groupby hasta 100 por 1 solicitud, hlword en cualquier dispositivo, estadísticas found/found-docs; tarifa desde 24 ₽/1000)xmlstock_images— búsqueda de imágenes de Google (url de página + url de imagen + título)xmlstock_news— noticias de Google (título, fuente, fecha, fragmento)xmlstock_video— videos de Google (url, título, vista previa, host, canal, duración)xmlstock_wordstat— Yandex Wordstat: consultas principales + similares con frecuencia (se puede por región), operadores de Wordstatxmlstock_wordstat_dynamics— dinámica de frecuencia por tiempo (día/semana/mes)xmlstock_wordstat_regions— demanda por regiones (count, share, affinity index + nombres de regiones)xmlstock_wordstat_regions_tree— árbol de regiones de Wordstat (id + nombre + ruta)xmlstock_balance— saldo de cuenta / verificación de clave (gratuito)
Wordstat a través de XMLStock — con la misma clave
XMLSTOCK_*que SERP; no se necesita Yandex Cloud (a diferencia del servidor separadowordstat).
xmlriver — SERP de Google/Yandex + verificación de indexación
xmlriver_serp— orgánicos de Google/Yandex (la profundidad se completa con paginación: cada 10 posiciones = 1 solicitud de pago), indicador de presencia de AI Overview; opciónincludeAIOverview— texto completo del Resumen de IA + enlaces citados (de pagoai=1, solo Google);includeAdditional— bloques SERP adicionales de Google desde<addresults>(knowledge_graph, localresultsplace, rs y otros; el contenido depende de las opciones de pago del panel de XMLRiver, los bloques no recibidos están enadditional.unavailable); segmentación geográfica de Google —location(ciudad →loc, «Moscow»/«1011969») ycountry(id ISO/numérico, se deduce automáticamente de la ciudad);device— desktop/mobile/tablet,os(ios/android) se envía solo condevice=mobilexmlriver_images— imágenes de Google (página + url de imagen + título + fuente + dimensiones); geo —location/countryxmlriver_news— noticias de Google (título, fuente, fecha, fragmento), filtro por tiempo; geo —location/countryxmlriver_maps— búsqueda de establecimientos en Google Maps (setab=maps, obligatorioszoom1–15 ycoords«latitud,longitud»,count5–50): nombre, calificación, dirección, teléfono, servicios, coordenadas, place_id, número de reseñas. IMPORTANTE: formato según la documentación, no confirmado en vivo (en la cuenta de prueba el endpoint responde constantemente con código 500 — probablemente se necesita una opción de pago del panel)xmlriver_check_index— verificación de indexación de URL en Google/Yandex (inindex)xmlriver_suggest— sugerencias de búsqueda de Google (hasta 50 frases por llamada, se paga por cada frase); geo de sugerencias —location/countryxmlriver_related_questions— bloque «Preguntas relacionadas» / People Also Ask de Google (preguntas siempre; respuestas — solo con la opción de pago «Related Questions con respuestas» activada en el panel)xmlriver_balance— saldo de cuenta / verificación de clave (gratuito)
wordstat — frecuencias de Yandex
wordstat_frequency— frecuencia amplia y exacta, consultas de refinamiento (related) y asociacioneswordstat_dynamics— frecuencia por tiempo (día/semana/mes)wordstat_regions— distribución por regiones con índice de afinidad y nombres de regioneswordstat_regions_tree— árbol completo de regiones de Wordstat (id + nombre)
gsc — Google Search Console
gsc_query— Search Analytics (clics/impresiones/CTR/posición), paginación automática,dataStatefinal/all, filtros arbitrarios de dimensiones (filters, semántica AND) yaggregationType(auto/byProperty/byPage)gsc_inspect_url— URL Inspection: estado de indexación, cobertura, canonical, último rastreo, usabilidad móvil, rich resultsgsc_list_sites— propiedades disponibles para la autorizacióngsc_get_site— nivel de acceso a la propiedadgsc_list_sitemaps— sitemaps enviados con estadogsc_get_sitemap— detalles de un sitemap
Las fechas de Search Analytics son en Pacific Time (no MSK); historial de ~16 meses; los datos finales se retrasan ~2-3 días (los recientes — dataState=all); ctr en la respuesta — proporción 0..1.
ga4 — Google Analytics 4
ga4_list_properties— propiedades GA4 disponibles para la autorización (de aquí se tomapropertyId— no es el Measurement IDG-XXXXXXX)ga4_metadata— qué dimensiones y métricas están disponibles en ESTA propiedad, incluidas las personalizadas (customEvent:…); búsqueda por subcadena,blockedReasons(con esa métrica el informe devolverá ceros) ytype(entero/decimal parametricFilters)ga4_check_compatibility— si la combinación de dimensiones/métricas es compatible en esta propiedad, sin informe pesado; si no es compatible — qué campos quitarga4_report— informe arbitrario: cualquier dimensión × métrica, filtros por dimensiones, ordenación (Data API completorunReport)ga4_bytime— dinámica de métricas por tiempo (día/hora/semana/mes)ga4_traffic_sources— fuentes de tráfico: grupo de canales, source/medium, campaña;organicOnly— solo orgánicoga4_geo— país/región/ciudadga4_devices— tipo de dispositivo/SO/navegadorga4_top_pages— top de páginas porpagePath, página de entrada o título; filtrosorganicOnlyypathContainsga4_events— eventos poreventName;keyEventsOnly— solo eventos clave (antes conversiones)ga4_realtime— informe en tiempo real (últimos 30 minutos)ga4_funnel— embudo (runFunnelReport): cuántos llegaron a cada paso y dónde se perdieron; paso = evento y/o condiciones por dimensiones, desglose por dimensión. Dentro de los pasos funciona el esquema de Exploration API (pagePathno está disponible allí), la cuota es separada y la solicitud es más costosa que un informe normalga4_annotations— anotaciones de la propiedad: marcas en fechas, incluidas las creadas por la propia GA4 (systemGenerated) — explicación frecuente de un salto inexplicable en la dinámicaga4_property_details— tarjeta de la propiedad: zona horaria de informes, moneda, nivel de servicio (STANDARD/360) y flujos de datos con su Measurement IDG-XXXXXXX
En todas las herramientas de informes hay includeQuota — cuántos «tokens» consumió la solicitud del Data API y cuántos quedan por hora/día.
Unidades y fechas: bounceRate/engagementRate GA4 las devuelve como proporción 0..1 (no porcentajes); las fechas se calculan en la zona horaria de la propiedad — se aceptan YYYY-MM-DD y palabras clave de GA4 (today, yesterday, 28daysAgo), la zona horaria real se devuelve en la respuesta. En las respuestas hay totalRows/truncated, y thresholded: true significa que parte de los datos está oculta por el umbral de confidencialidad de GA4.
ywm — Yandex.Webmaster
ywm_hosts— id de usuario + sitios confirmadosywm_summary— IKS, páginas en búsqueda, excluidas, problemas del sitio por importanciaywm_search_queries— análisis de consultas por URL (~2 semanas por defecto; se redefine con dateFrom/dateTo)ywm_queries_history— impresiones/clics/posiciones totales por tiempoywm_recommended_queries— consultas recomendadas aproximadas (demanda + falta de clics)ywm_popular— consultas populares del hostywm_indexing_history— páginas en búsqueda por tiempoywm_sqi_history— IKS por tiempoywm_external_links— selección de enlaces externos + número totalywm_broken_links— enlaces internos/externos rotosywm_diagnostics— problemas del sitioywm_important_urls— URLs rastreadas con estado de indexación/búsquedaywm_sitemaps— sitemap con estado
metrika — Yandex.Metrica
metrika_report— informe arbitrario: cualquier dimensiones × métricas, filtros, ordenación (Stat API completo)metrika_bytime— métricas por tiempo (día/semana/mes/hora)metrika_traffic_sources— visitas/usuarios/rebotes por fuentes de tráficometrika_geo— visitas por país/región/ciudadmetrika_devices— visitas por dispositivo/SO/navegadormetrika_goals— lista de objetivos (conversiones)metrika_counters— contadores disponiblesmetrika_landing_behavior— comportamiento en páginas de destino + logros de objetivosmetrika_search_phrases— frases de búsqueda (orgánico)metrika_top_landings— top de páginas de destino orgánicas
aparser — puente hacia A-Parser self-hosted
aparser_ping— verificación de conexión con la instancia y la contraseña de la APIaparser_status— veredicto de disponibilidad: versión, parsers instalados, cola, proxies vivosaparser_proxies— proxies vivos de la instancia (se pueden usar en lotes de proxy checkers; las credenciales de los proxies no se muestran)aparser_parsers— parsers instalados en la instanciaaparser_parser_fields— campos de resultado que el parser puede devolver (flat + arrays)aparser_get_preset— opciones del preset de configuración del parser (los valores sensibles se enmascaran)aparser_serp_google— orgánicos de Google (parserSE::Google); proxy por defecto + preflight de proxies vivosaparser_serp_yandex— orgánicos de Yandex (SE::Yandex); región mediantelraparser_suggest— sugerencias de búsqueda de Google/Yandexaparser_request— solicitud síncrona universal a cualquier parser (oneRequest)aparser_bulk_request— solicitud por lotes: un parser, muchas solicitudes en N hilos (bulkRequest)
Se necesita una instancia propia en ejecución de A-Parser (licencia + servidor): el puente la gestiona, pero no la aloja ni la proxifica. Los proxies y los proxy checkers (lotes) se configuran una vez en la GUI de A-Parser — el puente los lee, verifica (preflight) y selecciona (
checkers), pero no los crea. v1 es síncrono y de solo lectura: la cola de tareas y las grandes exportaciones asíncronas no están conectadas.
Inicio rápido
Opción 1 — con un clic para Claude Desktop (.mcpb)
La forma más sencilla, no necesitas instalar nada manualmente: descarga el .mcpb que necesites desde la página de lanzamiento y ábrelo con doble clic — Claude Desktop instalará el servidor por sí mismo y te pedirá las claves en el diálogo de instalación.
- Servidores con clave API (
xmlstock,xmlriver,wordstat,aparser) — las claves se introducen directamente en el instalador. - Servidores con OAuth (
gsc,ga4,ywm,metrika) no preguntan nada: la autorización se realiza en el chat (<server>_oauth_start→<server>_oauth_finish).
Los bundles son autónomos (~0.2 MB, dependencias incluidas); Node.js 20+ solo se necesita para la opción con npx. Para compilarlo tú mismo: pnpm build:mcpb.
Opción 2 — plugin para Claude Code (marketplace)
Análogo a .mcpb, pero para Claude Code: el servidor, las claves y las sugerencias se instalan con un solo comando, las claves se solicitan mediante un diálogo y los secretos van al almacenamiento del sistema, no a un archivo abierto.
claude plugin marketplace add antohins/seo-tools-mcp
A continuación — solo las fuentes que necesites; cada plugin trae exactamente un servidor:
claude plugin install xmlstock@seo-tools-mcp
claude plugin install gsc@seo-tools-mcp
claude plugin install ga4@seo-tools-mcp
Están disponibles xmlstock, xmlriver, wordstat, gsc, ga4, ywm, metrika, aparser — y seo-tools, que instala los ocho a la vez. El bundle es cómodo, pero son ~100 herramientas en cada sesión: si solo trabajas con Webmaster y Metrica, instala dos plugins, no el bundle.
Las claves se pueden introducir de inmediato (--config KEY=VALUE) o más tarde mediante /plugin configure <плагин>@seo-tools-mcp:
claude plugin install xmlstock@seo-tools-mcp --config XMLSTOCK_USER=12345 --config XMLSTOCK_KEY=...
Los campos marcados como secretos (claves API, secretos OAuth) los guarda Claude Code en el almacenamiento del sistema; no aparecen en settings.json. Los plugins con OAuth (gsc, ga4, ywm, metrika) al instalarse solo piden client_id/secret — el inicio de sesión se realiza en el chat mediante <сервер>_oauth_start → <сервер>_oauth_finish.
Junto con el servidor, el plugin trae habilidades — instrucciones procedimentales sobre su fuente:
cómo no quemar el saldo al extraer posiciones, por qué freq_broad infla el tráfico varias veces, por qué
GA4 devuelve ceros en silencio, en qué se diferencia la posición promedio de GSC de la extraída de los resultados. En el contexto
siempre ocupan ~110 tokens por habilidad y se despliegan solo cuando realmente se necesitan.
Opción 3 — mediante npx (sin clonar)
Cada servidor es un paquete npm autónomo seo-tools-mcp-<сервер>; se instala con un solo 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
¿Solo necesitas un servidor?
Los servidores no están vinculados entre sí: toma un solo paquete e ignora el resto. Cada uno es autónomo — el código común @seo-tools/shared está integrado en la compilación, así que no se arrastran dependencias adicionales ni la "cola" del monorepo. Basta con instalar el paquete necesario desde npm — ya viene todo listo para usar (npx -y lo descargará y ejecutará por sí mismo):
| Paquete (npm) | Servidor |
|---|---|
seo-tools-mcp-xmlstock | SERP Google/Yandex + Wordstat |
seo-tools-mcp-xmlriver | SERP Google/Yandex + verificación de indexación |
seo-tools-mcp-wordstat | frecuencias de Yandex (Yandex Cloud) |
seo-tools-mcp-gsc | Google Search Console |
seo-tools-mcp-ga4 | Google Analytics 4 |
seo-tools-mcp-ywm | Yandex.Webmaster |
seo-tools-mcp-metrika | Yandex.Metrica |
seo-tools-mcp-aparser | puente hacia 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
En cualquier cliente MCP (Claude Desktop, Cursor…) — se escribe un bloque en mcpServers:
{
"mcpServers": {
"xmlstock": {
"command": "npx",
"args": ["-y", "seo-tools-mcp-xmlstock"],
"env": { "XMLSTOCK_USER": "...", "XMLSTOCK_KEY": "..." }
}
}
}
La instalación directa de un solo paquete mediante enlace de GitHub (
npm i github:antohins/seo-tools-mcp) no es compatible: es un monorepo pnpm, un subpaquete separado no se instala así. Para instalar desde el código fuente — opción B a continuación (clonar + compilar). Los paquetes listos viven en npm.
Opción 4 — desde el código fuente
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
A continuación (cualquier opción) — directamente en el diálogo de Claude Code: «configura el acceso a xmlstock» → el agente llamará a xmlstock_auth_status, te indicará qué claves se necesitan y dónde obtenerlas, las aceptará mediante xmlstock_set_credentials y las guardará. Después pregunta los datos en lenguaje natural: «extrae el top-10 de Yandex para la consulta X», «frecuencia de frases …», «clics/impresiones de GSC del último mes». Las claves y OAuth se configuran una sola vez (ver Obtención de accesos).
Autorización interactiva (en cualquier sesión)
Cada servidor tiene herramientas de autenticación — las claves se pueden proporcionar directamente en el diálogo, sin editar archivos ni reiniciar:
<server>_auth_status— se llama al inicio del trabajo: muestra qué claves están definidas (enmascaradas), cuáles faltan y cómo obtenerlas (pasos de registro).<server>_set_credentials— guarda los valores proporcionados en~/.config/seo-tools-mcp/.env(permisos 600) y los aplica de inmediato.gsc_save_sa_json— acepta el contenido del archivo JSON de la clave de cuenta de servicio, lo coloca en el directorio de configuración y devuelve el email que se debe añadir a GSC.ywm_oauth_start/metrika_oauth_start→ enlace de autorización de Yandex; el usuario abre, permite, copia el código →*_oauth_finishintercambia el código por tokens access+refresh. Después el token se renueva automáticamente al caducar (code flow, no implicit).
Escenario típico de una nueva sesión: «configura el acceso a xmlstock» → el agente llama a xmlstock_auth_status → solicita las claves que faltan → xmlstock_set_credentials → trabaja.
⚠ Las claves proporcionadas a través del chat pasan por el contexto del modelo. Para una higiene máxima, todavía puedes escribirlas manualmente en ~/.config/seo-tools-mcp/.env — los servidores detectarán el archivo por sí mismos.
Multi-cuenta
Los sitios de los clientes están repartidos en diferentes cuentas de Google/Yandex — se admiten perfiles con nombre:
- Cada herramienta de trabajo acepta un parámetro opcional
account(«clientX», «agency»...). Sin él, se usa el perfil principal — compatibilidad total hacia atrás. - Las claves del perfil se almacenan en la misma configuración con un sufijo:
GSC_REFRESH_TOKEN__clientX,YANDEX_OAUTH_TOKEN__clientX,XMLSTOCK_KEY__clientX… - Añadir un perfil:
gsc_oauth_start(account="clientX")→ el usuario se autoriza con una cuenta de Google diferente →gsc_oauth_finish(account="clientX"). De forma similar,ywm_oauth_start/finish(account=...)para Yandex; claves API —<server>_set_credentials(account="clientX", ...). - Las aplicaciones OAuth son compartidas: un cliente de Google y una aplicación de Yandex atienden todos los perfiles (el cliente se crea una vez, las autorizaciones — las que sean). Por cuenta solo se almacenan tokens; el refresh renueva el token de su propio perfil.
- La resolución es estricta:
account="clientX"sin claves configuradas → error con la lista de perfiles configurados (sin fallbacks silenciosos a otra cuenta). Los valores por defecto (GSC_SITE_URL__clientX,YWM_HOST_ID__clientX,METRIKA_COUNTER_ID__clientX) también son por cuenta. <server>_auth_statusmuestra todos los perfiles y sus claves (enmascaradas).- Alternativa para aislamiento estricto: un archivo env separado mediante
SEO_TOOLS_MCP_ENV(si se especifica la ruta, la configuración local NO se lee).
Instalación
cd seo-tools-mcp
pnpm install
pnpm build
Secretos
Un único archivo env: ~/.config/seo-tools-mcp/.env (permisos 600). Todos los servidores lo leen al iniciar, y *_set_credentials/*_oauth_finish escriben en él por sí mismos — la edición manual no es obligatoria. Plantilla — .env.example. Las variables del entorno del proceso tienen prioridad sobre el archivo. Ruta alternativa al archivo — SEO_TOOLS_MCP_ENV (así un host puede tener varios perfiles independientes: diferentes claude mcp add con diferente SEO_TOOLS_MCP_ENV).
Registro en 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 — disponible en todas las sesiones/proyectos. Para compartir con el equipo — --scope project (creará .mcp.json en el repositorio; los secretos solo se sustituyen mediante ${VAR}).
Obtención de accesos (por servicio)
Todo lo de esta sección está duplicado en las respuestas de
<server>_auth_status— el agente te indicará los pasos por sí mismo. A continuación — para lectura humana.
XMLStock (prioridad 1) — SERP Google + Yandex
- Registro: https://xmlstock.com → panel personal, recargar saldo (Google XML y Yandex Live — desde 12 ₽/1000 solicitudes).
- Obtener el ID de usuario y la clave API →
XMLSTOCK_USER,XMLSTOCK_KEY(o mediantexmlstock_set_credentials). - Verificación:
xmlstock_balance.
Matices (descubiertos en respuestas reales):
- resaltados de resultados (
text_bolds) — parámetrohlword=1, etiqueta<hlword>en XML anidado (se analiza mediante stopNodes, las palabras adyacentes se unen en frases); PAA y related searches —related=1(PAA solo en Google); - la salida móvil no devuelve hlword/PAA/related — la instantánea móvil solo tiene posiciones+snippets, los resaltados se extraen de desktop;
- páginas con 0 en ambos motores; orgánicos en una página pueden ser <10 — el servidor completa con una página adicional (+1 solicitud de pago);
lracepta IDs de regiones de Yandex para ambos motores (XMLStock los mapea a Google por sí mismo);- errores HTTP 200 +
<error code>: 20–25/101/110/111/500 se reintentan, 55 — rate-limit con pausa, 15 = salida vacía (dinero descontado), 31/42 — fatales (autorización); - Wordstat NO está en XMLStock — las frecuencias se obtienen mediante un servidor separado (API oficial de Wordstat de Yandex).
Wordstat (prioridad 1) — frecuencias de Yandex
API oficial Wordstat API v2 (parte de Yandex Cloud Search API) — gratuita, sin solicitudes ni OAuth. Una vez en https://console.yandex.cloud:
- Crear un catálogo (folder) o usar uno existente → su ID en
WORDSTAT_FOLDER_ID. - Crear una cuenta de servicio con el rol
search-api.webSearch.user. - Emitir para ella una clave API con el ámbito
yc.search-api.execute→WORDSTAT_API_KEY. - Verificación:
wordstat_frequencycon cualquier frase.
Matices: frecuencia exacta = operadores "!слово !слово" (compatibles en topRequests/regions; en dynamics — solo con period=daily); los datos de topRequests — de los últimos 30 días; count llega como cadenas (se analiza); cuotas 10 rps / 100 solicitudes por hora (429 se reintenta, pero para extracción masiva hay que prever throttling); associations máximo 20.
Google Search Console (prioridad 1)
Dos vías; la recomendada — OAuth: el token hereda el acceso de tu cuenta de Google y ve todas sus propiedades de GSC a la vez (incluidas las futuras), no es necesario añadir al usuario en cada propiedad.
Vía A — OAuth (una vez):
- https://console.cloud.google.com → proyecto → APIs & Services → Library → activar Google Search Console API.
- OAuth consent screen: tipo External; a ti mismo en Test users. (Para un refresh-token de más de 7 días — pulsar Publish app; la advertencia «unverified» al autorizar es normal para uso personal.)
- Credentials → Create credentials → OAuth client ID → Desktop app → tomar client ID + secret.
- En el chat:
gsc_oauth_start(proporcionar clientId+secret) → abrir el enlace → permitir → el navegador redirigirá alocalhost:8585, el código se capturará automáticamente →gsc_oauth_finish. - Verificación:
gsc_list_sites— mostrará todas las propiedades de la cuenta. Ruta B — cuenta de servicio (para cron jobs headless): IAM → Service Accounts → clave JSON →gsc_save_sa_json(o ruta enGSC_SA_JSON) → añadir el email de la cuenta a cada propiedad de GSC necesaria (Configuración → Usuarios y permisos, «Pleno»).
Si se especifican ambos, OAuth tiene prioridad.
Google Analytics 4 (prioridad 1)
La autorización es la misma que para GSC, y la aplicación OAuth es compartida (GOOGLE_CLIENT_ID/GOOGLE_CLIENT_SECRET se reutilizan). Pero el scope de GA4 es propio, por lo que se necesita una autorización separada — una sola vez.
- En el mismo proyecto console.cloud.google.com → APIs & Services → Library → habilitar Google Analytics Data API y Google Analytics Admin API.
- En el chat:
ga4_oauth_start(si el client ID/secret ya están guardados para GSC — sin argumentos) → abrir el enlace → permitir → el navegador redirigirá alocalhost:8586(el puerto difiere del de GSC para que los servidores no entren en conflicto), el código se capturará automáticamente →ga4_oauth_finish. - Verificación:
ga4_list_properties— mostrará todas las propiedades de la cuenta y suspropertyId. - Es conveniente guardar la propiedad predeterminada:
ga4_set_credentials→GA4_PROPERTY_ID(id numérico del punto 3), de lo contrario pasarpropertyIden cada llamada.
Ruta B — cuenta de servicio: clave JSON → ga4_save_sa_json → añadir el email de la cuenta a la propiedad de GA4 (Administrador → Gestión de acceso al recurso, rol «Lector»).
Yandex OAuth (Webmaster + Metrika — una aplicación, un token)
- Una sola vez: https://oauth.yandex.ru/client/new → «Servicios web», Redirect URI:
https://oauth.yandex.ru/verification_code. Permisos (scope): Yandex.Webmaster — «Obtener información sobre sitios» (webmaster:hostinfo) + «Gestionar sitios» (webmaster:verify); Yandex.Metrika — «Obtener estadísticas» (metrika:read). Obtener ClientID y Client secret. - Luego, de forma interactiva en el chat:
ywm_oauth_start(pasar ClientID + secret, se guardarán) → abrir el enlace con la cuenta propietaria del sitio/contador → copiar el código →ywm_oauth_finish. Se obtendrán tokens access+refresh, comunes para ywm y metrika; se renuevan automáticamente. - Valores predeterminados:
YWM_HOST_ID(lista —ywm_hosts),METRIKA_COUNTER_ID(lista —metrika_counters) — configurar mediante*_set_credentials, o pasar en cada llamada. - Alternativa manual: obtener token mediante implicit-flow (
response_type=token) y guardarlo enYANDEX_OAUTH_TOKEN— pero sin refresh caducará (Webmaster ~6 meses, Metrika ~1 año).
Limitaciones de la API de Yandex (no son errores de los servidores): el filtro por URL en Webmaster solo existe en query-analytics (datos ~2 semanas); no hay endpoint de «consultas recomendadas» en la API v4 — ywm_recommended_queries lo aproxima mediante demanda (DEMAND) + déficit de clics; las frases de búsqueda en Metrika son mayormente «No definido» (cifrado).
A-Parser (self-hosted) — SERP y cientos de parsers desde tu propio servidor
- Tu propia instancia de A-Parser en ejecución (licencia + servidor) — el puente la gestiona, pero no la aloja ni la proxifica.
- En A-Parser: Settings → API — habilitar el servidor API, anotar el puerto (normalmente 9091) y la contraseña.
APARSER_URL=http://<IP-инстанса>:<порт>/API(obligatorio con la ruta/API),APARSER_PASSWORD= contraseña de ahí →aparser_set_credentials.- Verificación:
aparser_ping, luegoaparser_status(disponibilidad de la instancia + proxies vivos).
Matices: los proxies y los comprobadores de proxies (lotes) se configuran una vez en la GUI — sin proxies vivos, Google/Yandex bloquean rápidamente, por lo que las herramientas serp/suggest hacen preflight y avisan (use_proxy=false — bajo tu propio riesgo); los presets y lotes predeterminados se definen mediante env (APARSER_GOOGLE_PRESET, APARSER_YANDEX_PRESET, APARSER_PROXY_CHECKERS, APARSER_USE_PROXY); v1 es síncrono y de solo lectura — la cola de tareas y los métodos mutantes de la API no están conectados.
Formato de fechas y regiones
Fechas — YYYY-MM-DD (MSK). Regiones: nombre de la lista integrada de regiones frecuentes («Moscú», «spb», «Kazajistán»…) o id numérico de región de Yandex (213, 225…) — el id numérico siempre funciona. Varias regiones separadas por comas solo las admite el servidor wordstat; las herramientas SERP xmlstock_*/xmlriver_* aceptan UNA región. Referencia completa de ids — herramienta wordstat_regions_tree.
Dónde y cómo usar
Los servidores son procesos stdio normales sin vinculación a una máquina. Cuatro escenarios:
1. Claude Code, local
Registrar mediante claude mcp add --scope user (bloque «Registro en Claude Code» arriba) — disponible en todos los proyectos y sesiones.
2. Claude Code, otra 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)
En 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"] }
}
}
Las claves se tomarán de ~/.config/seo-tools-mcp/.env automáticamente.
4. Remoto: claude.ai / Claude Code desde cualquier lugar
claude.ai (web/mobile) solo admite remote MCP (Streamable HTTP sobre HTTPS público). Nuestros servidores stdio se trasladan a un VPS mediante el puente 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
Luego nginx: TLS + proxy_pass a 127.0.0.1:880X bajo ruta secreta (por ejemplo /mcp-<длинный-случайный-токен>/xmlstock/) — supergateway debe escuchar solo en localhost. Conexión:
- Claude Code:
claude mcp add --transport http xmlstock https://host/<секретный-путь>/xmlstock/mcp - claude.ai: Settings → Connectors → Add custom connector → la misma URL.
⚠ La ruta secreta es una puerta mínima (los custom connectors de claude.ai no transmiten cabeceras de autorización arbitrarias). Detrás del endpoint están todas las claves de servicios, por lo tanto: solo HTTPS, token largo en la ruta, access-log separado.
Alternativa para Claude Code sin puente HTTP — stdio mediante ssh:
claude mcp add xmlstock --scope user -- ssh root@SERVER node /opt/seo-tools-mcp/servers/xmlstock/dist/index.js
Desarrollo
pnpm build # собрать все воркспейсы
pnpm typecheck # только типы
pnpm test # юнит-тесты (vitest, без сети)
pnpm test:live # лайв-смоук по реальным API (нужны креды в конфиге; free-эндпоинты)
node servers/xmlstock/dist/index.js # ручной запуск (stdio)
Las pruebas unitarias cubren la lógica pura: enmascaramiento de secretos, clasificación de errores OAuth, paginación de Metrika/GSC (deduplicación, truncated), filtros, parser SERP, regiones. El smoke test en vivo levanta cada servidor y ejecuta una herramienta gratuita (xmlstock_balance, xmlriver_balance, wordstat_frequency, gsc_list_sites, ywm_hosts, metrika_counters, aparser_ping) — verificación de autorización de extremo a extremo.
Código común (shared/): cliente HTTP con reintentos en 429/5xx (3 intentos, backoff exponencial, Retry-After), cargador de env + configuración persistente, fábrica de herramientas de autenticación, OAuth de Yandex con auto-refresh, helpers JSON de MCP, contador de consumo de llamadas de pago. XMLStock además reintenta sus códigos «temporales» del cuerpo XML; el código 15 («nada encontrado») se trata como resultado vacío.
Compilación de servidores — tsup: shared/ se incrusta en el dist/index.js único de cada servidor (las dependencias de runtime permanecen externas), por lo que el paquete npm es autosuficiente.
Publicación en npm (para mantenedores)
Cada servidor se publica como paquete separado seo-tools-mcp-<сервер>; shared/ es privado y no se sube a npm (incrustado en los servidores). Mantenemos las versiones de todos los servidores sincronizadas.
npm login
pnpm -r build # shared (tsc) → серверы (tsup-бандл)
pnpm -r publish --access public # публикует 8 серверов; private-пакеты (shared, корень) пропускаются
pnpm publish sustituye automáticamente las versiones reales en lugar de workspace:* y no permitirá publicar si el árbol de trabajo está sucio.
El bump de versión — solo mediante el package.json raíz: editas la versión allí y ejecutas pnpm version:sync, que la distribuye a los 42 lugares (package.json y server.json de cada servidor, literal en new McpServer({ version }), manifiestos de plugins). pnpm -r exec npm version patch NO sirve para esto: actualizará solo los paquetes de servidores, el resto quedará en la versión anterior, y pnpm version:check en CI fallará. Para verificar sin escribir — pnpm version:check.
Contribuciones
Los PR son bienvenidos — ver CONTRIBUTING.md. Historial de cambios — CHANGELOG.md. Vulnerabilidades — de forma privada mediante Security Advisories (detalles — SECURITY.md).
Licencia
MIT © antohins