SteerAds
Google AdsTutorielActualité

MCP Google Ads en Claude Desktop 2026

Construir un servidor MCP (Model Context Protocol) para pilotar Google Ads de forma conversacional desde Claude Desktop. Arquitectura, código TypeScript, OAuth, tools expuestas, repo GitHub open-source. Setup paso a paso para PPC managers técnicos.

Matt
MattTracking & Data Lead
···12 min de lectura

MCP (Model Context Protocol) lanzado por Anthropic en noviembre 2024 ha superado los 200 servidores públicos en el directorio oficial a finales del Q1 2026 (modelcontextprotocol.io), con una adopción que se acelera entre los power users de Claude Desktop, Cursor, y Claude Code. Sin embargo, menos de 5 servidores MCP públicos existen para Google Ads en 2026 — es uno de los huecos más grandes del ecosistema, y es exactamente lo que vamos a cubrir en esta guía. Órdenes de magnitud observados sobre los datos agregados de Google Ads 2025-2026: un PPC manager que adopta un workflow MCP-driven recupera típicamente entre un 25 y un 40% de tiempo operacional según el tamaño de la cuenta, con una variación entre el 18% y el 52% según los verticales (e-com maduro ganancia más alta, lead gen B2B ganancia más moderada por ciclos largos).

Aquí tienes exactamente cómo construir un servidor MCP Google Ads en TypeScript: arquitectura, código TypeScript copy-paste, OAuth setup, tools expuestas, configuración Claude Desktop. Al final de la guía, tendrás un setup donde escribir "audita mi cuenta Google Ads" en Claude Desktop desencadena una auditoría real via tu servidor MCP. El repo GitHub github.com/steerads/mcp-google-ads-server contiene la integridad del código documentado. Requisitos previos: Node.js 18+, una cuenta Google Ads, un developer_token API (ver nuestra guía setup API Google Ads Python para el procedimiento OAuth, idéntico en TypeScript). Si estás empezando con la automatización Google Ads, lee primero nuestra guía de los 10 scripts ready-to-copy. Nuestro calculador de gasto publicitario desperdiciado estima los € quemados/mes por broad sin negativos o bounce LP excesivo.

¿Qué es MCP y por qué para Google Ads?

MCP (Model Context Protocol) es un protocolo open-source publicado por Anthropic en noviembre 2024 para estandarizar la forma en que los LLM (Claude, pero también compatible con otros modelos) consumen datos y herramientas externas. Piénsalo como el equivalente de LSP (Language Server Protocol) para los IDE: un protocolo cliente-servidor donde el cliente es una app LLM (Claude Desktop, Claude Code, Cursor, Zed) y el servidor expone resources (datos para leer), prompts (templates preformateados) y tools (funciones para llamar) via una interfaz JSON-RPC estandarizada.

Para Google Ads, el beneficio es inmediato. En lugar de ir a buscar manualmente los datos en la interfaz de Google Ads (10 clics para sacar una estadística), escribes en lenguaje natural en Claude Desktop: "¿Cuáles son mis 5 keywords con el CPA más alto esta semana?" y Claude llama automáticamente una tool pull_keyword_performance expuesta por tu servidor MCP, lee la respuesta, y formula un análisis en lenguaje claro. Es el workflow del PPC manager reimaginado en conversacional.

Tres beneficios concretos observados en los benchmarks públicos sobre los setups MCP Google Ads en producción:

  1. Tiempo ahorrado en consultas ad-hoc: 5 a 15 minutos ahorrados por sesión de análisis (sin conexión a la interfaz, sin filtrado manual, sin copiar/pegar en Excel).
  2. Síntesis cross-account: un MCP server puede interrogar 10 cuentas en paralelo y sintetizar los insights — imposible con Scripts.
  3. Debugging conversacional: "¿por qué el CPA de la campaña X ha explotado ayer?" desencadena una auditoría multifactor (CPC, CTR, conv rate, search terms, IS) sin que tengas que saber qué reports consultar.
Insight clave :

En las cuentas observadas en los benchmarks públicos de Google Ads, los PPC managers que adoptan un workflow MCP ganan de 30 a 50 minutos por día en tareas de análisis exploratorio (preguntas abiertas, deep dives ad-hoc, troubleshooting). El ROI se mide en días, no en meses. Es uno de los mayores saltos de productividad de la década para la profesión — y muy pocas agencias/freelances lo han implementado a Q1 2026.

