Skip to main content
ai22 февраля 2026 г.14 мин чтения

Серверы MCP: Как сделать Google Analytics по-настоящему полезным для разработчиков

Как серверы Model Context Protocol превращают Google Analytics из маркетинговой панели в удобный для разработчиков источник данных, к которому можно обращаться в разговорном режиме.

mcpanalyticsai
Серверы MCP: Как сделать Google Analytics по-настоящему полезным для разработчиков

Google Analytics всегда был маркетинговым инструментом, который разработчики терпят. Вы настраиваете отслеживание, конфигурируете события, а затем передаете это тому, кто действительно любит просматривать дашборды. Когда вам нужны данные самостоятельно — показатели отказов для конкретной страницы, воронки конверсии для новой функции, активные пользователи в реальном времени, сегментированные по странам — вы в конечном итоге прокликиваете пять вложенных меню, боретесь с конструктором запросов GA4 и задаетесь вопросом, почему задать вопрос требует больше усилий, чем ответить на него.

Model Context Protocol полностью меняет это. Обернув Reporting API GA4 в MCP-сервер, вы можете запрашивать свои аналитические данные в разговорном режиме через Claude или любого MCP-совместимого AI-помощника. Никаких дашбордов. Никаких конструкторов запросов. Просто спросите, что вы хотите узнать.

Что такое MCP и почему это важно

Model Context Protocol — это открытый стандарт, созданный Anthropic, который определяет, как AI-помощники взаимодействуют с внешними источниками данных и инструментами. Думайте об этом как о порте USB-C для AI — универсальном интерфейсе, который позволяет любому совместимому помощнику подключаться к любому совместимому источнику данных без пользовательского кода интеграции для каждой пары.

До MCP подключение AI-помощника к вашим аналитическим данным означало создание индивидуального конвейера: экспорт данных в CSV, вставка их в чат, надежда, что окно контекста достаточно велико. Или создание пользовательской интеграции API, написание шаблонов подсказок, самостоятельная обработка аутентификации. Каждый новый источник данных требовал новой интеграции.

MCP стандартизирует это в три концепции:

  • Resources (Ресурсы) — структурированные данные, которые предоставляет сервер (ваши свойства GA4, отчеты, измерения, метрики)
  • Tools (Инструменты) — действия, которые AI может вызывать (запустить отчет, запросить данные в реальном времени, перечислить доступные метрики)
  • Prompts (Подсказки) — многократно используемые шаблоны подсказок, предоставляемые сервером (общие аналитические запросы, предварительно структурированные для хороших результатов)

Сервер обрабатывает аутентификацию, получение данных и форматирование ответа. AI-помощник обрабатывает понимание естественного языка и интерпретацию результатов. Ни одна из сторон не должна знать детали реализации другой.

Почему это важно именно для аналитики

Аналитические платформы насыщены информацией, но бедны взаимодействием. GA4 обладает чрезвычайно мощными данными — он отслеживает каждую пользовательскую сессию, каждый просмотр страницы, каждое событие, каждую конверсию по всему вашему продукту. Но доступ к этим данным требует от вас мышления в терминах GA4: измерения, метрики, сегменты, диапазоны дат, фильтры, сравнения. Вы должны перевести свой вопрос в модель запросов GA4, прежде чем сможете получить ответ.

MCP-сервер инвертирует это. Вы задаете свой вопрос на простом языке. AI переводит его в правильные вызовы API, выполняет их и интерпретирует результаты. Трение между "У меня есть вопрос" и "У меня есть ответ" сокращается с минут до секунд.

Создание MCP-сервера для GA4

Реализация включает три слоя: фреймворк MCP-сервера, клиент Google Analytics Data API и логику связывания, которая сопоставляет намерение на естественном языке с вызовами API.

Настройка проекта

mkdir ga4-mcp-server
cd ga4-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk @google-analytics/data zod dotenv
npm install -D typescript @types/node

Пакет @modelcontextprotocol/sdk предоставляет фреймворк сервера. @google-analytics/data — это официальная клиентская библиотека Google для GA4 Data API (Reporting API, а не Admin API). zod обрабатывает проверку входных данных для параметров инструментов.

