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 Lakebase を PostgreSQL MCP Server 経由で Unity AI Gateway から呼び出す

0
Last updated at Posted at 2026-09-15

はじめに

本記事では、Databricks Lakebase に対して PostgreSQL 用 MCP Server である pg-mcp-server を接続し、その MCP Server を Azure Container Apps にホストします。

さらに、Azure Container Apps 上の MCP Server を Databricks Unity AI Gateway の MCP Service として登録し、MCP Inspector から呼び出すところまで試しました。

最終的な構成は以下です。

Databricks Lakebase は Free Edition で構成し、Databricks Unity AI Gateway は別テナントで構成しています。

MCP Inspector
      |
      | OAuth / Streamable HTTP
      v
Databricks Unity AI Gateway
      |
      | MCP Service
      v
Unity Catalog HTTP Connection
      |
      | HTTPS
      v
Azure Container Apps
      |
      | pg-mcp-server
      v
Databricks Lakebase

今回使用した pg-mcp-server は、PostgreSQL に対して query ツールやテーブル情報を提供する MCP Server です。

HTTP モードでは Streamable HTTP を使用し、デフォルトでは 3000 ポートの /mcp に MCP Endpoint を公開します。また、PostgreSQL の接続先は DATABASE_URL で指定します。

環境

今回の環境は以下です。

ローカル
- Windows
- VS Code
- WSL
- Azure CLI

Azure
- Azure Container Registry
- Azure Container Apps

Databricks
- Azure Databricks
- Lakebase
- Unity Catalog
- Unity AI Gateway

MCP Client
- MCP Inspector

Container Apps 自体の作成・設定は Azure Portal から行い、コンテナイメージのビルドのみ WSL から az acr build を使用します。

PostgreSQL MCP Server について

PostgreSQL 向けの MCP Server はいくつかありますが、今回の検証では ericzakariasson/pg-mcp-server (コミュニティ製のOSS) を利用します。

主な候補は以下です。

実装 特徴
ericzakariasson/pg-mcp-server Streamable HTTP 対応、リモート MCP として公開しやすい
stuzero/pg-mcp-server スキーマ探索や EXPLAIN など PostgreSQL 分析機能が充実
microsoft/postgres-mcp Microsoft 提供、現状は主に stdio transport 前提

MCP の代表的な Transport には次の2つがあります。

  • stdio
    MCP Client が MCP Server のプロセスを起動し、標準入力・標準出力で通信する方式。VS CodeやClaude Desktopなど、ローカル利用に向いている。

  • Streamable HTTP
    HTTP(S) 経由で MCP Server へ接続する方式。Container Apps などに MCP Server を配置し、リモートから利用する構成に向いている。

本検証では Streamable HTTP 接続が必要となるため、ericzakariasson/pg-mcp-server を利用しました。

1. Lakebase の準備

Lakebase のサンプルデータを用意するため、以下を実施しました。

エンドポイントのエラー

Lakebase を準備する際に以下のエラーが発生しました。

The endpoint has been disabled. Enable it using the API and retry.

こちらはエンドポイントを再有効化することで解決しました。

https://community.databricks.com/t5/lakebase-discussions/lakebase-postgres-branch-stuck-quot-disabled-quot-after-auto/td-p/167812

from databricks.sdk import WorkspaceClient
from databricks.sdk.service.postgres import (
    Endpoint,
    EndpointSpec,
    EndpointType,
    FieldMask
)

w = WorkspaceClient()

endpoint_name = "projects/my-project/branches/production/endpoints/primary"

endpoint_spec = EndpointSpec(
    endpoint_type=EndpointType.ENDPOINT_TYPE_READ_WRITE,
    disabled=False
)

result = w.postgres.update_endpoint(
    name=endpoint_name,
    endpoint=Endpoint(
        name=endpoint_name,
        spec=endpoint_spec
    ),
    update_mask=FieldMask(
        field_mask=["spec.disabled"]
    )
).wait()

print("Endpoint enabled")

endpoint = w.postgres.get_endpoint(
    name=endpoint_name
)