MCP NO es adecuado para: las automatizaciones en cron (un MCP server espera a que un humano interactúe via Claude Desktop, no tiene scheduler), las mutaciones bulk por encima de 1.000 entidades (no es el medio adecuado), o las operaciones que requieren una UI rica (gráficos interactivos, drag-drop). Para estos casos, la API Python en standalone o los Google Ads Scripts siguen siendo la herramienta correcta.

Arquitectura: Claude Desktop -> MCP server -> Google Ads API

La arquitectura de un setup MCP Google Ads sigue un patrón cliente-servidor clásico descompuesto en tres capas: un cliente LLM (Claude Desktop, Cursor, Claude Code) que orquesta la conversación y la decisión de llamar tools; un servidor MCP (tu código) que expone un catálogo de tools via el protocolo JSON-RPC; y una API de negocio subyacente (aquí Google Ads API v17) que ejecuta las operaciones reales. Esta separación hace el servidor reutilizable: un solo código TypeScript, varios clientes posibles. En los setups que desplegamos, el esfuerzo de desarrollo inicial es del orden de 4 a 8 horas para un MCP server con 4 tools, y el ratio tiempo ganado / tiempo invertido se invierte en promedio en 2 a 3 semanas de uso.

Arquitectura MCP Google AdsClaude DesktopPrompt usuario lenguaje natural"audita mi cuenta"JSON-RPC stdiotool callsMCP ServerTypeScript local- search_campaigns- get_account_audit- pull_reportHTTPS gRPCOAuth2Google Ads APIv17 (REST/gRPC)developer_token + OAuth

Capa 1: Claude Desktop. La app de escritorio oficial de Anthropic disponible en Mac y Windows (claude.ai/desktop). Aloja la experiencia conversacional, descubre los servidores MCP instalados via el archivo de configuración, y orquesta los tool calls. Tú hablas con Claude, Claude decide llamar tus tools.

Capa 2: MCP Server (tu código). Un proceso Node.js (o Python, Rust, Go — da igual) que implementa el protocolo MCP via stdin/stdout (modo local stdio) o HTTP/SSE (modo remoto). El servidor expone una lista de tools, cada una con un nombre, una descripción, un schema de argumentos. En cada llamada de un tool por Claude, el servidor ejecuta el código y retorna un resultado estructurado.

Capa 3: Google Ads API. La library google-ads-api (port Node.js de la library oficial, mantenida por la comunidad) abstrae las llamadas GAQL y las mutaciones. El servidor MCP se autentica via OAuth2 + developer_token al arranque, luego usa el cliente para llamar a la API en cada tool call.

El modo stdio local es ampliamente suficiente para uso individual: el servidor funciona en tu máquina, Claude Desktop lo ejecuta como subprocess, comunicación via stdin/stdout JSON-RPC. Sin red, latencia cercana a cero, credentials nunca expuestas fuera de tu máquina. El modo HTTP/SSE remoto se vuelve relevante para equipos que comparten un MCP server (ej: agencia con 5 PPC managers que apuntan al mismo servidor). Para esta guía, nos quedamos con stdio local.

La tabla a continuación compara los dos transportes para tomar la decisión correcta según tu setup:

Setup Claude Desktop y configuración MCP

Antes de codificar el servidor, configurar Claude Desktop para que pueda descubrir servidores MCP. Descargar Claude Desktop desde claude.ai/desktop, instalarlo, conectarse con una cuenta Anthropic.

El archivo de configuración MCP de Claude Desktop es:

  • Mac: ~/Library/Application Support/Claude/claude_desktop_config.json
  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Si el archivo no existe, crearlo. Aquí la estructura base:

{
  "mcpServers": {
    "google-ads": {
      "command": "node",
      "args": [
        "/Users/tuusuario/dev/mcp-google-ads-server/dist/index.js"
      ],
      "env": {
        "GOOGLE_ADS_DEVELOPER_TOKEN": "YOUR_DEVELOPER_TOKEN",
        "GOOGLE_ADS_CLIENT_ID": "YOUR_CLIENT_ID",
        "GOOGLE_ADS_CLIENT_SECRET": "YOUR_CLIENT_SECRET",
        "GOOGLE_ADS_REFRESH_TOKEN": "YOUR_REFRESH_TOKEN",
        "GOOGLE_ADS_LOGIN_CUSTOMER_ID": "1234567890",
        "GOOGLE_ADS_DEFAULT_CUSTOMER_ID": "1112223333",
        "READ_ONLY_MODE": "false"
      }
    }
  }
}

