SteerAds
Google AdsTutorielActualité

MCP Google Ads na Claude Desktop 2026

Budowanie serwera MCP (Model Context Protocol) do konwersacyjnego sterowania Google Ads z Claude Desktop. Architektura, kod TypeScript, OAuth, eksponowane tools, repo GitHub open-source. Krok po kroku dla technicznych PPC managerów.

Matt
MattTracking & Data Lead
···12 min czytania

MCP (Model Context Protocol) uruchomiony przez Anthropic w listopadzie 2024 przekroczył 200 publicznych serwerów w oficjalnym katalogu pod koniec Q1 2026 (modelcontextprotocol.io), z adopcją przyspieszającą wśród power users Claude Desktop, Cursor i Claude Code. Mimo to, mniej niż 5 publicznych serwerów MCP dla Google Ads istnieje w 2026 — to jedna z największych luk ekosystemu, i właśnie to wypełniamy w tym przewodniku. Rzędy wielkości obserwowane w zagregowanych danych Google Ads 2025-2026: PPC manager adoptujący workflow oparty na MCP typowo odzyskuje 25-40% czasu operacyjnego według wielkości konta, z różnicami między 18% a 52% zależnie od branży (dojrzały e-commerce osiąga największy zysk, lead gen B2B bardziej umiarkowany ze względu na długie cykle).

Oto dokładnie jak zbudować serwer MCP Google Ads w TypeScript: architektura, kod TypeScript do kopiowania, setup OAuth, eksponowane tools, konfiguracja Claude Desktop. Na końcu przewodnika będziesz miał setup, gdzie wpisanie "przeprowadź audyt mojego konta Google Ads" w Claude Desktop uruchamia prawdziwy audyt przez Twój serwer MCP. Repo GitHub github.com/steerads/mcp-google-ads-server zawiera cały udokumentowany kod. Wymagania: Node.js 18+, konto Google Ads, developer_token API (zob. nasz przewodnik setup API Google Ads Python dla procedury OAuth, identycznej po stronie TypeScript). Jeśli dopiero zaczynasz z automatyzacją Google Ads, najpierw przeczytaj nasz przewodnik 10 gotowych skryptów. Nasz kalkulator marnowanego budżetu szacuje EUR spalone miesięcznie przez broad bez wykluczeń lub nadmierne odbicia z LP.

Czym jest MCP i dlaczego dla Google Ads?

MCP (Model Context Protocol) to protokół open-source opublikowany przez Anthropic w listopadzie 2024 w celu standaryzacji sposobu, w jaki LLM (Claude, ale też kompatybilny z innymi modelami) konsumują dane i zewnętrzne narzędzia. Pomyśl o nim jak o odpowiedniku LSP (Language Server Protocol) dla IDE: protokół klient-serwer, gdzie klientem jest aplikacja LLM (Claude Desktop, Claude Code, Cursor, Zed), a serwer eksponuje zasoby (dane do odczytu), prompty (wstępnie sformatowane szablony) i tools (funkcje do wywołania) przez standaryzowany interfejs JSON-RPC.

Dla Google Ads korzyść jest natychmiastowa. Zamiast ręcznie szukać danych w interfejsie Google Ads (10 kliknięć, żeby pobrać statystykę), wpisujesz w języku naturalnym w Claude Desktop: "Jakie są moje 5 słów kluczowych z najwyższym CPA w tym tygodniu?" i Claude automatycznie wywołuje narzędzie pull_keyword_performance eksponowane przez Twój serwer MCP, czyta odpowiedź i formułuje analizę w zrozumiałym języku. To workflow PPC managera wyobrażony na nowo jako konwersacyjny.

Trzy konkretne korzyści obserwowane w publicznych benchmarkach na produkcyjnych setupach MCP Google Ads:

  1. Zaoszczędzony czas na zapytaniach ad-hoc: 5-15 minut zaoszczędzonych na sesję analizy (bez logowania do interfejsu, bez ręcznego filtrowania, bez kopiowania/wklejania do Excel).
  2. Synteza cross-account: serwer MCP może odpytać 10 kont równolegle i syntezować wnioski — niemożliwe po stronie Skryptów.
  3. Konwersacyjne debugowanie: "dlaczego CPA kampanii X eksplodował wczoraj?" uruchamia wieloczynnikowy audyt (CPC, CTR, wskaźnik konwersji, search terms, IS) bez potrzeby wiedzy, które raporty konsultować.
