0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Databricksからマネージド BigQuery MCPサーバーにアクセスする検証

0
Last updated at Posted at 2026-09-06

概要

本記事では、DatabricksからGoogle管理のBigQuery MCPサーバーにアクセスし、
BigQueryのデータを取得・分析できるか検証した内容を記載します。

<検証は以下の2パターンで行いました。>
検証A. Databricksノートブックから、Pythonで直接BigQuery MCPサーバーを呼び出す方法
検証B. Databricks Unity CatalogにMCP Serviceとして登録し、Playground上で自然言語からデータ分析を行う方法

Google Cloud側の準備

① テストデータの準備

まず、今回の検証で使用するBQテーブルを作成します。(今回は以下内容で作成)

空テーブル作成
CREATE OR REPLACE TABLE `TEST_DB.MCP_TEST_DATA` (
  customer_id        STRING  OPTIONS(description="顧客ID(システム内部の一意キー)"),
  kaiin_id           STRING  OPTIONS(description="会員ID"),
  card_no            STRING  OPTIONS(description="会員カード番号"),
  phone_no           STRING  OPTIONS(description="電話番号"),
  address            STRING  OPTIONS(description="住所"),
  customer_name      STRING  OPTIONS(description="氏名"),
  email              STRING  OPTIONS(description="メールアドレス"),
  birth_date         DATE    OPTIONS(description="生年月日"),
  gender             STRING  OPTIONS(description="性別"),
  postal_code        STRING  OPTIONS(description="郵便番号"),
  prefecture         STRING  OPTIONS(description="都道府県"),
  store_code         STRING  OPTIONS(description="登録店舗コード"),
  membership_rank    STRING  OPTIONS(description="会員ランク"),
  points_balance     INT64   OPTIONS(description="保有ポイント"),
  registration_date  DATE    OPTIONS(description="会員登録日"),
  last_purchase_date DATE    OPTIONS(description="最終購入日"),
  status             STRING  OPTIONS(description="会員ステータス(ACTIVE/INACTIVE)"),

  PRIMARY KEY (customer_id) NOT ENFORCED
);

データ挿入
INSERT INTO `TEST_DB.MCP_TEST_DATA`
(customer_id, kaiin_id, card_no, phone_no, address, customer_name, email, birth_date, gender, postal_code, prefecture, store_code, membership_rank, points_balance, registration_date, last_purchase_date, status)
VALUES
('CUST0000001','K10023001','4980123400010001','090-1234-5601','東京都千代田区丸の内1-1-1','佐藤','sato.taro01@example.com','1985-04-12','M','100-0005','東京都','ST001','ゴールド',12500,'2019-06-01','2026-08-01','ACTIVE'),
('CUST0000004','K10023004','4980123400010004','090-1234-5604','愛知県名古屋市中区栄4-4-4','田中','tanaka.misaki04@example.com','1995-02-18','F','460-0008','愛知県','ST004','ゴールド',22100,'2018-09-22','2026-08-10','ACTIVE'),
('CUST0000007','K10023007','4980123400010007','090-1234-5607','宮城県仙台市青葉区一番町7-7-7','山本','yamamoto.daisuke07@example.com','1983-01-27','M','980-0811','宮城県','ST007','ゴールド',18900,'2017-08-19','2026-08-05','ACTIVE'),
('CUST0000002','K10023002','4980123400010002','090-1234-5602','大阪府大阪市北区梅田2-2-2','鈴木','suzuki.hanako02@example.com','1990-07-23','F','530-0001','大阪府','ST002','シルバー',3400,'2020-01-15','2026-07-20','ACTIVE'),
('CUST0000005','K10023005','4980123400010005','090-1234-5605','福岡県福岡市博多区博多駅前5-5-5','伊藤','ito.kenta05@example.com','1988-06-30','M','812-0011','福岡県','ST005','シルバー',5600,'2019-12-01','2026-06-15','ACTIVE'),
('CUST0000008','K10023008','4980123400010008','090-1234-5608','広島県広島市中区紙屋町8-8-8','中村','nakamura.yumi08@example.com','1975-12-03','F','730-0011','広島県','ST008','シルバー',4300,'2020-06-25','2026-04-28','ACTIVE'),
('CUST0000011','K10023011','4980123400010011','090-1234-5611','埼玉県さいたま市大宮区桜木町11-11-11','吉田','yoshida.shota11@example.com','1993-03-16','M','330-0854','埼玉県','ST011','シルバー',3900,'2021-07-08','2026-06-02','ACTIVE'),
('CUST0000014','K10023014','4980123400010014','090-1234-5614','新潟県新潟市中央区古町14-14-14','松本','matsumoto.yoko14@example.com','1980-07-07','F','951-8063','新潟県','ST014','シルバー',5100,'2019-10-02','2026-07-25','ACTIVE'),
('CUST0000017','K10023017','4980123400010017','090-1234-5617','長野県長野市南長野17-17-17','林','hayashi.naoki17@example.com','1979-09-05','M','380-0835','長野県','ST017','シルバー',2800,'2020-08-30','2026-06-22','ACTIVE'),
('CUST0000020','K10023020','4980123400010020','090-1234-5620','石川県金沢市片町20-20-20','山口','yamaguchi.mao20@example.com','1998-01-30','F','920-0981','石川県','ST020','シルバー',3700,'2021-09-19','2026-04-11','ACTIVE'),
('CUST0000003','K10023003','4980123400010003','090-1234-5603','神奈川県横浜市西区みなとみらい3-3-3','高橋','takahashi.ichiro03@example.com','1978-11-05','M','220-0012','神奈川県','ST003','レギュラー',800,'2021-03-10','2026-05-11','ACTIVE'),
('CUST0000006','K10023006','4980123400010006','090-1234-5606','北海道札幌市中央区大通西6-6-6','渡辺','watanabe.sakura06@example.com','1992-09-14','F','060-0042','北海道','ST006','レギュラー',1200,'2022-04-05','2026-07-01','ACTIVE'),
('CUST0000009','K10023009','4980123400010009','090-1234-5609','京都府京都市下京区烏丸通9-9-9','小林','kobayashi.osamu09@example.com','1997-05-09','M','600-8216','京都府','ST009','レギュラー',600,'2023-01-11','2026-03-30','ACTIVE'),
('CUST0000012','K10023012','4980123400010012','090-1234-5612','千葉県千葉市中央区富士見12-12-12','山田','yamada.riko12@example.com','1986-10-11','F','260-0015','千葉県','ST012','レギュラー',950,'2022-11-20','2026-05-19','INACTIVE'),
('CUST0000015','K10023015','4980123400010015','090-1234-5615','岡山県岡山市北区表町15-15-15','井上','inoue.takuya15@example.com','1996-12-19','M','700-0822','岡山県','ST015','レギュラー',400,'2023-05-14','2026-02-10','ACTIVE');