Аутентификация с Google

Аутентификация GA4 API использует сервисный аккаунт Google Cloud. Создайте его в Google Cloud Console, загрузите файл ключа JSON и предоставьте ему доступ "Viewer" к вашему свойству GA4.

// src/analytics-client.ts
import { BetaAnalyticsDataClient } from "@google-analytics/data";

const analyticsClient = new BetaAnalyticsDataClient({
  keyFilename: process.env.GOOGLE_APPLICATION_CREDENTIALS,
});

const propertyId = process.env.GA4_PROPERTY_ID;

export async function runReport(
  dimensions: string[],
  metrics: string[],
  startDate: string,
  endDate: string,
  dimensionFilter?: Record<string, string>
) {
  const request: any = {
    property: `properties/${propertyId}`,
    dimensions: dimensions.map((d) => ({ name: d })),
    metrics: metrics.map((m) => ({ name: m })),
    dateRanges: [{ startDate, endDate }],
  };

  if (dimensionFilter) {
    const filterKey = Object.keys(dimensionFilter)[0];
    request.dimensionFilter = {
      filter: {
        fieldName: filterKey,
        stringFilter: {
          value: dimensionFilter[filterKey],
          matchType: "EXACT",
        },
      },
    };
  }

  const [response] = await analyticsClient.runReport(request);
  return formatReportResponse(response);
}

function formatReportResponse(response: any) {
  if (!response.rows || response.rows.length === 0) {
    return { data: [], summary: "No data found for the specified query." };
  }

  const headers = [
    ...(response.dimensionHeaders?.map((h: any) => h.name) ?? []),
    ...(response.metricHeaders?.map((h: any) => h.name) ?? []),
  ];

  const rows = response.rows.map((row: any) => {
    const values = [
      ...(row.dimensionValues?.map((v: any) => v.value) ?? []),
      ...(row.metricValues?.map((v: any) => v.value) ?? []),
    ];
    return Object.fromEntries(headers.map((h, i) => [h, values[i]]));
  });

  return {
    data: rows,
    rowCount: response.rowCount,
    summary: `Returned ${rows.length} rows.`,
  };
}

MCP-сервер

// src/server.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
import { runReport, getRealtimeData, getAvailableMetrics } from "./analytics-client";

const server = new McpServer({
  name: "ga4-analytics",
  version: "1.0.0",
});

// Tool: Run a custom report
server.tool(
  "run_report",
  "Run a Google Analytics 4 report with specified dimensions, metrics, and date range",
  {
    dimensions: z.array(z.string()).describe("GA4 dimensions like 'pagePath', 'country', 'deviceCategory'"),
    metrics: z.array(z.string()).describe("GA4 metrics like 'activeUsers', 'sessions', 'bounceRate'"),
    startDate: z.string().describe("Start date in YYYY-MM-DD format or relative like '7daysAgo'"),
    endDate: z.string().describe("End date in YYYY-MM-DD format or 'today'"),
    filter: z.record(z.string()).optional().describe("Optional dimension filter as key-value pair"),
  },
  async ({ dimensions, metrics, startDate, endDate, filter }) => {
    const result = await runReport(dimensions, metrics, startDate, endDate, filter);
    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
    };
  }
);

// Tool: Get real-time active users
server.tool(
  "realtime_users",
  "Get current real-time active users, optionally segmented by a dimension",
  {
    dimension: z.string().optional().describe("Optional dimension to segment by, like 'country' or 'pagePath'"),
  },
  async ({ dimension }) => {
    const result = await getRealtimeData(dimension);
    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
    };
  }
);

// Tool: List available metrics and dimensions
server.tool(
  "list_metrics",
  "List all available GA4 metrics and dimensions for the connected property",
  {},
  async () => {
    const result = await getAvailableMetrics();
    return {
      content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
    };
  }
);

// Resource: Property metadata
server.resource(
  "property-info",
  "ga4://property/info",
  async (uri) => ({
    contents: [{
      uri: uri.href,
      mimeType: "application/json",
      text: JSON.stringify({
        propertyId: process.env.GA4_PROPERTY_ID,
        description: "Connected GA4 property for analytics queries",
      }),
    }],
  })
);