Kluczowy wniosek :

W benchmarkach Google Ads, PPC managerowie adoptujący workflow MCP zyskują 30-50 minut dziennie na zadaniach eksploracyjnej analizy (otwarte pytania, ad-hoc deep dives, troubleshooting). ROI mierzy się w dniach, nie w miesiącach. To jeden z największych skoków produktywności w tej dekadzie dla zawodu — i bardzo mało agencji/freelancerów ma to wdrożone w Q1 2026.

MCP NIE jest odpowiedni dla: automatyzacji cron (serwer MCP czeka na interakcję człowieka przez Claude Desktop, nie ma schedulera), masowych mutacji powyżej 1 000 encji (nieodpowiednie medium), ani operacji wymagających bogatego UI (interaktywne wykresy, drag-drop). Dla tych przypadków, Python API standalone lub Google Ads Scripts pozostają właściwym narzędziem.

Architektura: Claude Desktop -> serwer MCP -> Google Ads API

Architektura setupu MCP Google Ads podąża za klasycznym wzorcem klient-serwer podzielonym na trzy warstwy: klient LLM (Claude Desktop, Cursor, Claude Code) orkiestrujący rozmowę i decyzję o wywołaniu tools; serwer MCP (Twój kod) eksponujący katalog tools przez protokół JSON-RPC; i leżące u podstaw API biznesowe (tu Google Ads API v17) wykonujące rzeczywiste operacje. To rozdzielenie sprawia, że serwer jest wielokrotnego użytku: jeden kod TypeScript, wiele możliwych klientów. Na wdrażanych przez nas setupach, początkowy wysiłek deweloperski wynosi 4-8 godzin dla serwera MCP z 4 tools, a stosunek zaoszczędzonego czasu do zainwestowanego odwraca się średnio po 2-3 tygodniach użytkowania.

Architecture MCP Google AdsClaude DesktopUser prompt en langage naturel"audite mon compte"JSON-RPC stdiotool callsMCP ServerTypeScript local- search_campaigns- get_account_audit- pull_reportHTTPS gRPCOAuth2Google Ads APIv17 (REST/gRPC)developer_token + OAuth

Warstwa 1: Claude Desktop. Oficjalna aplikacja desktopowa Anthropic dostępna na Mac i Windows (claude.ai/desktop). Hostuje doświadczenie konwersacyjne, odkrywa serwery MCP zainstalowane przez plik konfiguracyjny i orkiestruje wywołania tools. Rozmawiasz z Claude, Claude decyduje o wywołaniu Twoich tools.

Warstwa 2: Serwer MCP (Twój kod). Proces Node.js (lub Python, Rust, Go — nieważne) implementujący protokół MCP przez stdin/stdout (tryb lokalny stdio) lub HTTP/SSE (tryb zdalny). Serwer eksponuje katalog tools, każde z nazwą, opisem, schematem argumentów. Przy każdym wywołaniu narzędzia przez Claude, serwer wykonuje kod i zwraca ustrukturyzowany wynik.

Warstwa 3: Google Ads API. Biblioteka google-ads-api (port Node.js oficjalnej biblioteki, utrzymywana przez społeczność) abstrahuje wywołania GAQL i mutacje. Serwer MCP uwierzytelnia się przez OAuth2 + developer_token przy starcie, następnie używa klienta do wywoływania API przy każdym wywołaniu narzędzia.

Tryb stdio lokalny jest w pełni wystarczający do użytku indywidualnego: serwer działa na Twojej maszynie, Claude Desktop uruchamia go jako subprocess, komunikacja przez stdin/stdout JSON-RPC. Bez sieci, opóźnienie bliskie zeru, credentials nigdy nieeksponowane poza Twoją maszyną. Tryb HTTP/SSE zdalny staje się istotny dla zespołów współdzielących serwer MCP (np. agencja z 5 PPC managerami wskazującymi na ten sam serwer). W tym przewodniku zostajemy przy stdio lokalnym.