② サービスアカウントの作成

Databricksからアクセスするための、専用サービスアカウントを作成します。

・Cloud Console →「IAMと管理」→「サービスアカウント」→「+サービスアカウントを作成

image.png

以下のロールを付与して作成
image.png

③ サービスアカウントキーの発行

・サービスアカウントの詳細画面 →「キー」タブ →「キーを追加」→「新しい鍵を作成」→「JSON」

警告
今回は検証目的のため、サービスアカウントキー(JSON)の発行としていますが、本格運用の際はOAuth 2.0 + IAMによる認証が推奨されています。

Databricks側の準備

① サービスアカウントキーをDatabricks Secretsに登録

発行したJSONキーをBase64にエンコードした後、Databricks Secretに登録しています。

JSONをBase64にエンコード
```bash
python -c "import json, base64; print(base64.b64encode(json.dumps(json.load(open('サービスアカウントキー.json'))).encode()).decode())"
​```
DatabricksノートブックからSecret Scope作成・登録
import requests

HOST  = "https://<ワークスペースURL>"
TOKEN = "<Databricksアクセストークン>"

GCP_SA_KEY_B64 = "<Base64エンコードしたサービスアカウントキー>"

headers = {"Authorization": f"Bearer {TOKEN}"}

# スコープ作成
res = requests.post(
    f"{HOST}/api/2.0/secrets/scopes/create",
    headers=headers,
    json={"scope": "gcp-mcp"},
)
print(f"create-scope: {res.status_code} {res.text}")

# Base64文字列をSecretとして登録
res = requests.post(
    f"{HOST}/api/2.0/secrets/put",
    headers=headers,
    json={
        "scope": "gcp-mcp",
        "key": "sa-key-json-b64",
        "string_value": GCP_SA_KEY_B64,
    },
)
print(f"put-secret  : {res.status_code} {res.text}")

検証A. Databricksノートブックから、Pythonで直接BigQuery MCPサーバーを呼び出す

Databricksノートブックから、GoogleのマネージドBigQuery MCPサーバーに対して、
HTTP経由で直接アクセスできるかを検証します。

処理構成

  1. サービスアカウントキーから、Google Cloudの認証情報(credentials)を作成する
  2. 認証情報から、有効なアクセストークンを取得し、認証ヘッダーを組み立てる
  3. JSON-RPC形式のペイロードを組み立て、BigQuery MCPサーバーへPOSTリクエストを送る
  4. レスポンスを検証し、結果をPythonの辞書として返す