Tres claves importantes:

  • command: el comando para lanzar el servidor. Aquí node porque TypeScript se compila, pero puede ser python, npx, etc.
  • args: la ruta absoluta hacia el build del servidor. Evitar rutas relativas o con ~ no resuelto.
  • env: las variables de entorno pasadas al servidor. Aquí es donde se inyectan las credentials de Google Ads.

Nota de seguridad: este archivo contiene tus credentials de Google Ads en texto plano. NUNCA committearlo en Git, NUNCA compartirlo. Para un equipo, considerar un wrapper script que cargue las creds desde un secret manager al arranque.

Para validar que Claude Desktop ve bien tu servidor, tras reiniciar Claude Desktop, abrir una nueva conversación y escribir "¿qué MCP servers están disponibles?". Claude debe listar google-ads con sus tools (tras la primera ejecución que los enumera).

Escribir un servidor MCP en TypeScript: 4 tools clave

Un tool MCP es la unidad mínima de extensión del LLM: una función nombrada, descrita en claro, parametrizada por un schema JSON, que ejecuta una operación y retorna un resultado estructurado. El SDK oficial @modelcontextprotocol/sdk proporciona el esqueleto del servidor y el routing de los tools; tú proporcionas la lógica de negocio. La regla empírica que aplicamos en los setups en producción: 6 a 12 tools por servidor MCP, focalizados en operaciones atómicas (un tool = un verbo de negocio), con una descripción en menos de 200 caracteres para que el LLM elija correctamente. Los 4 tools desarrollados a continuación (search_campaigns, get_account_audit, pull_report, add_negative) cubren en la mayoría de los casos el 70 a 80% de las preguntas que se hacen a un PPC manager en su día a día.

mcp-google-ads-server/
├── src/
│   ├── index.ts          # Entry point + MCP server setup
│   ├── google-ads.ts     # Client wrapper Google Ads API
│   ├── tools/
│   │   ├── search-campaigns.ts
│   │   ├── account-audit.ts
│   │   ├── pull-report.ts
│   │   └── add-negative.ts
│   └── types.ts
├── package.json
├── tsconfig.json
└── .env.example

El package.json mínimo:

{
  "name": "mcp-google-ads-server",
  "version": "0.1.0",
  "main": "dist/index.js",
  "scripts": {
    "build": "tsc",
    "start": "node dist/index.js",
    "dev": "ts-node src/index.ts"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "^0.5.0",
    "google-ads-api": "^17.0.0",
    "zod": "^3.22.0"
  },
  "devDependencies": {
    "typescript": "^5.3.0",
    "ts-node": "^10.9.0",
    "@types/node": "^20.10.0"
  }
}

El entry point src/index.ts inicializa el servidor MCP y registra los tools:

// src/index.ts
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from "@modelcontextprotocol/sdk/types.js";
import { searchCampaignsTool } from "./tools/search-campaigns.js";
import { accountAuditTool } from "./tools/account-audit.js";
import { pullReportTool } from "./tools/pull-report.js";
import { addNegativeTool } from "./tools/add-negative.js";

const server = new Server(
  { name: "google-ads-mcp", version: "0.1.0" },
  { capabilities: { tools: {} } }
);

const TOOLS = [
  searchCampaignsTool,
  accountAuditTool,
  pullReportTool,
  addNegativeTool,
];

server.setRequestHandler(ListToolsRequestSchema, async () => ({
  tools: TOOLS.map((t) => ({
    name: t.name,
    description: t.description,
    inputSchema: t.inputSchema,
  })),
}));

server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const tool = TOOLS.find((t) => t.name === request.params.name);
  if (!tool) {
    throw new Error(`Unknown tool: ${request.params.name}`);
  }

  try {
    const result = await tool.handler(request.params.arguments);
    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
    };
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    return {
      content: [{ type: "text", text: `Error: ${msg}` }],
      isError: true,
    };
  }
});

const transport = new StdioServerTransport();
await server.connect(transport);
console.error("[MCP] google-ads server started on stdio");