async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
}

main().catch(console.error);

Это дает AI-помощнику три инструмента: запускать произвольные отчеты, проверять данные в реальном времени и узнавать, какие метрики и измерения доступны. Инструмент обнаружения важен — он позволяет AI выяснить правильные имена полей без необходимости запоминать, является ли это activeUsers или active_users или totalUsers.

Конечная точка данных в реальном времени

// Added to analytics-client.ts
export async function getRealtimeData(dimension?: string) {
  const request: any = {
    property: `properties/${propertyId}`,
    metrics: [{ name: "activeUsers" }],
  };

  if (dimension) {
    request.dimensions = [{ name: dimension }];
  }

  const [response] = await analyticsClient.runRealtimeReport(request);
  return formatReportResponse(response);
}

Данные в реальном времени — одна из самых ценных функций. В дашборде вы перешли бы в раздел реального времени, дождались бы его загрузки и прочитали бы цифры. Через MCP вы набираете "сколько людей сейчас на сайте?" и получаете ответ за две секунды.

Реальные запросы, которые разработчики действительно хотят выполнять

Теоретические возможности скучны. Вот реальные запросы, которые я запускаю ежедневно, и как они выглядят в виде разговорных запросов к AI:

Анализ трафика

"Каковы 10 самых популярных страниц по количеству сессий на этой неделе, и как каждая из них сравнивается с прошлой неделей?"

AI переводит это в два вызова runReport — один для текущей недели, один для предыдущей недели — затем вычисляет дельту и представляет сравнительную таблицу. В интерфейсе GA4 это требует настройки диапазона дат для сравнения, выбора правильного отчета, добавления измерения страницы, сортировки по сессиям и ограничения до 10. Через MCP это одно предложение.

"Покажите мне трафик из органического поиска за последние 30 дней, разбитый по целевым страницам."

Это становится одним отчетом с sessionDefaultChannelGroup в качестве фильтра измерения (отфильтрованного по "Organic Search"), landingPagePlusQueryString в качестве измерения и sessions плюс engagedSessions в качестве метрик.

Отладка конверсии

"Каков показатель отказов на /pricing по сравнению с /features за последние две недели?"

Два вызова отфильтрованных отчетов, результаты сравниваются бок о бок. Это тот тип вопроса, на который уходит 30 секунд, чтобы задать его в разговорном режиме, и 3 минуты, чтобы ответить через интерфейс GA4.

"В каких странах самый высокий коэффициент конверсии для события регистрации?"

Один отчет с измерением country, метрикой eventCount, отфильтрованной по событию sign_up, и sessions для расчета коэффициента конверсии. AI может даже выполнить деление и представить проценты напрямую.

Мониторинг производительности

"Каково среднее время вовлеченности за сессию на мобильных устройствах по сравнению с настольными в этом месяце?"

Сегментировано по deviceCategory, измеряя averageSessionDuration и engagedSessions. Простой запрос, но тот, который требует перехода к правильному отчету и настройки сегментов в GA4.

"Есть ли страницы с более чем 1000 просмотров на этой неделе, но с уровнем вовлеченности ниже 30%?"

Вот где разговорная аналитика действительно сияет. AI запускает отчет, программно фильтрует результаты и возвращает только те страницы, которые соответствуют обоим критериям. В GA4 вам пришлось бы экспортировать данные в электронную таблицу и фильтровать вручную, или создавать пользовательское исследование.

Подключение к Claude и AI-помощникам

Конфигурация Claude Desktop

После создания вашего MCP-сервера подключение его к Claude Desktop — это редактирование файла конфигурации:

{
  "mcpServers": {
    "ga4-analytics": {
      "command": "node",
      "args": ["/path/to/ga4-mcp-server/dist/server.js"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "/path/to/service-account-key.json",
        "GA4_PROPERTY_ID": "123456789"
      }
    }
  }
}