print("disabled:", endpoint.status.disabled)
print("state:", endpoint.status.current_state)

次に、Lakebase に MCP Server から接続する PostgreSQL ユーザーを用意します。

Auth TypeNative PostgreSQL Password を使用しました。

image.png

接続情報は Lakebase の Connect 画面から確認します。

postgresql://<USER>:<PASSWORD>@<DATABASE>?sslmode=require

image.png

次に、作成したユーザーに権限を付与します。

GRANT CONNECT
ON DATABASE databricks_postgres
TO mcp_user;

GRANT USAGE
ON SCHEMA public
TO mcp_user;

GRANT SELECT
ON ALL TABLES IN SCHEMA public
TO mcp_user;

ALTER DEFAULT PRIVILEGES
IN SCHEMA public
GRANT SELECT ON TABLES TO mcp_user;

pg-mcp-server 自体は、デフォルトでは書き込み操作が無効になっています。書き込みを許可する場合は DANGEROUSLY_ALLOW_WRITE_OPS の設定が必要です。

2. Dockerfile を作成する

WSL に作業フォルダを作成します。

mkdir -p ~/lakebase-mcp
cd ~/lakebase-mcp

code .

作業フォルダ配下に Dockerfile を作成します。

lakebase-mcp/
└── Dockerfile

Dockerfile の中身は以下とします。

FROM node:22-alpine

RUN npm install -g pg-mcp-server@0.3.0

# pg-mcp-server 0.3.0 の HTTP transport を
# stateless から stateful へ変更
RUN MCP_FILE="$(npm root -g)/pg-mcp-server/lib/src/mcp-server-http.js" \
    && grep -q "sessionIdGenerator: undefined" "$MCP_FILE" \
    && sed -i \
       's/sessionIdGenerator: undefined/sessionIdGenerator: () => globalThis.crypto.randomUUID()/' \
       "$MCP_FILE" \
    && grep "sessionIdGenerator" "$MCP_FILE"

ENV PORT=3000

EXPOSE 3000

CMD ["pg-mcp-server", "--transport=http"]

pg-mcp-server --transport=http とすることで Streamable HTTP モードになります。

stateless から stateful へ変更について、本記事の下部に記載している注意事項をご確認ください。

3. Azure Container Registry を作成する

Azure Portal から Azure Container Registry を作成します。

レジストリ名: acrxxxxx
場所: Japan East
SKU: Basic

image.png

1つの ACR に複数の Repository を作ることができます。

例えば、

acrxxxxx
├── sql-mcp-server
│   └── v1
└── lakebase-mcp
    └── v1

のように複数の MCP Server をまとめて管理できます。

4. ローカルで az acr build を実行する

今回はローカルで docker build / docker push は実行せず、Azure Container Registry 側でビルドします。

まず Azure にログインして、サブスクリプションを設定します。

# インストール
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# ログイン
az login
az account set \
  --subscription "<Subscription Name>"

Dockerfile のあるディレクトリで以下を実行します。

az acr build \
  --registry <ACR名> \
  --image lakebase-mcp:v1 \
  --file Dockerfile \
  .

az acr build はローカルのビルドコンテキストを ACR Tasks に送り、Azure 側でコンテナイメージをビルドして、そのまま Registry に Push します。

正常終了すると、Azure Container Registry でリポジトリを確認できます。

image.png

5. Azure Container Apps を作成する

Azure Portal から Container Apps を作成します。

コンテナー アプリの作成

以下のように作成します。

コンテナー アプリ名: lakebase-mcp-server
デプロイ元: コンテナー イメージ
Container Apps 環境: 
    リージョン: Japan East
    Container Apps 環境: <既存環境が無い場合は新規作成>

image.png

image.png

コンテナー設定で ACR のイメージを指定します。

イメージのソース: Azure Container Registry
レジストリ: acrxxxxx.azurecr.io
イメージ: lakebase-mcp
イメージ タグ: v1

image.png

イングレスを有効化します。