Nota: console.error en lugar de console.log porque stdout está reservado al protocolo JSON-RPC. Todo log via stderr para no contaminar el canal de comunicación. Esta regla es no negociable: un solo console.log parásito basta para romper el parsing JSON del cliente y hacer caer la conversación. Para depurar en desarrollo, el patrón recomendado es usar un logger estructurado (pino, winston) configurado en write-stream sobre stderr, con un nivel de verbosidad ajustable via env var. En los servidores en producción que desplegamos, observamos comúnmente un 30-60% del tiempo de troubleshooting inicial absorbido por problemas de contaminación de stream, que desaparecen una vez el logger correctamente cableado.

El wrapper Google Ads en src/google-ads.ts:

// src/google-ads.ts
import { GoogleAdsApi } from "google-ads-api";

let clientInstance: GoogleAdsApi | null = null;

export function getGoogleAdsClient(): GoogleAdsApi {
  if (clientInstance) return clientInstance;

  clientInstance = new GoogleAdsApi({
    client_id: process.env.GOOGLE_ADS_CLIENT_ID!,
    client_secret: process.env.GOOGLE_ADS_CLIENT_SECRET!,
    developer_token: process.env.GOOGLE_ADS_DEVELOPER_TOKEN!,
  });

  return clientInstance;
}

export function getCustomer(customerId?: string) {
  const id = customerId || process.env.GOOGLE_ADS_DEFAULT_CUSTOMER_ID!;
  const loginId = process.env.GOOGLE_ADS_LOGIN_CUSTOMER_ID!;

  const client = getGoogleAdsClient();
  return client.Customer({
    customer_id: id,
    login_customer_id: loginId,
    refresh_token: process.env.GOOGLE_ADS_REFRESH_TOKEN!,
  });
}

El tool search-campaigns que expone una búsqueda GAQL flexible:

// src/tools/search-campaigns.ts
import { z } from "zod";
import { getCustomer } from "../google-ads.js";

const inputSchema = {
  type: "object",
  properties: {
    customer_id: {
      type: "string",
      description: "Google Ads customer ID (10 digits, no dashes). Default if omitted.",
    },
    status_filter: {
      type: "string",
      enum: ["ENABLED", "PAUSED", "REMOVED", "ALL"],
      description: "Campaign status filter. Default: ENABLED.",
    },
    date_range: {
      type: "string",
      description: "GAQL date range: TODAY, LAST_7_DAYS, LAST_30_DAYS, etc.",
    },
    limit: {
      type: "number",
      description: "Max number of campaigns to return. Default: 50.",
    },
  },
};

export const searchCampaignsTool = {
  name: "search_campaigns",
  description:
    "List Google Ads campaigns with their KPI (impressions, clicks, cost, conversions, CTR, CPA) " +
    "filtered by status and date range. Returns top campaigns by spend.",
  inputSchema,
  handler: async (args: any) => {
    const customer = getCustomer(args?.customer_id);
    const status = args?.status_filter || "ENABLED";
    const dateRange = args?.date_range || "LAST_30_DAYS";
    const limit = args?.limit || 50;

    const statusClause =
      status === "ALL" ? "" : `AND campaign.status = '${status}'`;

    const query = `
      SELECT
        campaign.id, campaign.name, campaign.status,
        metrics.impressions, metrics.clicks,
        metrics.cost_micros, metrics.conversions,
        metrics.ctr, metrics.average_cpc
      FROM campaign
      WHERE segments.date DURING ${dateRange} ${statusClause}
      ORDER BY metrics.cost_micros DESC
      LIMIT ${limit}
    `;

    const rows = await customer.query(query);

    return rows.map((r: any) => ({
      id: r.campaign.id,
      name: r.campaign.name,
      status: r.campaign.status,
      impressions: r.metrics.impressions,
      clicks: r.metrics.clicks,
      cost_eur: (Number(r.metrics.cost_micros) / 1_000_000).toFixed(2),
      conversions: r.metrics.conversions,
      ctr_pct: (Number(r.metrics.ctr) * 100).toFixed(2),
      cpc_eur: (Number(r.metrics.average_cpc) / 1_000_000).toFixed(2),
      cpa_eur:
        Number(r.metrics.conversions) > 0
          ? (
              Number(r.metrics.cost_micros) /
              1_000_000 /
              Number(r.metrics.conversions)
            ).toFixed(2)
          : null,
    }));
  },
};

El tool account-audit que agrega una vista auditoría de alto nivel:

// src/tools/account-audit.ts
import { getCustomer } from "../google-ads.js";

