Codelab: Spanner MCP サーバー

1. 概要

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

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 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 ボタンをクリックします。
  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

上記の settings.json ファイルでは、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>(実際のプロジェクト ID に置き換えてください)内のすべての Spanner インスタンスを一覧表示してください」

対応:

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.

Deep Relationship Analysis

「過去 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 エージェントが運用データとやり取りするためのスケーラブルで認証されたパスを提供する方法について説明しました。