Codelab: Spanner MCP サーバー

1. 概要

この Codelab では、gemini-cli と Google の Model Context Protocol(MCP) サーバーを使用して Spanner でグラフクエリを発行する方法について説明します。Spanner Graph を含む Spanner のマルチモデル データベースをマネージド MCP サービスと統合することで、複雑な GQL(Graph Query Language)または SQL クエリを手動で作成することなく、1 つのデータベースで、不正行為の輪やサプライ チェーンの依存関係など、データに隠された関係を自然言語で明らかにできます。

43e1993ca796652e.png

学習内容

  • MCP 用に Spanner Graph を含む Spanner マルチモデル データベースを設定する方法。
  • Gemini CLI をマネージド リモート Spanner サービス エンドポイントに接続する方法。
  • 自然言語を使用して、GQL と統合された SQL を自動的に生成し、リレーショナル オペレーションとともにグラフ トラバーサルとパターン マッチングを実行する方法。
  • AI ワークフローでグラフデータを保護するためのベスト プラクティス。

前提条件

  • 課金が有効な Google Cloud プロジェクトが用意されていること。
  • ターミナル(Cloud Shell など)にアクセスできること。この Codelab をご覧ください。
  • gcloud CLI がインストールされ、認証されていること。
  • Gemini CLI にアクセスできること。

注: すべてのコマンドは Unix ターミナルで実行します。適切な認証で gcloud にアクセスできるターミナルにアクセスするには、上記の前提条件をご覧ください。

2. Spanner マルチモデル環境を設定する

マネージド MCP は、データベース スキーマが事前に定義されている場合に最適に機能します。Spanner Graph のサンプルに基づいて、金融の「不正行為検出」グラフを作成します。

API を有効にする

export PROJECT_ID="YOUR_PROJECT_ID"
gcloud config set project ${PROJECT_ID}

# Enable Spanner's MCP endpoint
gcloud beta services mcp enable spanner.googleapis.com --project=${PROJECT_ID}

データベース スキーマを作成する

データベース テーブルとプロパティ グラフを使用して、インスタンスとデータベースを作成します。このスキーマは、アカウント人物 、それらの間の転送 を追跡します。

注: これらの DDL ステートメントは Spanner Studio から実行できます。GCP コンソールから Spanner データベースを作成してクエリを実行する方法については、こちらの リンク をご覧ください。

CREATE TABLE Account (
  id INT64 NOT NULL,
  create_time TIMESTAMP,
  is_blocked BOOL,
  nick_name STRING(MAX),
) PRIMARY KEY(id);

CREATE TABLE Person (
  id INT64 NOT NULL,
  name STRING(MAX),
  birthday TIMESTAMP,
  country STRING(MAX),
  city STRING(MAX),
) PRIMARY KEY(id);

CREATE TABLE AccountTransferAccount (
  id INT64 NOT NULL,
  to_id INT64 NOT NULL,
  amount FLOAT64,
  create_time TIMESTAMP NOT NULL,
  order_number STRING(MAX),
  FOREIGN KEY(to_id) REFERENCES Account(id),
) PRIMARY KEY(id, to_id, create_time),
  INTERLEAVE IN PARENT Account ON DELETE CASCADE;

CREATE TABLE PersonOwnAccount (
  id INT64 NOT NULL,
  account_id INT64 NOT NULL,
  create_time TIMESTAMP,
  FOREIGN KEY(account_id) REFERENCES Account(id),
) PRIMARY KEY(id, account_id),
  INTERLEAVE IN PARENT Person ON DELETE CASCADE;

CREATE PROPERTY GRAPH FinGraph
  NODE TABLES(
    Account
      KEY(id)
      LABEL Account PROPERTIES(
        create_time,
        id,
        is_blocked,
        nick_name),

    Person
      KEY(id)
      LABEL Person PROPERTIES(
        birthday,
        city,
        country,
        id,
        name)
  )
  EDGE TABLES(
    AccountTransferAccount
      KEY(id, to_id, create_time)
      SOURCE KEY(id) REFERENCES Account(id)
      DESTINATION KEY(to_id) REFERENCES Account(id)
      LABEL Transfers PROPERTIES(
        amount,
        create_time,
        id,
        order_number,
        to_id),

    PersonOwnAccount
      KEY(id, account_id)
      SOURCE KEY(id) REFERENCES Person(id)
      DESTINATION KEY(account_id) REFERENCES Account(id)
      LABEL Owns PROPERTIES(
        account_id,
        create_time,
        id)
  );