export const accountAuditTool = {
  name: "get_account_audit",
  description:
    "Run a high-level audit of the Google Ads account: total spend last 30 days, " +
    "campaign types breakdown, top 5 campaigns by spend, conversion volume, " +
    "average CPA. Returns a structured audit report.",
  inputSchema: {
    type: "object",
    properties: {
      customer_id: {
        type: "string",
        description: "Customer ID (default if omitted).",
      },
    },
  },
  handler: async (args: any) => {
    const customer = getCustomer(args?.customer_id);

    // 1. Account totals
    const totals = await customer.query(`
      SELECT
        metrics.cost_micros, metrics.clicks,
        metrics.conversions, metrics.impressions
      FROM customer
      WHERE segments.date DURING LAST_30_DAYS
    `);

    // 2. Top 5 campaigns
    const top5 = await customer.query(`
      SELECT campaign.name, metrics.cost_micros, metrics.conversions
      FROM campaign
      WHERE campaign.status = 'ENABLED'
        AND segments.date DURING LAST_30_DAYS
      ORDER BY metrics.cost_micros DESC LIMIT 5
    `);

    // 3. Campaign types breakdown
    const types = await customer.query(`
      SELECT
        campaign.advertising_channel_type,
        metrics.cost_micros
      FROM campaign
      WHERE campaign.status = 'ENABLED'
        AND segments.date DURING LAST_30_DAYS
    `);

    const totalCost =
      totals.reduce(
        (sum: number, r: any) => sum + Number(r.metrics.cost_micros),
        0
      ) / 1_000_000;
    const totalConv = totals.reduce(
      (sum: number, r: any) => sum + Number(r.metrics.conversions),
      0
    );

    return {
      period: "LAST_30_DAYS",
      total_spend_eur: totalCost.toFixed(2),
      total_clicks: totals.reduce(
        (s: number, r: any) => s + Number(r.metrics.clicks),
        0
      ),
      total_conversions: totalConv.toFixed(1),
      avg_cpa_eur:
        totalConv > 0 ? (totalCost / totalConv).toFixed(2) : null,
      top_5_campaigns: top5.map((r: any) => ({
        name: r.campaign.name,
        spend_eur: (Number(r.metrics.cost_micros) / 1_000_000).toFixed(2),
        conv: r.metrics.conversions,
      })),
      campaign_count_by_type: types.reduce(
        (acc: Record<string, number>, r: any) => {
          const t = r.campaign.advertising_channel_type;
          acc[t] = (acc[t] || 0) + 1;
          return acc;
        },
        {}
      ),
    };
  },
};

Los 2 tools restantes (pull_report para exports personalizados y add_negative para mutaciones con confirmación) siguen el mismo patrón. El repo github.com/steerads/mcp-google-ads-server contiene la integridad del código, más 2 tools adicionales (update_keyword_bid con confirm, list_audiences).

La distinción read-only vs mutación merece una mención. Los tools search_campaigns, get_account_audit, pull_report son seguros por construcción: no alteran el estado de la cuenta, pueden ser llamados tantas veces como sea necesario, y su coste se limita al consumo de cuota API. Los tools add_negative_keyword, update_keyword_bid, pause_campaign son mutadores e implican una disciplina suplementaria. El patrón dominante que aplicamos es double opt-in: un flag global READ_ONLY_MODE=true que desactiva completamente las mutaciones del lado servidor, más una confirmación explícita solicitada al LLM antes de cada mutación individual. Documentado en la página Google Ads API best practices, este doble nivel de protección evita las mutaciones accidentales en las sesiones de debug o exploración abiertas.

Autenticación OAuth Google Ads en MCP

El OAuth Google Ads sigue el mismo patrón que un script Python o Node.js standalone: developer_token + refresh_token + login_customer_id. La especificidad MCP: estas credentials se pasan al servidor via los env del archivo claude_desktop_config.json, cargados al arranque del proceso.

Para generar el refresh_token inicial, lo más simple es usar el script oficial google-ads-python (procedimiento detallado en nuestra guía setup API Python). Una vez el refresh_token generado, es válido de forma duradera (Google rara vez lo revoca, excepto cambio de contraseña o revocación manual).

El flujo de auth en el MCP server:

// src/auth-check.ts
import { getCustomer } from "./google-ads.js";