イングレス: Enabled
イングレス トラフィック: どこからでもトラフィックを受け入れます
イングレス タイプ: HTTP
転送: Auto
ターゲット ポート: 3000

image.png

今回の場合、以下のような転送となります。

Internet
   |
   | HTTPS :443
   v
Azure Container Apps
   |
   | HTTP :3000
   v
pg-mcp-server

Lakebase 接続文字列をシークレットに登録する

コンテナー アプリ作成後、

Container App
→ セキュリティ
→ シークレット

からシークレットを追加します。

Lakebase の Connect 画面から接続文字列を取得し、シークレットに登録します。

キー: lakebase-url
値: postgresql://mcp_user:<PASSWORD>@<DATABASE>?sslmode=require

image.png

環境変数を設定する

コンテナー アプリのリビジョンを編集し、環境変数を設定します。

1つ目: 
    名前: DATABASE_URL
    ソース: シークレットの参照
    値: lakebase-url
2つ目: 
    名前: PORT
    ソース: 手動入力
    値: 3000

image.png

リビジョンとは

Azure Container Apps のリビジョンは、

Container App の「ある時点のコンテナイメージ + 設定」をまとめた1世代分の実行バージョン

です。

例えば、

Container App
└── Revision 1
    ├── image: lakebase-mcp:v1
    ├── DATABASE_URL
    ├── PORT=3000
    └── CPU / Memory

となります。

イメージや環境変数などを変更すると、新しいリビジョンが作成されます。

Container Apps のログを確認する

Azure Portal から、

Container Apps
→ 監視
→ ログ ストリーム

を確認します。

正常時には以下のようなログが確認できます。

image.png

6. Unity AI Gateway に MCP Server を登録する

次に Container Apps 上の MCP Server を Databricks に登録します。

Databricks の外部 MCP Server 登録では、

External MCP Server
      ↓
Unity Catalog Connection
      ↓
MCP Service

という構成になります。

MCP Service として登録することで、Unity Gateway が外部 MCP Server への呼び出しを仲介でき、Unity Catalog の権限管理も利用できます。

HTTP 接続の作成

まずは、HTTP 接続を作成します。

本検証では、Container Apps への認証は設定していないので、bearer_token は任意の文字列を設定しています。

ノートブックで以下を実行します。

from databricks.sdk import WorkspaceClient
from databricks.sdk.service import catalog

w = WorkspaceClient()

connection = w.connections.create(
    name="connection_dbx_free_edition_lakebase",
    connection_type=catalog.ConnectionType.HTTP,
    parent="schemas/enomoto_demo.mcp_demo",
    options={
        "host": "<Container Apps のアプリケーション URL>",
        "port": "443",
        "base_path": "/mcp",
        "bearer_token": "test-token",
    },
    comment="free edition 環境の Lakebase への接続",
)
print(connection.full_name)

image.png

MCP サービスの作成

次に MCP サービスを作成します。

ノートブックで以下を実行します。

from databricks.sdk.service import catalog as c

w = WorkspaceClient()
mcp_service = w.ai_gateway.create_mcp_service(
    parent="schemas/enomoto_demo.mcp_demo",
    mcp_service_id="mcp_dbx_free_edition_lakebase",
    mcp_service=c.McpService(
        comment="free edition 環境の Lakebase MCP サービス",
        config=c.McpServiceConfig(
            source_connection=c.McpServiceConfigSourceConnection(
                name="connections/enomoto_demo.mcp_demo.connection_dbx_free_edition_lakebase"
            ),
        ),
    ),
)

image.png

7. Unity AI Gateway 経由で MCP Inspector から呼ぶ

MCP Client から Databricks MCP へは Streamable HTTP と OAuth / PAT などを使用して接続できます。

MCP Inspector のサーバー登録方法はこちらの記事をご参照ください。

登録完了後、正常に実行できるか確認します。

SELECT current_user, current_database(), version();

image.png

image.png

Databricks の Ingress/Egress 制限について

