AI Agents Analytics

Google AnalyticsのMCPサーバーを作る方法

Alejandro Rioja
Alejandro Rioja
2 分で読める
TL;DR

まずはGoogle公式のGA4用MCPサーバーを試してください。試験運用版で、Pythonでローカル実行し、自分のパソコンでGA4を扱う用途ならこれで足ります。自作する場合は、MCPのTypeScript SDKと@google-analytics/dataでrun_reportツールを1つ書き、gcloudとanalytics.readonlyスコープでログインし、claude mcp addで登録します。難しいのは他の人向けにホスティングする段階です。MCPのOAuthフロー、機密性の高いスコープに対するGoogleの確認(未確認アプリは100ユーザーまで)、そしてData APIのプロパティ単位の割り当てに収めるためのキャッシュが必要になります。

無料ニュースレター

毎週水曜。28,400人以上の読者。無駄なし。

自分のノートパソコンで動くGA4用MCPサーバーなら、午後いっぱいあれば作れます。他の人がログインして使えるサーバーとなると、ずっと大きな仕事です。このガイドでは午後で作れる版を紹介し、そのあと大きな版に何が必要かを並べます。どちらが必要か判断してください。

目次

目次を開く

まず公式サーバーを確認する

Googleは独自のGoogle Analytics MCPサーバーを公開していますが、まだ試験運用版の扱いです。自分のパソコン上でPythonで動き、使う前にGoogle CloudプロジェクトでGoogle Analytics Admin APIとData APIを有効にする必要があります。run_report、run_realtime_report、run_funnel_reportのほか、アカウント、プロパティ、カスタムディメンション、Google広告とのリンクを調べるツールが最初から揃っています。GA4だけを、自分のパソコンだけで使うならこれで十分です。

bash
gcloud auth application-default login \
  --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform \
  --client-id-file=YOUR_CLIENT_JSON_FILE

pipx run analytics-mcp

GoogleのセットアップページでCloudプロジェクトの準備を順に説明しており、READMEにはClaude Code用のclaude mcp addの正確なコマンドも載っています。ホスティング版はないので、Pythonを実行できる環境でしか使えません。

自分の質問に合わせたツールが欲しいとき、複数のデータソースを1つの回答にまとめたいとき、チームやクライアントにも使ってもらいたいときは、自作しましょう。

必要なもの

  • Google Analytics Data APIを有効にしたGoogle Cloudプロジェクト(5分で済みます)。
  • そのプロジェクトで作成した、デスクトップアプリ用のOAuthクライアントID(JSONでダウンロード)。--client-id-fileで指定するのがこのファイルです。
  • Node 22以降。現行の@google-analytics/dataパッケージがこれを必要とします。
  • ログインに使うGoogleアカウントに、GA4プロパティの閲覧者権限。

ステップ1:どんなレポートでも実行できるツールを1つ作る

まずはrun_reportというツールを1つだけ作ります。ClaudeはGA4の指標名やディメンション名をすでに知っているので、柔軟なツールが1つあればほとんどの質問に対応できます。実際にどんな質問をするかが見えてきたら、もっと用途を絞ったツールに分けましょう。

フォルダを用意して、一度だけログインします。2つ目のgcloudコマンドは省略しないでください。GoogleのAnalytics APIは、割り当てプロジェクトが指定されていないユーザー認証情報を受け付けません。

bash
mkdir ga4-mcp && cd ga4-mcp
npm init -y && npm pkg set type=module
npm install @modelcontextprotocol/sdk @google-analytics/data zod

gcloud auth application-default login \
  --scopes https://www.googleapis.com/auth/analytics.readonly,https://www.googleapis.com/auth/cloud-platform \
  --client-id-file=YOUR_CLIENT_JSON_FILE
gcloud auth application-default set-quota-project YOUR_PROJECT_ID

次に、これをga4.tsとして保存します。

typescript
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { BetaAnalyticsDataClient } from '@google-analytics/data';
import { z } from 'zod';

const ga = new BetaAnalyticsDataClient(); // Application Default Credentials
const server = new McpServer({ name: 'ga4', version: '1.0.0' });