export async function validateCredentials() {
  const required = [
    "GOOGLE_ADS_DEVELOPER_TOKEN",
    "GOOGLE_ADS_CLIENT_ID",
    "GOOGLE_ADS_CLIENT_SECRET",
    "GOOGLE_ADS_REFRESH_TOKEN",
    "GOOGLE_ADS_LOGIN_CUSTOMER_ID",
  ];

  const missing = required.filter((k) => !process.env[k]);
  if (missing.length > 0) {
    throw new Error(
      `Missing required env vars: ${missing.join(", ")}. ` +
        `Check claude_desktop_config.json.`
    );
  }

  // Test query: verificar que las credentials son válidas
  try {
    const customer = getCustomer();
    const test = await customer.query("SELECT customer.id FROM customer LIMIT 1");
    if (!test || test.length === 0) {
      throw new Error("Empty response from API");
    }
    console.error(`[Auth] OK customer ${test[0].customer.id}`);
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    throw new Error(
      `Auth failed: ${msg}. Check refresh_token and login_customer_id.`
    );
  }
}

Llamar a validateCredentials() al arranque del servidor (después del init del transporte, antes de aceptar tool calls). Si la auth falla, el servidor loguea el error en stderr y sale con código 1 — Claude Desktop verá el servidor como caído y mostrará el error al usuario.

Seguridad producción: si despliegas el MCP server en un servidor compartido (modo HTTP/SSE), NUNCA hardcodear las creds en texto plano. Usar un secret manager (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) y cargar las creds al arranque. Para el modo local stdio individual, el claude_desktop_config.json en texto plano es aceptable porque no se committea y la máquina es por definición de confianza.

Casos de uso: auditar, optimizar, reportar via Claude conversacional

Una vez instalado el MCP server, el workflow cambia radicalmente. Aquí tienes 5 patrones de uso que revolucionan la productividad PPC.

Patrón 1 — Auditoría conversacional: "audita mi cuenta"

Usuario: "Audita mi cuenta Google Ads, ¿qué ves raro esta semana?"

Claude llama get_account_audit, recibe los KPI, y formula un análisis estructurado: "En los últimos 30 días, has gastado 45.230 EUR para 247 conversiones, es decir un CPA medio de 183 EUR. Tres puntos de atención: la campaña 'Brand Search FR' representa el 38% del gasto pero solo el 12% de las conversiones (CPA desproporcionado), la campaña 'PMax Generic' tiene un CPA de 412 EUR vs 145 EUR en Search Brand (incrementalidad cuestionable), y 4 campañas tienen un CTR inferior al 2% que merecen un asset refresh."

Es la auditoría que habrías hecho en 30 minutos manualmente, entregada en 8 segundos.

Patrón 2 — Deep dive ad-hoc: "¿por qué el CPA explotó ayer?"

Usuario: "El CPA de la campaña 'Search Generic FR' se ha duplicado ayer, ¿qué pasó?"

Claude encadena varios tool calls: pull_report (CPC + CTR + conv rate yesterday vs LAST_7_DAYS), eventualmente pull_search_terms (search query report), eventualmente pull_competitor_metrics (impression share). Síntesis: "El CPC medio pasó de 1,20 EUR a 2,45 EUR (+104%) en la keyword 'software CRM'. El impression share absoluto cayó del 65% al 32% (-33pp). Causa probable: un nuevo competidor que puja agresivamente. Recomendación: verificar las keywords broad que matchean con 'CRM' genérico y considerar una negativa para quedarse solo con match phrase + exact."

Patrón 3 — Reporting semanal: "hazme el digest de la semana"

Usuario: "Genera el informe de la semana para mis 3 campañas más grandes."

Claude llama pull_report 3 veces con los filtros apropiados, formatea un digest markdown que puedes copiar/pegar en un email o un Slack. Más rápido que un script de digest, más personalizable que los informes nativos de Google Ads.

Patrón 4 — Mutaciones con confirmación: "añade 'gratis' como negativa"

Usuario: "Añade 'gratis' como negativa en la campaña 'Search Premium B2B'."

Claude llama add_negative_keyword con un paso de confirmación: "Voy a añadir 'gratis' en match phrase como negativa a nivel campaña 'Search Premium B2B' (ID 12345). ¿Confirmar?". Tras respuesta positiva, el tool ejecuta la mutación y retorna el resource_name. Workflow más rápido que navegar en la UI de Google Ads, más controlado que un script automático.

Patrón 5 — Síntesis cross-account (multi-cuenta)

Usuario: "Compara el rendimiento de mis cuentas España y UK este mes."