設定
# Google側の対象情報
PROJECT_ID = "<PROJECT_ID>"
DATASET_ID = "<DATASET_ID>"
TABLE_ID = "<TABLE_ID>"
MCP_ENDPOINT = "https://bigquery.googleapis.com/mcp"

# Base64→JSON
sa_key_b64 = dbutils.secrets.get(scope="gcp-mcp", key="sa-key-json-b64")
sa_key_json = base64.b64decode(
    sa_key_b64.replace("\n", "").replace(" ", "")
).decode("utf-8")
sa_key_info = json.loads(sa_key_json)

# 認証情報の作成
credentials = service_account.Credentials.from_service_account_info(
    sa_key_info,
    scopes=["https://www.googleapis.com/auth/bigquery"],
)
認証ヘッダーの組み立て
def get_mcp_headers():
    auth_req = google.auth.transport.requests.Request()
    credentials.refresh(auth_req)
    return {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {credentials.token}",
    }
MCPサーバー呼び出し関数(call_mcp)の定義
def call_mcp(method: str, params: dict | None = None) -> dict:
    """BigQuery MCPサーバーへJSON-RPCリクエストを送る。"""
    payload = {"jsonrpc": "2.0", "id": "1", "method": method}
    if params is not None:
        payload["params"] = params

    response = requests.post(
        MCP_ENDPOINT,
        headers=get_mcp_headers(),
        data=json.dumps(payload),
        timeout=60,
    )
    response.raise_for_status()
    return response.json()

利用可能ツールの確認

BigQuery MCPサーバーに、利用可能なツールの一覧を問い合わせます。

tools_response = call_mcp("tools/list")
 
print("利用可能なツール:")
for tool in tools_response.get("result", {}).get("tools", []):
    print(" -", tool.get("name"))

image.png

マネージドBigQuery MCPで用意されているツールの概要は以下の通りです。

ツール名 概要
list_dataset_ids プロジェクト内のBigQueryデータセットID一覧を取得する
get_dataset_info 指定したデータセットのメタデータ(作成日時、説明など)を取得する
list_table_ids 指定したデータセット内のテーブルID一覧を取得する
get_table_info 指定したテーブルのスキーマ・メタデータを取得する
execute_sql_readonly 読み取り専用(SELECT文のみ)でSQLクエリを実行する。INSERT/UPDATE/DELETEは実行不可
execute_sql SQLクエリを実行する(読み取り・書き込みともに可能)

クエリの実行

execute_sql_readonlyツールを使って、会員ランク(membership_rank)ごとの
人数と平均保有ポイントを集計してみます。

analysis_query = f"""
SELECT
  membership_rank,
  COUNT(*) AS customer_count,
  AVG(points_balance) AS avg_points_balance
FROM `{PROJECT_ID}.{DATASET_ID}.{TABLE_ID}`
GROUP BY membership_rank
ORDER BY customer_count DESC
"""
 
query_response = call_mcp(
    "tools/call",
    params={
        "name": "execute_sql_readonly",
        "arguments": {
            "projectId": PROJECT_ID,
            "query": analysis_query,
        },
    },
)
 
print(json.dumps(query_response, indent=2, ensure_ascii=False))

実行結果
{
  "id": "1",
  "jsonrpc": "2.0",
  "result": {
    "content": [
      {
        "text": "{\"schema\":{\"fields\":[{\"name\":\"membership_rank\",\"type\":\"STRING\",\"mode\":\"NULLABLE\"},{\"name\":\"customer_count\",\"type\":\"INTEGER\",\"mode\":\"NULLABLE\"},{\"name\":\"avg_points_balance\",\"type\":\"FLOAT\",\"mode\":\"NULLABLE\"}]},\"rows\":[{\"f\":[{\"v\":\"シルバー\"},{\"v\":\"7\"},{\"v\":\"4114.285714285714\"}]},{\"f\":[{\"v\":\"レギュラー\"},{\"v\":\"5\"},{\"v\":\"790.0\"}]},{\"f\":[{\"v\":\"ゴールド\"},{\"v\":\"3\"},{\"v\":\"17833.333333333332\"}]}],\"jobComplete\":true,\"queryId\":\"job_7s4ZRJ1KytDq4m0GjpT2x9KXNGQO\",\"totalBytesBilled\":\"10485760\",\"totalSlotMs\":\"6\",\"totalBytesProcessed\":\"345\"}",
        "type": "text"
      }
    ],
    "structuredContent": {
      "jobComplete": true,
      "queryId": "job_7s4ZRJ1KytDq4m0GjpT2x9KXNGQO",
      "rows": [
        {
          "f": [
            {
              "v": "シルバー"
            },
            {
              "v": "7"
            },
            {
              "v": "4114.285714285714"
            }
          ]
        },
        {
          "f": [
            {
              "v": "レギュラー"
            },
            {
              "v": "5"
            },
            {
              "v": "790.0"
            }
          ]
        },
        {
          "f": [
            {
              "v": "ゴールド"
            },
            {
              "v": "3"
            },
            {
              "v": "17833.333333333332"
            }
          ]
        }
      ],
      "schema": {
        "fields": [
          {
            "mode": "NULLABLE",
            "name": "membership_rank",
            "type": "STRING"
          },
          {
            "mode": "NULLABLE",
            "name": "customer_count",
            "type": "INTEGER"
          },
          {
            "mode": "NULLABLE",
            "name": "avg_points_balance",
            "type": "FLOAT"
          }
        ]
      },
      "totalBytesBilled": "10485760",
      "totalBytesProcessed": "345",
      "totalSlotMs": "6"
    }
  }
}