本検証では、Databricks の Ingress/Egress 制限は何も設定せずに実施しています。
ネットワーク制限がある場合、MCP クライアントの IP 等を許可する必要があると考えられます。

https://learn.microsoft.com/ja-jp/azure/databricks/agents/mcp-tools/connect-clients?utm_source=chatgpt.com#verify-network-configuration

注意事項

pg-mcp-server を Streamable HTTP で利用した際、initialize は成功するものの、その後のリクエストで 500 Internal Server Error や以下のエラーが発生することがありました。

Invalid Request: Server already initialized

そのため本検証では、以下のように Mcp-Session-Id を発行する Stateful 構成へ変更しています。

sessionIdGenerator: () => globalThis.crypto.randomUUID()

これにより、initialize 以降の tools/listtools/call を同じ MCP セッションとして扱えるようになります。

ただし、上記の変更だけでは別クライアントから再度 initialize すると Server already initialized になることがあります。

Client A
  ↓ initialize
McpServer A

Client B
  ↓ initialize
同じ McpServer A
  ↓
Server already initialized
MCP Inspector で発生したエラーの例
[
  {
    "id": "1789463501100-xxx",
    "timestamp": "2026-09-15T09:11:41.100Z",
    "method": "POST",
    "url": "https://adb-12345678.9.azuredatabricks.net/ai-gateway/mcp-services/enomoto_demo.mcp_demo.mcp_dbx_free_edition_lakebase",
    "requestHeaders": {
      "accept": "application/json, text/event-stream",
      "authorization": "[REDACTED]",
      "content-type": "application/json"
    },
    "requestBody": "{\"method\":\"initialize\",\"params\":{\"protocolVersion\":\"2025-11-25\",\"capabilities\":{\"sampling\":{},\"elicitation\":{\"form\":{},\"url\":{}},\"roots\":{\"listChanged\":true},\"tasks\":{\"list\":{},\"cancel\":{},\"requests\":{\"sampling\":{\"createMessage\":{}},\"elicitation\":{\"create\":{}}}},\"extensions\":{\"io.modelcontextprotocol/tasks\":{},\"io.modelcontextprotocol/ui\":{\"mimeTypes\":[\"text/html;profile=mcp-app\"],\"elicitation\":{}}}},\"clientInfo\":{\"name\":\"mcp-inspector\",\"version\":\"0.0.0\"}},\"jsonrpc\":\"2.0\",\"id\":0}",
    "responseStatus": 200,
    "responseStatusText": "OK",
    "responseHeaders": {
      "alt-svc": "h3=\":443\"; ma=86400, h3-29=\":443\"; ma=86400",
      "content-encoding": "gzip",
      "content-type": "application/json",
      "date": "Tue, 15 Sep 2026 09:11:41 GMT",
      "server": "databricks",
      "server-timing": "request_id;dur=0;desc=\"13ba80be-xxx\", client_protocol;dur=0;desc=\"HTTP/1.1\"",
      "strict-transport-security": "max-age=31536000; includeSubDomains; preload",
      "transfer-encoding": "chunked",
      "vary": "Accept-Encoding",
      "x-content-type-options": "nosniff",
      "x-databricks-org-id": "12345678",
      "x-request-id": "13ba80be-xxx"
    },
    "duration": 402,
    "category": "transport",
    "responseBody": "{\"jsonrpc\":\"2.0\",\"id\":0,\"error\":{\"code\":-32603,\"message\":\"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"error\\\":{\\\"code\\\":-32600,\\\"message\\\":\\\"Invalid Request: Server already initialized\\\"},\\\"id\\\":null}\",\"data\":{\"upstream_status\":400}}}"
  }
]

initialize は基本的に各 MCP セッションの開始時に1度だけ実行します。そのため、curlinitialize した直後に MCP Inspector から接続する、といったテストをすると上記エラーが発生します。

検証では、Container Apps のリビジョンを再起動すると解決しました。

本番環境では、複数クライアントや Unity AI Gateway から利用する場合は、最終的には Mcp-Session-Id ごとに McpServerTransport を分離して管理する実装が必要と考えられます。

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?