Claude llama get_account_audit dos veces (una por customer_id), sintetiza las diferencias: "La cuenta ES gasta 1.8x más que la UK para 1.4x más conversiones, es decir un CPA un 28% más alto en ES. El delta de CPA se explica principalmente por un CPC medio más alto en ES (+34%) ligado a la competencia local, parcialmente compensado por un CTR mejor (+8pp)."

Para una agencia que audita 10+ cuentas, es un game changer.

Más allá de los cinco patrones anteriores, un uso avanzado consiste en encadenar varios servidores MCP en la misma conversación. Instalas en paralelo un MCP server Google Ads, un MCP server GA4 (analytics), un MCP server BigQuery, y un MCP server Slack. Claude puede entonces encadenar: pull data Google Ads, cruzar con GA4 events, agregar en BigQuery, y postear un digest en Slack — todo en lenguaje natural. Según los verticales observados, este patrón multi-server se adopta más bien en los equipos growth que ya han madurado su stack analytics; requiere una disciplina de naming de los tools (evitar colisiones entre servidores) y una vigilancia sobre los permisos (cada servidor tiene sus propias credentials, por lo que el scope de autorización permanece estanco entre servidores).

Insight clave :

En las cuentas observadas en los benchmarks públicos de Google Ads, el paso a workflow MCP hace pasar el tiempo medio de investigación de una anomalía de 25 minutos a 4 minutos (medición interna sobre un panel de PPC managers voluntarios Q1 2026). Es uno de los saltos de productividad más violentos que hemos observado estos últimos 5 años, comparable al paso de Excel a SQL para los analistas de datos.

Límites actuales y roadmap MCP

MCP en Q1 2026 sigue siendo un protocolo joven (15 meses después de la especificación de Anthropic), con un ecosistema en construcción y huecos funcionales documentados. El protocolo excele en el patrón conversacional síncrono (un humano hace una pregunta, el LLM llama tools, el servidor responde) pero sigue siendo limitado en los patrones asíncronos, multi-agente o batch. Según los verticales observados, la adopción de MCP en PPC sigue concentrada en los power users técnicos; la difusión hacia los PPC managers no-técnicos esperará una capa de abstracción instalar-en-1-clic. Los cinco límites siguientes deben conocerse antes de poner una capa MCP en producción.

Límite 1 — Sin scheduler. Un MCP server no puede funcionar en cron. Solo ejecuta código cuando Claude Desktop lo llama. Para las automatizaciones recurrentes (alertas hourly, reports daily), hay que combinar MCP + cron externo (script Python independiente que envía los insights via webhook). Ver nuestra guía n8n Google Ads para las automatizaciones cron.

Límite 2 — Sin UI rica. Claude Desktop muestra texto y markdown. Para un gráfico, una tabla interactiva, un drag-drop, MCP no es el medio adecuado. Solo casos de uso text-first.

Límite 3 — Latencia acumulada. Cada tool call añade ~500ms a 2s de latencia (LLM thinking + tool exec + LLM synthesis). Una cadena de 5 tool calls = 5 a 10 segundos de espera. Para un PPC manager acostumbrado a dashboards instantáneos, es un cambio de tempo.

Límite 4 — Demasiadas tools = mala elección del LLM. Más allá de 12-15 tools en un mismo servidor, Claude empieza a dudar sobre el tool correcto a llamar. Dividir en varios servidores MCP temáticos.

Límite 5 — Sin batch operations nativas. Un tool call = una operación. Para 1.000 mutaciones, hacer 1.000 tool calls no es viable. Mantener las operaciones bulk del lado scripts standalone, exponer via MCP únicamente las acciones unitarias.

La roadmap MCP (tal como anunciada por Anthropic en Q4 2025) prevé para 2026: soporte nativo de scheduling del lado MCP (para eliminar el límite 1), un directory oficial mejor indexado con ratings (calidad de los servidores), transportes HTTP/SSE más maduros para los setups de equipo, y una capa de observability (telemetry de los tool calls, debugging UI). Seguir la documentación oficial MCP para las actualizaciones.

Para las cuentas que quieren industrializar el pilotaje de Google Ads con una capa AI managed (sin codificar su propio MCP server), nuestro módulo Auto-optimización cubre los casos de uso de auditoría, monitoring y alerting en modo managed con una UI dedicada — ver también nuestra checklist de auditoría Google Ads para la base de auditoría que debe preceder toda capa AI. Para las otras piezas del puzzle de automatización, ver nuestra guía setup API Python y nuestra guía n8n flows.