テストデータ通り、以下の集計結果が取得できていることが確認できます。

会員ランク 人数 平均保有ポイント
シルバー 7人 4,114
レギュラー 5人 790
ゴールド 3人 17,833

検証B.Databricks Unity CatalogにMCP Serviceとして登録し、Playground上で自然言語からデータ分析を行う

Databricksの Unity Catalog にBigQuery MCPサーバーを「MCP Service」として登録し、
Playground上から自然言語でBigQueryのデータを分析できるかを検証します。

手順

  1. Unity AI Gateway の MCPs 画面から、BigQuery MCPサーバーを新規登録する
  2. 認証方式を選択し、必要な情報を設定する
  3. 登録されたツール一覧を確認する
  4. Playground上で、自然言語によるデータ分析を実行する

① Unity AI Gateway の MCPs 画面から新規登録

Databricksワークスペースの左メニューから「AI Gateway」を開き、上部タブの「MCPs」を選択します。

image.png

右上の「+ MCP」ボタンをクリックし、Connect an existing MCP serverを選択します。
image.png

登録時に指定する項目は以下の通りです。

項目
Catalog 任意(例: test_db
Schema 任意(例: mcp
Name 任意(例: gcp_mcp
Connection Create new connection
Server URL https://bigquery.googleapis.com/mcp

② 認証方式の設定

今回は検証目的なので、Bearer token で認証します。

Databricksノートブックで以下を実行し、アクセストークンを取得します。

import json
import base64
from google.oauth2 import service_account
import google.auth.transport.requests

# Databricks SecretsからBase64エンコードされたサービスアカウントキーを取得
sa_key_b64 = dbutils.secrets.get(scope="gcp-mcp", key="sa-key-json-b64")
sa_key_json = base64.b64decode(
    sa_key_b64.replace("\n", "").replace(" ", "")
).decode("utf-8")
sa_key_info = json.loads(sa_key_json)

credentials = service_account.Credentials.from_service_account_info(
    sa_key_info,
    scopes=["https://www.googleapis.com/auth/bigquery"],
)

# アクセストークンを取得
auth_req = google.auth.transport.requests.Request()
credentials.refresh(auth_req)

print("取得したアクセストークン:")
print(credentials.token)

取得したアクセストークンを、Bearer token欄に貼り付け、Create & load toolsボタンをクリックします。
image.png

Create & load toolsボタンをクリックしたら、利用可能なToolの一覧が表示され選択が可能になります
image.png

警告
アクセストークンは発行から約1時間で失効するため、更新が必要です。
今回は検証目的のため、アクセストークンでの認証を選択していますが恒久運用にはOAuth系の認証方式への切り替えが必要です。

④ Playgroundでの自然言語分析

Create MCP Serviceで作成後、画面右上のTry in Playgroundをクリックすると、このMCP Serviceのツールを使えるチャット画面が開きます。
image.png

以下のように、テーブル情報を含めて自然言語で質問してみます。

プロジェクトID:<PROJECT_ID>のBigQueryのTEST_DBデータセットにあるMCP_TEST_DATAから、会員ランク(membership_rank)ごとの人数を集計してください。 ​

実行すると、使用したToolと結果を含めたやり取りが画面に表示され、
最終的な集計結果が出力されます。
image.png
image.png

まとめ

DatabricksからGoogle管理のBigQuery MCPサーバーへのアクセスを、2つの方法で検証しました。
検証A. Databricksノートブックから、Pythonで直接BigQuery MCPサーバーを呼び出す方法
検証B. Databricks Unity CatalogにMCP Serviceとして登録し、Playground上で自然言語からデータ分析を行う方法

どちらの方法でも、GoogleのマネージドMCPサーバーに対してBigQueryのデータを取得・分析できることを確認できました。
本番規模のデータに対してエージェントが適切なSQLを自律生成し、適切なToolを使用して分析が行えるかの検証が今後の課題です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?