Poniższa tabela porównuje dwa transporty, aby pomóc w właściwym wyborze dla Twojego setupu:

Setup Claude Desktop i konfiguracja MCP

Przed kodowaniem serwera, skonfiguruj Claude Desktop, aby mógł odkrywać serwery MCP. Pobierz Claude Desktop z claude.ai/desktop, zainstaluj, zaloguj się kontem Anthropic.

Plik konfiguracyjny MCP Claude Desktop to:

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

Jeśli plik nie istnieje, utwórz go. Oto podstawowa struktura:

{
  "mcpServers": {
    "google-ads": {
      "command": "node",
      "args": [
        "/Users/votreuser/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"
      }
    }
  }
}

Trzy ważne klucze:

  • command: polecenie do uruchomienia serwera. Tu node, bo TypeScript się kompiluje, ale może być python, npx, itp.
  • args: absolutna ścieżka do builda serwera. Unikaj ścieżek względnych lub z nierozwiązanym ~.
  • env: zmienne środowiskowe przekazywane do serwera. Tu wstrzykujemy credentials Google Ads.

Uwaga o bezpieczeństwie: ten plik zawiera Twoje credentials Google Ads w postaci jawnej. NIGDY nie commituj go do Git, NIGDY nie udostępniaj. Dla zespołu, rozważ skrypt wrapper ładujący credentials z secret managera przy uruchomieniu.

Aby zweryfikować, że Claude Desktop widzi Twój serwer, po restarcie Claude Desktop otwórz nową rozmowę i wpisz "jakie serwery MCP są dostępne?". Claude powinien wylistować google-ads z jego tools (po pierwszym uruchomieniu, które je wylicza).

Pisanie serwera MCP w TypeScript: 4 kluczowe tools

Narzędzie MCP to minimalna jednostka rozszerzenia LLM: nazwana funkcja, opisana czytelnie, sparametryzowana schematem JSON, wykonująca operację i zwracająca ustrukturyzowany wynik. Oficjalny SDK @modelcontextprotocol/sdk dostarcza szkielet serwera i routing tools; Ty dostarczasz logikę biznesową. Empiryczna zasada stosowana na produkcyjnych setupach: 6-12 tools na serwer MCP, skupionych na atomowych operacjach (jedno narzędzie = jeden czasownik biznesowy), z opisem poniżej 200 znaków, aby LLM wybrał właściwie. 4 tools rozwijane poniżej (search_campaigns, get_account_audit, pull_report, add_negative) pokrywają w większości przypadków 70-80% pytań zadawanych PPC managerowi na co dzień.

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

Minimalny package.json:

{
  "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"
  }
}

Entry point src/index.ts inicjalizujący serwer MCP i rejestrujący 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");

Uwaga: console.error zamiast console.log, ponieważ stdout jest zarezerwowany dla protokołu JSON-RPC. Wszystkie logi przez stderr, aby nie zanieczyszczać kanału komunikacji. Ta zasada jest bezwzględna: jeden zbędny console.log wystarczy, aby zepsuć parsowanie JSON klienta i zerwać rozmowę. Do debugowania w fazie developerskiej, zalecany wzorzec to ustrukturyzowany logger (pino, winston) skonfigurowany do pisania na stderr, z poziomem szczegółowości regulowanym przez env var.

Wrapper Google Ads w 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!,
  });
}

Narzędzie search-campaigns eksponujące elastyczne wyszukiwanie GAQL:

// 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,
    }));
  },
};

Narzędzie account-audit agregujące widok audytu wysokiego poziomu:

// 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;
        },
        {}
      ),
    };
  },
};

Pozostałe 2 tools (pull_report dla niestandardowych eksportów i add_negative dla mutacji z potwierdzeniem) podążają tym samym wzorcem. Repo github.com/steerads/mcp-google-ads-server zawiera cały kod, plus 2 dodatkowe tools (update_keyword_bid z potwierdzeniem, list_audiences).