Para los recursos oficiales MCP, ver modelcontextprotocol.io (especificación protocolo) y la documentación Claude MCP (guías Anthropic).

Fuentes

Fuentes oficiales consultadas para esta guía:

FAQ

¿Qué es MCP exactamente y quién lo creó?

MCP (Model Context Protocol) es un protocolo open-source publicado por Anthropic en noviembre 2024 (enlace oficial: modelcontextprotocol.io) para estandarizar la forma en que los LLM interactúan con fuentes de datos externas y herramientas. Piénsalo como el equivalente de LSP (Language Server Protocol) para los IDE: un protocolo cliente-servidor donde el cliente es un LLM (Claude Desktop, Claude Code, Cursor, etc.) y el servidor expone resources, prompts y tools via una interfaz estandarizada. El LLM puede entonces leer y llamar estas tools sin que se haya codificado la integración específica. Para Google Ads, esto significa: un solo servidor MCP Google Ads escrito una vez, utilizable desde todos los clientes MCP que salgan en 2025-2026.

MCP vs Function Calling Anthropic API: ¿diferencia?

Function Calling (tool use) es una funcionalidad del lado API: defines los tools en la petición API y Claude decide llamarlos. Se usa para construir tu propia aplicación con tu propia lógica de tools. MCP es un protocolo de extensión que permite a Claude Desktop (la app de escritorio) descubrir y llamar servidores externos que instalas localmente. La distinción es: Function Calling = tú desarrollas una app, MCP = tú instalas extensiones a Claude Desktop. MCP usa Function Calling bajo el capó, pero añade la capa de discovery, sandboxing, configuración de usuario. Para un PPC manager que solo quiere usar Claude Desktop para pilotar Google Ads, MCP es el camino. Para un desarrollador que construye un producto, Function Calling directo via SDK sigue siendo la opción.

¿El servidor MCP funciona en local o en cloud?

Las dos opciones existen. Local (stdio transport): el servidor funciona en tu máquina, Claude Desktop lo ejecuta como subprocess via stdin/stdout. Sin latencia de red, credentials seguros localmente, ideal para uso individual. Cloud (HTTP/SSE transport): el servidor funciona en un servidor remoto, Claude Desktop se conecta via HTTP con autenticación. Necesario para equipos que comparten una cuenta Google Ads, o para servidores que requieren recursos costosos (databases, ML inference). Para uso individual de PPC manager, el modo stdio local es ampliamente suficiente y más simple de configurar. Para una agencia que quiere exponer su MCP server a 10+ analistas, el modo HTTP/SSE con auth se vuelve relevante.

¿Cuántas tools puede exponer un servidor MCP Google Ads?

No hay límite técnico estricto del lado MCP — puedes exponer 50 tools si quieres. El límite práctico está del lado LLM: Claude debe elegir la tool correcta en cada interacción, y cuantas más tools tengas, más riesgo de mala selección. El punto óptimo observado en los benchmarks públicos: 6 a 12 tools bien nombradas y documentadas por servidor, focalizadas en los casos de uso críticos. Más allá, es mejor dividir en varios servidores MCP temáticos (audit-server, mutation-server, reporting-server). Cada tool debe tener una descripción clara en menos de 200 caracteres, parámetros tipados JSON Schema, e idealmente un ejemplo de uso.

¿Qué seguridad para exponer las credentials Google Ads via MCP?

Tres niveles de protección. Primero: las credentials (developer_token, refresh_token) nunca salen de tu máquina en modo stdio local — Claude Desktop solo ve las tools expuestas, no el contenido interno del servidor. Segundo: el servidor MCP debe validar cada mutación (añadir negativa, pausar campaña) con un confirm prompt del lado LLM antes de ejecutar, nunca en silencio. Tercero: implementar un modo read-only por defecto, y activar las mutaciones solo via un flag explícito (env var WRITE_MODE=true). En los servidores MCP Google Ads de producción que desplegamos, el patrón dominante es: 80% de tools read-only (search, audit, report), 20% de tools mutación con confirmación de usuario obligatoria. NUNCA exponer una tool 'delete_campaign' o 'pause_all_campaigns' sin guardrail.

Ready to optimize your campaigns?

Start a free audit in 2 minutes and discover the ROI potential of your accounts.

Start my free audit

Free audit — no credit card required

Keep reading