google-measurement-mcp
MCP seguro ante todo para GA4, Search Console y Tag Manager.
Documentación
google-measurement-mcp
El stack de medición de Google para agentes de IA: GA4, Search Console y Tag Manager en un solo servidor MCP.
Las herramientas de lectura están siempre activas. Las herramientas de escritura están desactivadas a menos que las habilites explícitamente. Las operaciones destructivas no están implementadas en absoluto.
Estado: Temprano — v0.1.0. Hay 15 herramientas de lectura y 9 herramientas de escritura opcionales disponibles en GA4, Search Console y Tag Manager. Consulta Roadmap.
Por qué existe esto
Apuntar un agente de IA a tus análisis es de bajo riesgo. Apuntarlo a tu contenedor de Tag Manager en vivo no lo es: una publicación defectuosa rompe el seguimiento en todas las páginas de tu sitio.
La mayoría de los servidores MCP de GTM pueden publicar contenedores. Este hace que eso sea difícil a propósito:
- Las herramientas de escritura están ausentes a menos que pases
--enable-write. No es que estén presentes y den error — genuinamente no están en la lista de herramientas, por lo que un agente no puede verlas ni intentarlas. - Las operaciones destructivas no existen en el código base. Sin eliminación, sin archivo, sin remoción de etiquetas, disparadores, variables, mapas del sitio o eventos clave. Esta es una decisión de diseño deliberada, no una brecha.
- La publicación requiere confirmación humana.
gtm_publish_versionsinconfirm: truedevuelve un diff de lo que se publicaría y se niega a publicar.
¿Deberías usar esto o el servidor oficial de Google?
Si solo necesitas GA4, y solo lecturas — usa el de Google. Está mantenido por Google, tiene una comunidad mucho más grande y tiene funciones de GA4 que este servidor no tiene.
| google-measurement-mcp | analytics-mcp de Google | |
|---|---|---|
| APIs | GA4 + Search Console + Tag Manager | Solo GA4 |
| Escrituras | Sí, detrás de una bandera explícita | No — solo lectura |
| Informes de embudo | ❌ no implementado | ✅ run_funnel_report |
| Enlaces de Google Ads | ❌ no implementado | ✅ list_google_ads_links |
| Detalles de propiedad | Parcial (vía resúmenes de cuenta) | ✅ get_property_details |
| Runtime | Node ≥ 20, npm | Python 3.10+, PyPI |
| Autenticación | OAuth, cuenta de servicio o ADC | ADC |
| Mantenedor | Comunidad (una persona) | |
| Estado | Temprano — v0.1.0 | Experimental |
| Licencia | Apache-2.0 | Apache-2.0 |
Donde el de Google es genuinamente mejor: flujos de trabajo solo GA4, análisis de embudos, atribución de Google Ads y el simple hecho de que está mantenido por el equipo que posee la API. Si tu pregunta es "qué pasó en mi propiedad de GA4", usa el de ellos primero.
Donde este se gana su lugar: necesitas Search Console y Tag Manager junto con GA4 sin ejecutar tres servidores, o necesitas acceso de escritura y quieres que las operaciones peligrosas sean difíciles de alcanzar por accidente. Ejecutar ambos lado a lado es totalmente razonable — no entran en conflicto.
Inicio rápido (alrededor de 5 minutos)
1. Crea un proyecto de Google Cloud y habilita las APIs
En la consola de Google Cloud, crea un proyecto y luego habilita:
- Google Analytics Data API
- Google Analytics Admin API
- Google Search Console API
- Tag Manager API
2. Configura la pantalla de consentimiento
APIs y servicios → Pantalla de consentimiento de OAuth. Google ha migrado esto a Google Auth Platform, donde la configuración está dividida en páginas de la barra lateral izquierda — Branding, Audience, Clients, Data Access. Establece el tipo de usuario Externo y tu correo electrónico como ambos contactos.
No nombres la aplicación
google-measurement-mcp. Google rechaza cualquier nombre de aplicación OAuth que contenga "Google" con un mensaje que no explica por qué: "La solicitud falló porque el nombre de la aplicación no cumple con los requisitos de Google."Nómbrala
Measurement MCPen su lugar. Es solo la etiqueta en tu propia pantalla de consentimiento y no tiene nada que ver con el nombre del paquete.
3. ⚠️ Publica la aplicación — no te saltes esto
Google Auth Platform → Audience → Publicar aplicación. (UI anterior: Pantalla de consentimiento de OAuth → Estado de publicación.)
Si dejas el estado como Prueba, Google expira tu inicio de sesión después de 7 días y tendrás que iniciar sesión nuevamente cada semana.
Publicar no es verificación de Google. Tú eres el único usuario de tu propio cliente OAuth, por lo que no hay revisión, ni auditoría de seguridad, ni espera. Verás una pantalla única de "Google no ha verificado esta aplicación" — eso es esperado. Haz clic en Avanzado → Ir a (no seguro). Es tu propia aplicación.
4. Crea un cliente OAuth
Google Auth Platform → Clientes → Crear cliente OAuth → Tipo de aplicación: Aplicación de escritorio. (UI anterior: APIs y servicios → Credenciales → Crear credenciales → ID de cliente OAuth.)
Anota el ID y el secreto del cliente. Aplicación de escritorio importa — un cliente de "Aplicación web" falla con redirect_uri_mismatch.
5. Configura tu cliente MCP
Claude Code
claude mcp add google-measurement \
--scope user \
-e GMCP_OAUTH_CLIENT_ID=your-client-id.apps.googleusercontent.com \
-e GMCP_OAUTH_CLIENT_SECRET=your-client-secret \
-- npx -y google-measurement-mcp
Agrega --enable-write después del nombre del paquete para exponer las herramientas de escritura.
Cursor — ~/.cursor/mcp.json
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": {
"GMCP_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
"GMCP_OAUTH_CLIENT_SECRET": "your-client-secret"
}
}
}
}
Recarga los servidores MCP después de editar, o la lista de herramientas anterior permanece en caché.
Claude Desktop — claude_desktop_config.json
Misma forma que Cursor. macOS: ~/Library/Application Support/Claude/claude_desktop_config.json. Windows: %APPDATA%\Claude\claude_desktop_config.json.
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": {
"GMCP_OAUTH_CLIENT_ID": "your-client-id.apps.googleusercontent.com",
"GMCP_OAUTH_CLIENT_SECRET": "your-client-secret"
}
}
}
}
Conectores personalizados de claude.ai
Actualmente no compatible. Los conectores de claude.ai requieren un servidor MCP remoto sobre HTTP; este es un servidor local stdio por diseño, lo que mantiene tus credenciales de Google en tu propia máquina en lugar de en la de otra persona.
6. Inicia sesión una vez
Ejecuta el servidor una vez en una terminal. Imprime una URL — ábrela, aprueba, listo. El token de actualización se guarda en caché en ~/.config/google-measurement-mcp/ con permisos solo para el propietario, y tu cliente MCP lo recoge a partir de entonces.
GMCP_OAUTH_CLIENT_ID=... GMCP_OAUTH_CLIENT_SECRET=... npx -y google-measurement-mcp
No se necesitan concesiones de permisos en GA4, Search Console o Tag Manager. OAuth usa el acceso que tu cuenta de Google ya tiene.
Habilitando herramientas de escritura
Las herramientas de escritura están ocultas por defecto. Para exponerlas:
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp", "--enable-write"],
"env": { "GMCP_ENABLE_WRITE": "1" }
}
}
}
Ya sea la bandera o la variable de entorno es suficiente. Al inicio, el servidor escribe una línea en stderr nombrando cada herramienta de escritura que expuso.
El modo de escritura solicita ámbitos OAuth adicionales, por lo que debes iniciar sesión nuevamente después de habilitarlo.
Configuración alternativa: cuenta de servicio (agencias y CI)
Úsala cuando necesites operación sin cabeza, trabajos programados o una identidad en muchas propiedades de clientes. Es más trabajo — requiere otorgar acceso en tres UIs de productos separadas.
Configuración de cuenta de servicio (8 pasos)
- Crea una cuenta de servicio en tu proyecto de Google Cloud.
- Crea y descarga una clave JSON.
- GA4 → Admin → Gestión de acceso a la propiedad → agrega el correo de la cuenta de servicio como Viewer (lectura) o Editor (escritura).
- Search Console → Configuración → Usuarios y permisos → agrega el correo como Full o Owner.
- Tag Manager → Admin → Gestión de usuarios → agrega el correo con permiso Publish en el contenedor.
- Establece
GOOGLE_APPLICATION_CREDENTIALSa la ruta de la clave JSON.
{
"mcpServers": {
"google-measurement": {
"command": "npx",
"args": ["-y", "google-measurement-mcp"],
"env": { "GOOGLE_APPLICATION_CREDENTIALS": "/absolute/path/to/key.json" }
}
}
}
Nota: muchas organizaciones bloquean la creación de claves de cuenta de servicio mediante la política de organización constraints/iam.disableServiceAccountKeyCreation. Si la creación de claves falla, usa OAuth en su lugar.
Tercera opción: ADC de gcloud
Si ya tienes la CLI de gcloud:
gcloud auth application-default login \
--scopes=https://www.googleapis.com/auth/analytics.readonly,\
https://www.googleapis.com/auth/webmasters.readonly,\
https://www.googleapis.com/auth/tagmanager.readonly
No se necesita configuración adicional — el servidor recoge ADC automáticamente.
No probado para ámbitos de escritura. Google restringe qué ámbitos puede solicitar el cliente integrado de gcloud. Si el modo de escritura falla bajo ADC, usa OAuth o una cuenta de servicio.
Orden de resolución de credenciales
GOOGLE_APPLICATION_CREDENTIALS— cuenta de servicio, si está establecida- Token OAuth de usuario en caché
- Credenciales predeterminadas de la aplicación
La línea de inicio en stderr te dice cuál se resolvió.
Configuración
| Variable | Predeterminado | Propósito |
|---|---|---|
GMCP_OAUTH_CLIENT_ID | — | ID de cliente OAuth de escritorio |
GMCP_OAUTH_CLIENT_SECRET | — | Secreto de cliente OAuth de escritorio |
GMCP_OAUTH_CLIENT_JSON | — | Ruta a un JSON de cliente OAuth descargado, en lugar de los dos anteriores |
GOOGLE_APPLICATION_CREDENTIALS | — | Ruta de clave JSON de cuenta de servicio |
GMCP_ENABLE_WRITE | sin establecer | 1 habilita herramientas de escritura (igual que --enable-write) |
GMCP_DEFAULT_ROW_LIMIT | 25 | Límite de filas predeterminado en cada herramienta de informes |
GMCP_TOKEN_PROFILE | default | Perfil con nombre, para mantener varias identidades de Google en una máquina |
Herramientas
Lectura — siempre disponibles (15)
| Herramienta | Función |
|---|---|
ga4_list_account_summaries | Cuentas y propiedades. Empieza aquí para encontrar un propertyId |
ga4_run_report | Informe de GA4, devuelto como filas planas |
ga4_run_realtime_report | Últimos ~30 minutos |
ga4_list_custom_dimensions | Dimensiones personalizadas con ámbito |
ga4_list_key_events | Eventos clave con método de conteo |
gsc_list_sites | Propiedades de Search Console. Empieza aquí para un siteUrl |
gsc_search_analytics_query | Clics, impresiones, CTR, posición |
gsc_list_sitemaps | Mapas del sitio enviados con advertencias y errores |
gsc_inspect_url | Estado de indexación para una URL (cuota: 2,000/día por propiedad) |
gtm_list_accounts | Cuentas de GTM. Empieza aquí para un accountId |
gtm_list_containers | Contenedores — nota containerId (numérico) vs publicId (GTM-XXXXXXX) |
gtm_list_workspaces | Espacios de trabajo en un contenedor |
gtm_list_tags | Etiquetas con tipo, disparadores y parámetros |
gtm_list_triggers | Disparadores con condiciones de activación |
gtm_list_variables | Variables definidas por el usuario |
Las respuestas están limitadas a 25 filas por defecto. Cuando la salida se recorta, obtienes truncated: true más orientación — prefiere estrechar la consulta sobre aumentar limit.
Escritura — solo con --enable-write (9)
| Herramienta | Función | Reversible |
|---|---|---|
ga4_create_custom_dimension | Crea una dimensión personalizada | No — solo archivo, y los espacios son limitados |
ga4_create_key_event | Marca un evento como evento clave | Sí, desde la UI de GA4 |
ga4_update_key_event | Cambia el método de conteo | Sí |
gsc_submit_sitemap | Envía una URL de mapa del sitio | Sí, desde la UI de Search Console |
gtm_create_tag | Crea una etiqueta en un espacio de trabajo | Sí — no está en vivo hasta publicarse |
gtm_update_tag | Actualiza una etiqueta, fusionando sobre su configuración actual | Sí — no está en vivo hasta publicarse |
gtm_create_trigger | Crea un disparador en un espacio de trabajo | Sí — no está en vivo hasta publicarse |
gtm_create_version | Captura un espacio de trabajo en una versión | Seguro — crear ≠ publicar |
gtm_publish_version | Publica en el sitio en vivo | Sí, vía historial de versiones de GTM |
gtm_update_tag fusiona — la omisión preserva, el vaciado explícito limpia.
La API cruda de GTM reemplaza: omitir firingTriggerId lo vacía silenciosamente, dejando una etiqueta que se ve completamente normal en la UI de GTM y nunca se activa. Verificamos eso contra la API en vivo, y luego hicimos que este servidor lea-y-fusione para que no pueda suceder por accidente.
// changes the name, keeps everything else
{ "tagPath": "...", "name": "New name", "type": "html" }
// deliberately unwires the tag from all triggers
{ "tagPath": "...", "name": "New name", "type": "html", "firingTriggerId": [] }
parameter fusiona por clave, para que puedas cambiar un parámetro sin reenviar el resto. La respuesta lista preservedFields para que puedas ver qué se transfirió.
Seguridad
No implementado, por diseño:
delete_key_event · archive_custom_dimension · delete_sitemap · eliminación de etiquetas / disparadores / variables · agregar y eliminar sitios de GSC · mutación de propiedades y flujos de datos de GA4
Estos se omiten deliberadamente. Un agente no puede llamar lo que no existe.
También:
- Las escrituras de GTM operan en un espacio de trabajo, nunca directamente en el contenedor en vivo.
- GTM mantiene historial de versiones, por lo que una publicación se puede revertir desde la UI de GTM.
La puerta de confirmación de publicación
gtm_publish_version es la única operación aquí que cambia un sitio web en vivo. Requiere confirm: true.
Llamada sin ello, la herramienta realiza una ejecución en seco: obtiene la versión que se publicaría, la compara con la versión actualmente en vivo y devuelve un resumen — nombrando etiquetas, disparadores y variables agregados o eliminados. No publica nada.
// confirm omitted -> nothing published
{
"published": false,
"dryRun": true,
"wouldPublish": { "containerVersionId": "7", "tagCount": 3 },
"currentlyLive": { "containerVersionId": "6", "tagCount": 3 },
"delta": { "tags": { "added": ["Tag NEW"], "removed": ["Tag GONE"], "unchangedCount": 2 } },
"instruction": "NOTHING WAS PUBLISHED. Show this summary to a human..."
}
Esto se verifica mediante una prueba espía que afirma que la API de publicación nunca se invoca sin confirm: true — incluso cuando confirm es un valor no booleano verdadero como "true" o 1, que la validación rechaza:
node scripts/verify-confirm-gate.mjs
Solución de problemas
"El nombre de la aplicación no cumple con los requisitos de Google"
El nombre de tu aplicación OAuth contiene "Google", que la política de marca de Google prohíbe. Cambia el nombre a Measurement MCP. Esto es solo una etiqueta de visualización de la pantalla de consentimiento y no está relacionado con el nombre del paquete.
"Tu inicio de sesión guardado de Google ya no es válido" Lo más probable es que tu pantalla de consentimiento siga en Pruebas (caducidad del token de 7 días) — consulta el paso 3. Otras causas: más de 25 inicios de sesión guardados para un cliente OAuth, un reloj desincronizado o acceso revocado desde tu página de cuenta de Google.
redirect_uri_mismatch
Tu cliente OAuth es de tipo "Aplicación web". Crea un cliente de Aplicación de escritorio en su lugar.
"Permiso denegado" La identidad con sesión iniciada no tiene acceso a esa propiedad, sitio o contenedor — o la API relevante no está habilitada en tu proyecto de Cloud. En la ruta de la cuenta de servicio, confirma que se otorgaron las tres concesiones.
Una API funciona pero otra no devuelve nada (por ejemplo, GA4 funciona, Tag Manager vacío)
Tus activos de GA4, Search Console y Tag Manager probablemente están divididos entre diferentes cuentas de Google. gtm_list_accounts devolviendo 0 en lugar de un error es la señal — la llamada tuvo éxito, simplemente no había nada que esa identidad pudiera ver.
No vuelvas a autenticarte como la otra cuenta. Eso generalmente solo mueve el problema, perdiendo acceso a las APIs que actualmente funcionan. En su lugar, otorga a tu identidad existente acceso al activo faltante:
- Tag Manager → Administración → Gestión de usuarios → añade tu correo electrónico
- GA4 → Administración → Gestión de acceso a la propiedad → añade tu correo electrónico
- Search Console → Configuración → Usuarios y permisos → añade tu correo electrónico
No se necesita reautenticación; los ámbitos ya están otorgados. Los cambios de permisos tardan uno o dos minutos en propagarse.
"Cuota de Google agotada" La inspección de URL de Search Console está limitada a 2,000/día y 600/minuto por propiedad. La API de Tag Manager tiene límites estrictos por usuario — las llamadas de GTM se espacian por minutos, no por segundos.
Faltan herramientas de escritura
Es de esperar a menos que hayas pasado --enable-write o establecido GMCP_ENABLE_WRITE=1. Vuelve a autenticarte después de habilitarlo, ya que el modo de escritura necesita ámbitos adicionales.
Hoja de ruta
- Fase 1 — autenticación, servidor,
ga4_run_report - Fase 2 — suite completa de lectura en GA4, Search Console, Tag Manager
- Fase 3 — herramientas de escritura detrás de la bandera, puerta de confirmación de publicación
- Fase 4 — pruebas de contrato, matriz de trazabilidad, CI
- Fase 5 — lanzamiento en npm
Desarrollo
npm install
npm run build
npm test # 78 contract tests, no network, no credentials
node scripts/verify-confirm-gate.mjs # 17 assertions on the publish gate
Las pruebas de contrato simulan los clientes de Google y verifican el comportamiento de las llamadas, por lo que se ejecutan en cualquier lugar, incluido CI. Las críticas para la seguridad viven en test/contract/safety.test.ts — un fallo allí es un bloqueador de lanzamiento.
Tres documentos cubren el detalle de ingeniería:
docs/DESIGN.md— por qué la arquitectura de seguridad tiene la forma que tienedocs/API-NOTES.md— comportamientos de la API de Google que no están documentados, son fáciles de pasar por alto o son activamente engañososdocs/TESTING.md— matriz de trazabilidad que mapea cada herramienta a su método de API, ámbito, reversibilidad, cuota y pruebas de cobertura, además de las brechas conocidas
Requisitos
Node.js >= 20.
Licencia
Apache-2.0