Rozróżnienie read-only vs mutacja zasługuje na komentarz. Narzędzia search_campaigns, get_account_audit, pull_report są bezpieczne z konstrukcji: nie zmieniają stanu konta, mogą być wywoływane dowolną liczbę razy, a ich koszt ogranicza się do zużycia limitu API. Narzędzia add_negative_keyword, update_keyword_bid, pause_campaign są mutacyjne i wymagają dodatkowej dyscypliny. Dominujący wzorzec stosowany przez nas to double opt-in: globalna flaga READ_ONLY_MODE=true całkowicie wyłączająca mutacje po stronie serwera, plus explicytne potwierdzenie wymagane od LLM przed każdą indywidualną mutacją. Udokumentowane na stronie best practices Google Ads API, ten dwupoziomowy poziom ochrony zapobiega przypadkowym mutacjom w sesjach debugowania lub eksploracji.

Uwierzytelnianie OAuth Google Ads w MCP

OAuth Google Ads podąża tym samym wzorcem co samodzielny skrypt Python lub Node.js: developer_token + refresh_token + login_customer_id. Specyfika MCP: te credentials są przekazywane do serwera przez env w pliku claude_desktop_config.json, ładowane przy starcie procesu.

Aby wygenerować początkowy refresh_token, najprościej jest użyć oficjalnego skryptu google-ads-python (szczegółowa procedura w naszym przewodniku setup API Python). Po wygenerowaniu refresh_token jest długotrwały (Google rzadko go unieważnia, chyba przy zmianie hasła lub ręcznym unieważnieniu).

Flow uwierzytelniania w serwerze MCP:

// 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 : verifier que les credentials sont valides
  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.`
    );
  }
}

Wywołaj validateCredentials() przy starcie serwera (po inicjalizacji transportu, przed akceptowaniem wywołań tools). Jeśli uwierzytelnianie nie powiedzie się, serwer loguje błąd na stderr i kończy działanie z kodem 1 — Claude Desktop zobaczy serwer jako niedostępny i wyświetli błąd użytkownikowi.

Bezpieczeństwo produkcyjne: jeśli wdrażasz serwer MCP na współdzielonym serwerze (tryb HTTP/SSE), NIGDY nie hardkoduj credentials w postaci jawnej. Użyj secret managera (AWS Secrets Manager, GCP Secret Manager, HashiCorp Vault) i ładuj credentials przy starcie. Dla trybu stdio lokalnego indywidualnego, claude_desktop_config.json w postaci jawnej jest akceptowalny, ponieważ nie jest commitowany, a maszyna jest z definicji zaufana.

Przypadki użycia: audyt, optymalizacja, raportowanie przez Claude konwersacyjny

Po zainstalowaniu serwera MCP workflow zmienia się radykalnie. Oto 5 wzorców użycia rewolucjonizujących produktywność PPC.

Wzorzec 1 — Konwersacyjny audyt: "przeprowadź audyt mojego konta"

Użytkownik: "Przeprowadź audyt mojego konta Google Ads, co widzisz niepokojącego w tym tygodniu?"

Claude wywołuje get_account_audit, otrzymuje KPI i formułuje ustrukturyzowaną analizę: "W ciągu ostatnich 30 dni wydałeś 45 230 EUR na 247 konwersji, co daje średni CPA 183 EUR. Trzy kwestie do uwagi: kampania 'Brand Search FR' stanowi 38% spend, ale tylko 12% konwersji (nieproporcjonalny CPA), kampania 'PMax Generic' ma CPA 412 EUR vs 145 EUR na Search Brand (wątpliwa przyrostowość), i 4 kampanie mają CTR poniżej 2%, które wymagają odświeżenia zasobów."

To audyt, który zrobiłbyś ręcznie w 30 minut, dostarczonego w 8 sekund.

Wzorzec 2 — Ad-hoc deep dive: "dlaczego CPA eksplodował wczoraj?"

Użytkownik: "CPA kampanii 'Search Generic FR' podwoił się wczoraj, co się stało?"

Claude łączy kilka wywołań tools: pull_report (CPC + CTR + wskaźnik konwersji wczoraj vs LAST_7_DAYS), ewentualnie pull_search_terms (raport zapytań), ewentualnie pull_competitor_metrics (impression share). Synteza: "Średni CPC wzrósł z 1,20 EUR do 2,45 EUR (+104%) na słowie kluczowym 'oprogramowanie CRM'. Absolutny impression share spadł z 65% do 32% (-33pp). Prawdopodobna przyczyna: nowy konkurent agresywnie licytujący. Rekomendacja: sprawdź broad match keywords dopasowujące się do generic 'CRM' i rozważ wykluczenie, aby zachować tylko phrase match + exact."

Wzorzec 3 — Cotygodniowe raportowanie: "przygotuj podsumowanie tygodnia"

Użytkownik: "Wygeneruj raport tygodnia dla moich 3 największych kampanii."

Claude wywołuje pull_report 3 razy z odpowiednimi filtrami, formatuje digest markdown, który możesz skopiować do e-maila lub Slacka. Szybciej niż skrypt do digestów, bardziej konfigurowalne niż natywne raporty Google Ads.

Wzorzec 4 — Mutacje z potwierdzeniem: "dodaj 'gratis' jako wykluczenie"

Użytkownik: "Dodaj 'gratis' jako wykluczenie do kampanii 'Search Premium B2B'."

Claude wywołuje add_negative_keyword z krokiem potwierdzenia: "Zamierzam dodać 'gratis' jako phrase match wykluczenie na poziomie kampanii 'Search Premium B2B' (ID 12345). Potwierdzić?" Po odpowiedzi twierdzącej, narzędzie wykonuje mutację i zwraca resource_name. Workflow szybszy niż nawigacja w UI Google Ads, bardziej kontrolowany niż automatyczny skrypt.

Wzorzec 5 — Synteza cross-account (multi-konto)

Użytkownik: "Porównaj wyniki moich kont polska i UK w tym miesiącu."

Claude wywołuje get_account_audit dwa razy (jeden per customer_id), syntezuje różnice: "Konto PL wydaje 1,8x więcej niż UK na 1,4x więcej konwersji, co daje CPA wyższy o 28% po stronie PL. Delta CPA wyjaśnia się głównie wyższym średnim CPC na PL (+34%) spowodowanym lokalną konkurencją, częściowo skompensowanym lepszym CTR (+8pp)."

Dla agencji audytującej 10+ kont, to zmiana zasad gry.

Poza pięcioma wzorcami powyżej, zaawansowane użycie polega na łączeniu kilku serwerów MCP w tej samej rozmowie. Instalujesz równolegle serwer MCP Google Ads, serwer MCP GA4 (analytics), serwer MCP BigQuery i serwer MCP Slack. Claude może wtedy łączyć: pobierz dane Google Ads, skrzyżuj z zdarzeniami GA4, agreguj w BigQuery i opublikuj digest na Slacku — wszystko w języku naturalnym. Według obserwowanych branż, wzorzec multi-serwer adopcji odbywa się raczej w zespołach growth, które już dojrzały swój stack analityczny; wymaga dyscypliny nazewnictwa tools (unikanie kolizji między serwerami) i czujności dotyczącej uprawnień (każdy serwer ma własne credentials, więc zakres autoryzacji pozostaje szczelny między serwerami).

Kluczowy wniosek :

W benchmarkach Google Ads, przejście na workflow MCP skraca średni czas badania anomalii z 25 minut do 4 minut (wewnętrzny pomiar na panelu dobrowolnych PPC managerów Q1 2026). To jeden z najbardziej gwałtownych skoków produktywności obserwowanych w ciągu ostatnich 5 lat, porównywalny z przejściem z Excel na SQL dla analityków danych.

Obecne ograniczenia i roadmapa MCP

MCP w Q1 2026 pozostaje młodym protokołem (15 miesięcy po specyfikacji Anthropic), z budującym się ekosystemem i udokumentowanymi lukami funkcjonalnymi. Protokół wyróżnia się w synchronicznym wzorcu konwersacyjnym (człowiek zadaje pytanie, LLM wywołuje tools, serwer odpowiada), ale pozostaje ograniczony w wzorcach asynchronicznych, multi-agent lub wsadowych. Według obserwowanych branż, adopcja MCP w PPC pozostaje skupiona na technicznych power users; dyfuzja do ni技echnicznych PPC managerów poczeka na warstwę abstrakcji instalacja-w-1-klik. Pięć poniższych ograniczeń należy znać przed wdrożeniem warstwy MCP do produkcji.

Ograniczenie 1 — Brak schedulera. Serwer MCP nie może działać jako cron. Wykonuje kod tylko gdy Claude Desktop go wywołuje. Dla cyklicznych automatyzacji (alerty co godzinę, raporty dziennie), trzeba łączyć MCP + zewnętrzny cron (niezależny skrypt Python wysyłający wnioski przez webhook). Zob. nasz przewodnik n8n Google Ads dla automatyzacji cron.

Ograniczenie 2 — Brak bogatego UI. Claude Desktop wyświetla tekst i markdown. Dla wykresu, interaktywnej tabeli, drag-drop, MCP nie jest odpowiednim medium. Tylko przypadki użycia text-first.

Ograniczenie 3 — Skumulowane opóźnienie. Każde wywołanie narzędzia dodaje ~500ms-2s opóźnienia (myślenie LLM + wykonanie narzędzia + synteza LLM). Łańcuch 5 wywołań tools = 5-10 sekund oczekiwania. Dla PPC managera przyzwyczajonego do natychmiastowych dashboardów, to zmiana tempa.

Ograniczenie 4 — Zbyt wiele tools = zły wybór LLM. Powyżej 12-15 tools w tym samym serwerze, Claude zaczyna wahać się przy wyborze właściwego narzędzia. Podziel na kilka tematycznych serwerów MCP.

Ograniczenie 5 — Brak natywnych operacji wsadowych. Jedno wywołanie narzędzia = jedna operacja. Dla 1 000 mutacji, wykonanie 1 000 wywołań tools jest niewykonalne. Zachowaj masowe operacje po stronie samodzielnych skryptów, eksponuj przez MCP tylko unitarne akcje.

Roadmapa MCP (ogłoszona przez Anthropic w Q4 2025) przewiduje na 2026: natywne wsparcie schedulingu po stronie MCP (aby wyeliminować ograniczenie 1), lepiej zindeksowany oficjalny directory z ocenami (jakość serwerów), dojrzalsze transporty HTTP/SSE dla teamowych setupów, i warstwę obserwowalności (telemetria wywołań tools, UI debugowania). Śledź oficjalną dokumentację MCP dla aktualizacji.

Dla kont chcących uprzemysłowić sterowanie Google Ads z zarządzaną warstwą AI (bez kodowania własnego serwera MCP), nasz moduł Auto-optymalizacji pokrywa przypadki użycia audytu, monitoringu i alertów w trybie zarządzanym z dedykowanym UI — zob. też naszą checklistę audytu Google Ads dla bazy audytowej, która powinna poprzedzać każdą warstwę AI. Dla pozostałych elementów puzzla automatyzacji, zob. nasz przewodnik setup API Python i nasz przewodnik n8n flows.

Dla oficjalnych zasobów MCP, zob. modelcontextprotocol.io (specyfikacja protokołu) i dokumentację Claude MCP (przewodniki Anthropic).

Źródła

Oficjalne źródła wykorzystane w tym przewodniku:

FAQ

Czym dokładnie jest MCP i kto go stworzył?

MCP (Model Context Protocol) to protokół open-source opublikowany przez Anthropic w listopadzie 2024 (oficjalny link: modelcontextprotocol.io) w celu standaryzacji sposobu, w jaki LLM wchodzą w interakcje z zewnętrznymi źródłami danych i narzędziami. Pomyśl o nim jak o odpowiedniku LSP (Language Server Protocol) dla IDE: protokół klient-serwer, gdzie klientem jest LLM (Claude Desktop, Claude Code, Cursor, itp.), a serwer eksponuje zasoby, prompty i tools przez standaryzowany interfejs. LLM może wtedy czytać i wywoływać te tools bez konieczności kodowania specyficznej integracji. Dla Google Ads oznacza to: jeden serwer MCP Google Ads napisany raz, używalny ze wszystkich klientów MCP, które pojawią się w 2025-2026.

MCP vs Function Calling Anthropic API: różnica?

Function Calling (tool use) to funkcja po stronie API: definiujesz tools w żądaniu API i Claude decyduje, czy je wywołać. Używane do budowania własnej aplikacji z własną logiką tools. MCP to protokół rozszerzenia, który pozwala Claude Desktop (aplikacji desktopowej) odkrywać i wywoływać zewnętrzne serwery instalowane lokalnie. Różnica: Function Calling = budujesz aplikację, MCP = instalujesz rozszerzenia do Claude Desktop. MCP używa Function Calling pod spodem, ale dodaje warstwę discovery, sandboxing, konfiguracji użytkownika. Dla PPC managera, który chce po prostu użyć Claude Desktop do sterowania Google Ads, MCP jest właściwą drogą. Dla dewelopera budującego produkt, bezpośredni Function Calling przez SDK pozostaje opcją.

Czy serwer MCP działa lokalnie czy w chmurze?

Obie opcje istnieją. Lokalny (transport stdio): serwer działa na Twojej maszynie, Claude Desktop uruchamia go jako subprocess przez stdin/stdout. Brak opóźnień sieciowych, credentials bezpieczne lokalnie, idealne do użytku indywidualnego. Chmurowy (transport HTTP/SSE): serwer działa na zdalnym serwerze, Claude Desktop łączy się z nim przez HTTP z uwierzytelnianiem. Niezbędny dla zespołów współdzielących konto Google Ads, lub dla serwerów wymagających kosztownych zasobów (bazy danych, inferencja ML). Dla indywidualnego PPC managera, tryb stdio lokalny jest w pełni wystarczający i prostszy w konfiguracji. Dla agencji chcącej udostępnić serwer MCP 10+ analitykom, tryb HTTP/SSE z uwierzytelnianiem staje się istotny.

Ile tools może eksponować serwer MCP Google Ads?

Brak ścisłego limitu technicznego po stronie MCP — możesz eksponować 50 tools, jeśli chcesz. Praktyczny limit leży po stronie LLM: Claude musi wybrać właściwe narzędzie przy każdej interakcji, a im więcej tools, tym większe ryzyko złego wyboru. Obserwowany sweet spot w publicznych benchmarkach: 6-12 dobrze nazwanych i udokumentowanych tools na serwer, skupionych na krytycznych przypadkach użycia. Powyżej tej liczby, lepiej podzielić na kilka tematycznych serwerów MCP (audit-server, mutation-server, reporting-server). Każde narzędzie musi mieć jasny opis w mniej niż 200 znakach, typowane parametry JSON Schema i idealnie przykład użycia.

Jakie bezpieczeństwo przy eksponowaniu credentials Google Ads przez MCP?

Trzy poziomy ochrony. Pierwszy: credentials (developer_token, refresh_token) nigdy nie opuszczają Twojej maszyny w trybie stdio lokalnym — Claude Desktop widzi tylko eksponowane tools, nie wewnętrzną zawartość serwera. Drugi: serwer MCP musi walidować każdą mutację (dodanie wykluczenia, wstrzymanie kampanii) z potwierdzeniem po stronie LLM przed wykonaniem, nigdy w ciszy. Trzeci: implementować tryb read-only domyślnie i włączać mutacje tylko przez jawną flagę (env var WRITE_MODE=true). Na produkcyjnych serwerach MCP Google Ads, które wdrażamy, dominujący wzorzec to: 80% tools read-only (search, audit, report), 20% tools mutacji z obowiązkowym potwierdzeniem użytkownika. NIGDY nie eksponuj narzędzia 'delete_campaign' ani 'pause_all_campaigns' bez zabezpieczenia.

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