server.registerTool(
  'run_report',
  {
    description:
      'Run a GA4 report. Uses GA4 Data API metric and dimension names. ' +
      'Dates accept YYYY-MM-DD, "28daysAgo", "yesterday", "today".',
    inputSchema: {
      propertyId: z.string().describe('Numeric GA4 property ID, e.g. 123456789'),
      metrics: z.array(z.string()).describe('e.g. ["sessions", "engagedSessions"]'),
      dimensions: z.array(z.string()).default([]).describe('e.g. ["sessionDefaultChannelGroup"]'),
      startDate: z.string().default('28daysAgo'),
      endDate: z.string().default('today'),
    },
  },
  async ({ propertyId, metrics, dimensions, startDate, endDate }) => {
    const [res] = await ga.runReport({
      property: `properties/${propertyId}`,
      dateRanges: [{ startDate, endDate }],
      metrics: metrics.map((name) => ({ name })),
      dimensions: dimensions.map((name) => ({ name })),
      limit: 100,
    });
    // Turn GA's nested rows into plain { dimension: value, metric: value } objects.
    const rows = (res.rows ?? []).map((row) => {
      const out: Record<string, string> = {};
      row.dimensionValues?.forEach((v, i) => (out[dimensions[i]] = v.value ?? ''));
      row.metricValues?.forEach((v, i) => (out[metrics[i]] = v.value ?? ''));
      return out;
    });
    return { content: [{ type: 'text', text: JSON.stringify({ rowCount: res.rowCount, rows }) }] };
  },
);

await server.connect(new StdioServerTransport());

ファイルにキーは一切含まれていません。クライアントはgcloudが保存したばかりのログイン情報を使い、すべての呼び出しはあなた自身として、あなたの閲覧者権限で実行されます。

ステップ2:Claudeに追加する

Claude Codeなら、コマンド1つで登録できます。ファイルはフルパスで指定してください。--scope userを付けるとすべてのプロジェクトで使えます。付けない場合は、コマンドを実行したフォルダでしか読み込まれません。

bash
claude mcp add --scope user ga4 -- npx -y tsx /full/path/to/ga4-mcp/ga4.ts

あとは「プロパティ123456789で、先月エンゲージのあったセッションが最も多かったチャネルはどれ?」と聞くだけです。Claudeが指標を選び、ツールを呼び出し、結果の行を説明してくれます。Claude Desktopの場合は同じサーバーを設定ファイルに書きます。場所は初めてのMCPサーバーの作り方で説明しています。

ステップ3:難しくなるところ

ここまではすべて、あなた自身として、あなたのパソコン上で動いています。それ以外の場所で動かす必要が出てくると、次の点が変わります。

  1. ホスティングとOAuth。 claude.aiやモバイルアプリからは、ノートパソコン上のサーバーにアクセスできません。ホスティングするサーバーには、各ユーザーが自分のGoogleアカウントでログインできるようにMCPのOAuthフローが必要で、さらにユーザーのリフレッシュトークンを安全に保管する場所も要ります。
  2. Googleのアプリ確認。 analytics.readonlyは機密性の高いスコープです。Googleがアプリを確認するまで、すべてのユーザーに「未確認のアプリ」という警告が表示され、ユーザー数は100人までに制限されます。確認には、自分のドメイン上のプライバシーポリシー、ログイン手順のデモ動画、スコープごとの書面での理由説明、そして審査が必要です。
  3. 割り当て。 Data APIはプロパティごとにトークンを計測します。標準プロパティでは1時間あたり40,000、1日あたり200,000で、1つのCloudプロジェクトが使えるのはプロパティごとに1時間あたり最大14,000、同時リクエストは10件までです。ほとんどのリクエストは10トークン以下ですが、期間が長い、ディメンションが多い、トラフィックの多いプロパティといった条件ではコストが上がります。しかもエージェントは、GA4の画面をクリックする人よりはるかに速くレポートを投げます。ホスティングすると、すべての呼び出しがあなたのプロジェクトの枠から引かれます。returnPropertyQuota: trueを付けて各リクエストのコストを確認し、繰り返し使う結果はキャッシュし、レポートは小さく保ちましょう。

SiteWideはホスティングとログインを引き受けます。Googleによる確認はまだ手続き中なので、今のところSiteWideでもGA4には同じ未確認アプリの画面が表示されます。こうした作業を自分でやりたくないなら、SiteWideを接続してください。

Claudeに作らせる

空のフォルダでClaude Codeを開き、これを貼り付けてください。コードが英語なので、プロンプトも英語のままにしています。

code
Build me a TypeScript MCP server for Google Analytics 4 using @modelcontextprotocol/sdk and @google-analytics/data. Give it one tool, run_report, that takes a property id, metrics, dimensions and a date range. Authenticate with Application Default Credentials. Then give me the exact gcloud command to log in with the analytics.readonly scope, and register the server with `claude mcp add`. Don't invent metric names: link me to Google's API schema page so I can check them.

結果を信用する前に、使われている指標とディメンションをすべてGoogleのAPIスキーマのページと照らし合わせてください。でっち上げられた名前はコード上では問題なく見え、APIに拒否されて初めてエラーになります。

広告
続きを読む

関連記事

続きを読む

AIプレイブックをメールでお届け

毎週水曜。28,400人以上の読者。無駄なし。

↵ ↵ すべての結果を見る esc esc で閉じる