На macOS это находится в ~/Library/Application Support/Claude/claude_desktop_config.json. На Windows это %APPDATA%\Claude\claude_desktop_config.json.

После перезапуска Claude Desktop инструменты GA4 появятся в меню инструментов. Claude теперь может вызывать их напрямую в разговоре.

Интеграция Claude Code

Для разработчиков, которые работают преимущественно в терминале, Claude Code поддерживает MCP-серверы нативно. Добавьте сервер в .mcp.json вашего проекта:

{
  "mcpServers": {
    "ga4-analytics": {
      "command": "node",
      "args": ["./mcp-servers/ga4/dist/server.js"],
      "env": {
        "GOOGLE_APPLICATION_CREDENTIALS": "./credentials/ga4-service-account.json",
        "GA4_PROPERTY_ID": "123456789"
      }
    }
  }
}

Теперь вы можете запрашивать аналитические данные, не покидая редактора. Во время отладки регрессии производительности вы можете спросить "каков показатель отказов на /checkout на этой неделе по сравнению с прошлой неделей?" без переключения контекста на браузер.

Использование с другими MCP-совместимыми клиентами

Прелесть MCP как стандарта в том, что любой совместимый клиент работает. Cursor, Windsurf и другие редакторы, поддерживающие MCP, могут подключаться к одному и тому же серверу. Вы создаете сервер один раз, и он работает везде.

Практические примеры разговорной аналитики

Позвольте мне рассказать о реальном рабочем процессе, который я регулярно использую.

Утренняя проверка

Я начинаю день, спрашивая Claude: "Дай мне сводку вчерашнего трафика — общее количество сессий, активных пользователей, 5 самых популярных страниц и любые страницы с уровнем вовлеченности ниже 25%."

AI делает три вызова инструмента: один для общих метрик, один для самых популярных страниц, один для страниц с низкой вовлеченностью. Он возвращает что-то вроде:

Вчера: 2341 сессия от 1892 уникальных пользователей. Самыми популярными страницами были /home (580 сессий), /pricing (412), /docs/getting-started (389), /blog/mcp-guide (267), /features (198). Две страницы имели вовлеченность ниже 25%: /legal/terms (12%) и /blog/old-post-2024 (22%).

Это заняло бы 5-10 минут в интерфейсе GA4. Через MCP это занимает 15 секунд.

Мониторинг запуска функции

Когда я выпускаю новую функцию, я хочу знать, находят ли ее люди и используют ли ее. "Сравните трафик на /features/new-dashboard за последние 3 дня с 3 днями до запуска, разбитый по каналам привлечения."

AI выполняет сравнение, определяет, какие каналы способствуют обнаружению (обычно прямой и органический поиск отстают от социальных сетей и рефералов в первые дни после запуска), и выделяет любые аномалии.

Отладка жалоб пользователей

Когда пользователи сообщают, что "сайт работает медленно", я могу спросить: "Каково среднее время загрузки страницы по страницам за последние 7 дней, отсортированное по самым медленным?" Если GA4 имеет данные Web Vitals (через протокол измерения или события gtag), MCP-сервер может вывести это, не открывая браузер.

Еженедельная отчетность

"Сгенерируйте сравнение по неделям сессий, новых пользователей, уровня вовлеченности и коэффициента конверсии для каждой из наших 20 самых популярных страниц."

Это создает отформатированную таблицу, которую я могу напрямую вставить в сообщение Slack или обновление команды. Никакой гимнастики с электронными таблицами, никакой обрезки скриншотов.

Создание расширенных функций

Уровень кэширования

API GA4 имеет ограничения скорости (обычно 10 запросов в минуту на свойство для бесплатного уровня). Для MCP-сервера, который может часто запрашиваться, добавьте уровень кэширования:

import { createHash } from "crypto";

const cache = new Map<string, { data: any; expiry: number }>();

function getCacheKey(dimensions: string[], metrics: string[], startDate: string, endDate: string): string {
  const input = JSON.stringify({ dimensions, metrics, startDate, endDate });
  return createHash("md5").update(input).digest("hex");
}