データを入力する

人物を挿入する

INSERT INTO Person (id, name, birthday, country, city) VALUES
(1, 'Alex', '1990-01-01T00:00:00Z', 'USA', 'New York'),
(2, 'Lee', '1985-05-15T00:00:00Z', 'USA', 'San Francisco'),
(3, 'Dana', '1995-08-20T00:00:00Z', 'Canada', 'Vancouver'),
(4, 'Maria', '1992-04-15T00:00:00Z', 'USA', 'Chicago'),
(5, 'David', '1988-11-20T00:00:00Z', 'Canada', 'Toronto');

アカウントを挿入する

INSERT INTO Account (id, create_time, is_blocked, nick_name) VALUES
(7, '2020-01-10T14:22:20.222Z', false, 'Vacation Fund'),
(16, '2020-01-28T01:55:09.206Z', true, 'Vacation Fund'),
(20, '2020-02-18T13:44:20.655Z', false, 'Rainy Day Fund'),
(25, '2023-01-15T10:00:00Z', false, 'Savings'),
(30, '2023-02-20T11:00:00Z', false, 'Checking');
INSERT INTO PersonOwnAccount (id, account_id, create_time) VALUES
(1, 7, '2020-01-10T14:22:20.222Z'),
(2, 16, '2020-01-28T01:55:09.206Z'),
(3, 20, '2020-02-18T13:44:20.655Z'),
(4, 25, '2023-01-15T10:00:00Z'),
(5, 30, '2023-02-20T11:00:00Z');

転送を追加する

INSERT INTO AccountTransferAccount (id, to_id, amount, create_time, order_number) VALUES
(7, 16, 300, '2024-02-28T10:00:00Z', 'ORD123'),
(7, 16, 100, '2024-02-29T11:00:00Z', 'ORD124'),
(16, 20, 300, '2024-02-29T12:00:00Z', 'ORD125'),
(20, 7, 500, '2024-02-29T13:00:00Z', 'ORD126'),
(20, 16, 200, '2024-02-29T14:00:00Z', 'ORD127'),
(7, 25, 150.75, '2024-03-01T12:00:00Z', 'ORD456'),
(25, 30, 200.00, '2024-03-02T14:30:00Z', 'ORD457'),
(30, 16, 50.25, '2024-03-03T16:00:00Z', 'ORD458');

3. Gemini CLI と Spanner MCP を構成する

このラボは、Gemini CLI をメイン エージェントとして使用してほとんどのアクションを実行するように設計されています。最初の手順は、リモート Spanner MCP サーバーと連携するように構成することです。また、Gemini CLI の最新バージョンと、Gemini-3-pro や Gemini-3-flash(現在プレビュー版)などの Gemini の最新バージョンを使用することを強くおすすめします。

Gemini CLI の最新バージョンがすでにインストールされていて、最新の Gemini モデルを使用するように構成されている場合は、次の 2 つの手順をスキップして、手順 3 に直接進んでください。

Gemini API キーを取得する

Gemini CLI で最新の Gemini モデルを使用するには、API キー認証で構成する必要があります。API キーは、Google AI Studio で取得できます。

  1. ブラウザで Google AI Studio に移動し、API キーを取得します。
  2. 画面の右側にある [Create API key(API キーを作成)] ボタンをクリックします。
  3. ポップアップ ウィンドウで、プロジェクトを選択するか、表示されていない場合はインポートします。

4072657f24158cbe.png

  1. API キーを作成します。
  2. 右側のコピーボタンを使用してキーをコピーできます。

a9a9a1bddb81ae21.png

キーが準備できたので、Gemini CLI で使用できます。

Gemini CLI を構成する

Gemini CLI は、設定構成ファイルを使用して構成することも、/settings コマンドを使用してインタラクティブに構成することもできます。設定は設定ファイルに保存します。

まず、プロジェクトのディレクトリを作成します。ディレクトリに projectspannermcp という名前を付け、次のコマンドを使用してそのディレクトリに切り替えます。

mkdir ~/projectspannermcp
cd ~/projectspannermcp