export async function cachedRunReport(
  dimensions: string[],
  metrics: string[],
  startDate: string,
  endDate: string
) {
  const key = getCacheKey(dimensions, metrics, startDate, endDate);
  const cached = cache.get(key);

  if (cached && cached.expiry > Date.now()) {
    return cached.data;
  }

  const result = await runReport(dimensions, metrics, startDate, endDate);

  // Cache for 5 minutes (real-time queries get shorter TTL)
  const ttl = startDate === "today" ? 60_000 : 300_000;
  cache.set(key, { data: result, expiry: Date.now() + ttl });

  return result;
}

Запросы в реальном времени получают TTL в 1 минуту. Исторические запросы получают 5 минут. Это позволяет вам оставаться в пределах ограничений скорости во время разговорной сессии, когда AI может сделать несколько связанных запросов подряд.

Поддержка нескольких свойств

Если вы управляете несколькими продуктами или клиентами, расширьте сервер для поддержки переключения между свойствами GA4:

server.tool(
  "switch_property",
  "Switch to a different GA4 property",
  {
    propertyId: z.string().describe("The GA4 property ID to switch to"),
  },
  async ({ propertyId }) => {
    // Validate access
    const properties = await listAccessibleProperties();
    if (!properties.includes(propertyId)) {
      return {
        content: [{ type: "text", text: `No access to property ${propertyId}` }],
      };
    }

    currentPropertyId = propertyId;
    return {
      content: [{ type: "text", text: `Switched to property ${propertyId}` }],
    };
  }
);

Теперь вы можете сказать "переключиться на свойство staging и показать мне вчерашний трафик", не перенастраивая ничего.

Вопросы безопасности

Запуск MCP-сервера, который получает доступ к аналитическим данным, вызывает несколько проблем безопасности, требующих преднамеренного решения.

Управление учетными данными

Файл ключа сервисного аккаунта является наиболее чувствительной частью. Никогда не коммитьте его в систему контроля версий. Используйте переменные окружения или менеджер секретов. Если вы запускаете MCP-сервер локально (что является обычным случаем для Claude Desktop), храните файл ключа вне каталога вашего проекта с ограниченными правами доступа к файлам:

chmod 600 /path/to/service-account-key.json

Для командных сред рассмотрите возможность использования Workload Identity Federation Google Cloud вместо файла ключа. Это полностью исключает статические учетные данные, используя кратковременные токены, привязанные к идентификатору среды выполнения.

Принцип наименьших привилегий

Сервисный аккаунт должен иметь доступ только для чтения к GA4. В частности, предоставьте роль "Viewer" на уровне свойства GA4 — а не роль "Editor" или "Administrator". MCP-серверу никогда не потребуется изменять вашу конфигурацию аналитики, создавать аудитории или изменять настройки измерения.

На уровне проекта Google Cloud предоставьте только область analyticsdata.readonly. Это предотвращает доступ сервисного аккаунта к любым другим службам Google Cloud, даже если ключ скомпрометирован.

Область раскрытия данных

Будьте внимательны к тому, к каким данным может получить доступ MCP-сервер. GA4 может содержать PII — идентификаторы пользователей, идентификаторы клиентов, геолокацию, полученную по IP. Ваш MCP-сервер должен удалять или маскировать поля, которые не нужны для запросов, которые вы хотите поддерживать.

const BLOCKED_DIMENSIONS = ["userID", "clientId"];

function validateDimensions(dimensions: string[]) {
  const blocked = dimensions.filter((d) => BLOCKED_DIMENSIONS.includes(d));
  if (blocked.length > 0) {
    throw new Error(`Blocked dimensions for privacy: ${blocked.join(", ")}`);
  }
}

Это особенно важно, если другие члены команды могут взаимодействовать с MCP-сервером. Вы хотите предотвратить случайные запросы, которые могут раскрыть данные отдельных пользователей.

Безопасность транспорта

MCP в настоящее время работает через stdio (стандартный ввод/вывод) при использовании с Claude Desktop, что означает, что связь происходит в пределах локальных границ процесса. Сетевого воздействия нет. Однако, если вы развертываете MCP-сервер по HTTP (используя транспорт SSE), вам потребуются TLS, токены аутентификации и ограничение скорости — относитесь к нему как к любой другой конечной точке API.