このディレクトリに、Gemini 構成ファイルのディレクトリを作成し、すべてのコマンドを実行します。Gemini CLI はデフォルトで、ユーザー スコープの構成ファイルと ~/.gemini ディレクトリにインストールされている拡張機能を使用します。ただし、~/projectspannermcp ディレクトリに独自のプロジェクト スコープ構成を作成します。まず、構成ディレクトリとファイルを作成します。

mkdir ~/projectspannermcp/.gemini
touch ~/projectspannermcp/.gemini/settings.json

次に、Cloud Shell エディタを使用して ~/projectspannermcp/.gemini/settings.json ファイルを開きます。

edit ~/projectspannermcp/.gemini/settings.json

開いたエディタ ウィンドウに次の構成を追加します。

{
  "general": {
    "preferredEditor": "vscode",
    "previewFeatures": true,
    "sessionRetention": {
      "enabled": true
    }
  },
  "ide": {
    "enabled": true,
    "hasSeenNudge": true
  },
  "security": {
    "auth": {
      "selectedType": "gemini-api-key"
    }
  },
  "ui": {
    "theme": "Default"
  },
  "tools": {
    "shell": {
      "enableInteractiveShell": false
    }
  }
}

ファイルを編集したら、ctrl+s を使用して変更を保存し、[Open Terminal(ターミナルを開く)] ボタンをクリックしてターミナルに戻ります。

b4d9fc5b7a8bc7b7.png

上記の設定ファイルでは、Gemini CLI の認証タイプが gemini-api-key に設定されています。モデルにキーを指定する必要があります。これを行うには、Gemini CLI で使用するディレクトリに .env ファイルを作成し、Gemini CLI 認証用の API キーを環境変数として保存します。この環境変数は、IDE の起動時に取得されます。

Cloud Shell エディタを使用してファイルを編集します。

edit ~/projectspannermcp/.env

上記の「Gemini API キーを取得する」の手順で作成した API キーを保存します。

GEMINI_API_KEY= <YOUR_API_KEY>

ターミナルに戻って続行できます。次のステップでは、Gemini CLI を最新バージョンに更新します。Google Cloud Shell または環境のバージョンが古く、最新の構成と MCP サービスで正しく動作しない可能性があります。そのため、Gemini CLI を最新バージョンに更新して起動することが重要です。ターミナルで次のコマンドを実行します。

cd ~/projectspannermcp/
npm install -g @google/gemini-cli@latest

これで、バージョンを確認できます。Google Cloud Shell で作業している場合は、シェルを再起動するたびに以前のバージョンに戻る可能性があることに注意してください。Gemini CLI 自体に対する変更は、Cloud Shell では永続的ではありません。

gemini --version

最新の Gemini CLI バージョン(このラボの作成時点ではバージョン 0.27)が表示されます。最新の Gemini CLI バージョンはこちらで確認できます。これで起動して、最新の Gemini モデルを使用していることを確認できます。プロジェクト フォルダで次のコマンドを実行して、Gemini CLI を起動します。

gemini

Gemini CLI が起動したら、インターフェースで /about コマンドを実行して、バージョンとモデルを確認できます。次のような結果が表示されます。

af2be742dd0a5bc1.png

最新の Gemini-3 モデルを使用していることがわかります。自然言語クエリを示す以下の手順では、Gemini-3 モデルを使用する必要があります。

Spanner MCP を使用するように Gemini CLI を構成する

settings.json ファイルに追加するものがもう 1 つあります。まず、gemini cli を終了します(Ctrl+C キーを 2 回押します)。

上記と同じ settings.json に、Spanner MCP サーバーを構成するビットを追加します。以下に、完全な settings.json を示します。"mcpServers" で始まるビットに注意してください。

{
 "general": {
   "preferredEditor": "vscode",
   "previewFeatures": true,
   "sessionRetention": {
     "enabled": true
   }
 },
 "ide": {
   "enabled": true,
   "hasSeenNudge": true
 },
 "security": {
   "auth": {
     "selectedType": "gemini-api-key"
   }
 },
 "ui": {
   "theme": "Default"
 },
 "tools": {
   "shell": {
     "enableInteractiveShell": false
   }
 },
 "mcpServers": {
   "spanner": {
     "httpUrl": "https://spanner.googleapis.com/mcp",
     "authProviderType": "google_credentials",
     "oauth": {
       "scopes": ["https://www.googleapis.com/auth/spanner.admin",
                  "https://www.googleapis.com/auth/spanner.data"]
     },
     "timeout": 5000
   }
 },
 "mcp": {
   "allowed": [
     "spanner"
   ]
 }
}

次のステップに進む前に、認証を行います。

gcloud auth application-default login

認証後、gemini-cli を再度起動します。

gemini

4. グラフに焦点を当てたクエリを含むマルチモデルを生成する

まず、構成済みのプロジェクトの Spanner インスタンスを一覧表示します。

「プロジェクト <project1> のすべての Spanner インスタンスを一覧表示してください(実際のプロジェクト ID に置き換えてください)」

対応:

The Spanner instances in your project are:
 [instance1]

「<instance1> のすべてのデータベースを一覧表示してください(実際のインスタンスに置き換えてください)」

対応:

The Spanner databases in [instance1] are:
  [database1]

次に、Spanner の設定セクションで DDL ステートメントと挿入ステートメントを実行したインスタンス/データベースを記憶するように gemini に指示します。

「特に指定がない限り、すべてのクエリはインスタンス <your-instance> の db <your-db> に対して送信されるものとします」

NOTE: 上記の DDL ステートメントと挿入ステートメントを実行したインスタンス/データベースを使用してください

接続すると、Gemini モデルはグラフ スキーマを理解します。自然言語を使用して高度なトラバーサルを実行できるようになりました。

モデルはこれらを GQL(Graph Query Language)に自動的に変換します。

ネットワーク構造を特定する

「‘FinGraph' プロパティ グラフの構造を説明してください。ノードラベルとエッジラベルは何ですか?」

対応:

  Node Labels
   * `Account`: Represents financial accounts.
       * Properties: id, create_time, is_blocked, nick_name
   * `Person`: Represents individuals.
       * Properties: id, name, birthday, country, city

  Edge Labels
   * `Transfers`: Represents a transfer between two Account nodes.
       * Source: Account
       * Destination: Account
       * Properties: id, to_id, amount, create_time, order_number
   * `Owns`: Represents a Person owning an Account.
       * Source: Person
       * Destination: Account
       * Properties: id, account_id, create_time

不正行為とサイクルの検出

「アカウント A から送金され、3 ホップ以内にアカウント A に戻った循環送金を見つけてください。」

対応:

The analysis confirms the following circular transfers where money returns to the originating account within 3 hops:

  3-Hop Cycles
  Money travels through two intermediate accounts before returning to the origin.
   * Account 16 (Involved in multiple 3-hop paths)
   * Account 20 (Involved in multiple 3-hop paths)
   * Account 7 (Involved in multiple 3-hop paths)

These accounts are participating in circular flow patterns of varying lengths.

詳細な関係分析

「過去 24 か月間に、異なる人物が所有するアカウントに 499 ドル以上を送金したアカウントを所有するすべての人物を特定してください。」

対応:

Dana is the only person who owns an account that has sent more than $499 to an account owned by a different person in the last 24 months.

(Specifically, her account sent exactly $500, which is the maximum transfer amount in the database).

経路探索

「アカウント ID 16 とアカウント ID 20 の間の転送の最短パスを見つけてください。」

対応:

The shortest path between Account 16 and Account 20 is 1 hop.

This means there is a direct transfer from Account 16 to Account 20.

5. 完了

以上で、この Codelab は完了です。

学習した内容

この Codelab では、Spanner MCP サーバーで gemini-cli を構成し、Spanner Graph データに対して自然言語クエリを発行して分析情報を取得する方法について説明しました。主なマイルストーンの概要は次のとおりです。

  • マネージド インフラストラクチャ: リモート Spanner MCP サーバーを有効にし、ローカル プロキシや MCP ツールボックスが不要になりました。
  • グラフの統合: ノードとエッジを使用して複雑な関係を表す Spanner プロパティ グラフ(FinGraph)を構成しました。
  • ネイティブ ツール: 標準の URI スキームを使用して、Gemini CLI をマネージド Spanner エンドポイントに直接接続しました。
  • 自然言語 SQL と GQL: グラフ固有のプロンプトでサーバーを操作し、LLM が手動で SQL/GQL コーディングを行わずにマルチホップ トラバーサルとサイクル検出を実行できるようにしました。
  • エンタープライズ対応: マネージド MCP が、AI エージェントが運用データとやり取りするためのスケーラブルで認証されたパスを提供する方法について説明しました。