Журналирование аудита

Журналируйте каждый запрос, обрабатываемый MCP-сервером. Не только для безопасности — для подотчетности. Когда кто-то спрашивает "кто и когда запрашивал наши аналитические данные", у вас должен быть ответ.

function logQuery(tool: string, params: Record<string, unknown>) {
  console.log(JSON.stringify({
    timestamp: new Date().toISOString(),
    tool,
    params,
    propertyId: currentPropertyId,
  }));
}

Компромиссы и ограничения

Что работает хорошо

Разговорная аналитика устраняет кривую обучения GA4 для разработчиков. Вам не нужно знать имена измерений и метрик GA4, типы отчетов или синтаксис фильтров. AI обрабатывает перевод. Для специальных вопросов — тех, которые вы задаете один раз и никогда не повторяете — это значительно быстрее, чем дашборд.

Сочетание аналитики с контекстом разработки очень мощно. Когда вы отлаживаете в Claude Code и можете одновременно проверять аналитические данные, цикл обратной связи сокращается. Вы видите код, журналы ошибок и влияние на пользователя в одном месте.

Что работает не очень хорошо

Сложные исследования, требующие итеративной доработки, по-прежнему быстрее в интерфейсе GA4 Explore. Если вы строите анализ воронки с несколькими этапами, пользовательскими сегментами и группами сравнения, визуальный конструктор дает вам немедленную обратную связь, которую разговорный интерфейс не может обеспечить.

Дашборды в реальном времени, которые автоматически обновляются, находятся за пределами текущей модели MCP. MCP — это запрос-ответ: вы спрашиваете, он отвечает. Для постоянно обновляющегося дашборда, показывающего пользователей в реальном времени, лучше подходит специально созданный инструмент, такой как представление GA4 в реальном времени или пользовательская панель Grafana.

Объем данных является ограничением. GA4 Data API возвращает до 100 000 строк за запрос. Для свойств с миллионами ежедневных событий вам может потребоваться быть конкретным в отношении измерений и диапазонов дат, чтобы избежать превышения этого предела. API также имеет поведение выборки для больших наборов данных — результаты могут быть оценочными, а не точными для запросов с высокой кардинальностью.

MCP против прямой интеграции API

Если вы создаете функцию продукта, которой нужны аналитические данные (например, панель администратора для вашего SaaS), используйте GA4 API напрямую. MCP предназначен для запросов с участием человека, а не для программных конвейеров данных. Накладные расходы на перевод естественного языка и интерпретацию AI излишни, когда вы точно знаете, какой запрос нужно выполнить.

MCP сияет, когда вопрос неструктурирован, когда вы не знаете точно, что ищете, или когда усилия по созданию надлежащей интеграции не оправданы для одноразового вопроса. Это аналитический эквивалент открытия REPL вместо написания скрипта.

Начало работы

Если вы хотите попробовать это сами, минимальный путь таков:

  1. Создайте проект Google Cloud и включите Google Analytics Data API.
  2. Создайте сервисный аккаунт с доступом Viewer к вашему свойству GA4.
  3. Загрузите JSON-файл ключа сервисного аккаунта.
  4. Клонируйте или соберите MCP-сервер, как описано выше.
  5. Добавьте сервер в конфигурацию Claude Desktop или Claude Code.
  6. Начните задавать вопросы.

Вся настройка занимает около 30 минут, если у вас уже есть свойство GA4. Отдача немедленная — в первый раз, когда вы получите ответ на аналитический вопрос за 5 секунд вместо 5 минут, вы не захотите возвращаться к дашборду.

Аналитические данные — один из самых недоиспользуемых активов в большинстве команд разработчиков. Не потому, что они не ценны, а потому, что доступ к ним всегда был достаточно неудобным, чтобы препятствовать случайным запросам. MCP устраняет это трение. Данные те же. Вопросы те же. Время ответа — вот что меняется.

DU

Danil Ulmashev

Full Stack Developer

Хотите работать вместе?