はじめに
Snowflake では、Snowflake-managed MCP Server を利用することで、MCP(Model Context Protocol)クライアントから Snowflake 上のデータや機能にアクセスできます。
一方、Databricks では外部の MCP Server を HTTP Connection として接続し、Unity Gateway の MCP サービスとして公開することで、Databricks 上のエージェントやアプリケーションから利用できます。
そこで本記事では、Snowflake-managed MCP Server を Databricks から利用する構成を実際に構築し、以下の2つの OAuth 認証方式を検証します。
- Microsoft Entra ID を利用した OAuth 認証(M2M)
- Snowflake OAuth を利用した OAuth 認証(U2M)
M2M では、Microsoft Entra ID の Client Credentials Flow で取得したアクセストークンを Snowflake の External OAuth で検証し、Snowflake のサービスユーザーおよびロールへマッピングします。
一方、U2M では Snowflake OAuth を利用し、Databricks の HTTP Connection から Snowflake にサインインすることで、ユーザー単位の認証を行います。
さらに、作成した Snowflake-managed MCP Server を Databricks の HTTP Connection に登録し、Unity Gateway の MCP サービス経由で tools/list を実行できるところまで確認します。
本記事では、それぞれの認証方式について、Snowflake・Microsoft Entra ID・Databricks の設定手順と、実際の接続確認結果を順番に紹介します。
それぞれの認証では以下の構成にします。
- Microsoft Entra ID を利用した OAuth 認証(M2M)
- Snowflake OAuth を利用した OAuth 認証(U2M)
Microsoft Entra ID を利用した OAuth 認証(M2M)
1. Snowflake で MCP を作成する
Snowflake-managed MCP Server を作成します。
本検証では、SYSTEM_EXECUTE_SQL(SQL 実行)ツールを使用しました。
CREATE OR REPLACE MCP SERVER <DATABASE_NAME>.<SCHEMA_NAME>.DEMO_MCP_01
FROM SPECIFICATION $$
tools:
- title: "SQL Execution Tool"
name: "sql_exec_tool"
type: "SYSTEM_EXECUTE_SQL"
description: "SQL 実行"
config:
read_only: false
query_timeout: 600
warehouse: "MCP_WH"
$$;
DESCRIBE MCP SERVER DEMO_MCP_01;
2. Snowflake に MCP 用ロールを作成する
MCP 専用ロールを作成します。
CREATE ROLE IF NOT EXISTS MCP_ROLE;
必要な権限を付与します。
GRANT USAGE ON DATABASE <DATABASE_NAME>
TO ROLE MCP_ROLE;
GRANT USAGE ON SCHEMA <DATABASE_NAME>.<SCHEMA_NAME>
TO ROLE MCP_ROLE;
GRANT USAGE ON WAREHOUSE MCP_WH
TO ROLE MCP_ROLE;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA <DATABASE_NAME>.<SCHEMA_NAME> TO ROLE MCP_ROLE;
GRANT USAGE
ON MCP SERVER <DATABASE_NAME>.<SCHEMA_NAME>.DEMO_MCP_01
TO ROLE MCP_ROLE;
3. Entra ID に Snowflake OAuth Resource 用アプリ登録を作成する
Entra ID で Snowflake OAuth Resource 用アプリ登録を作成します。
| 項目 | 設定値 |
|---|---|
| 名前 | snowflake-mcp-resource |
| アカウントの種類 | シングル テナントのみ |
続いて、Snowflake OAuth Resource 用アプリ登録 → API の公開 を選択して、Application ID URI を設定します。
設定する値は以下です。
api://<snowflake-mcp-resource_CLIENT_ID>
最後に MCP アクセス用 App Role を作成します。
Snowflake OAuth Resource 用アプリ登録 → アプリ ロール を選択して、以下のように適用します。
| 項目 | 設定値 |
|---|---|
| 表示名 | MCP Role |
| メンバーの種類 | アプリケーション |
| 値 | session:role:MCP_ROLE |
| 説明 | Snowflake MCP access |
4. Databricks アクセス用アプリ登録を作成する
Databricks アクセス用アプリ登録を作成します。
手順は以下の記事の 7-2. をご参照ください。Client ID と Client Secret を控えておきます。
作成後、API のアクセス許可を付与します。
Databricks アクセス用アプリ登録 → API のアクセス許可 を選択して、以下のように追加します。
| 項目 | 設定値 |
|---|---|
| アクセス許可の種類 | アプリケーションの許可 |
| アクセス許可 | session:role:MCP_ROLE |
その後、「管理者の同意」を実行します。
5. アクセス トークンの中身を確認する
Azure Portal の Cloud Shell で以下を実行します。
TOKEN=$(curl -sS \
-X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=<CLIENT_ID>" \
--data-urlencode "client_secret=<CLIENT_SECRET>" \
--data-urlencode "grant_type=client_credentials" \
--data-urlencode "scope=api://<RESOURCE_APP_CLIENT_ID>/.default" \
"https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token" \
| jq -r '.access_token')
python3 - <<'PY'
import os
import json
import base64
token = os.environ["TOKEN"]
payload = token.split(".")[1]
payload += "=" * (-len(payload) % 4)
data = json.loads(
base64.urlsafe_b64decode(payload)
)
print(json.dumps(data, indent=2))
PY
出力結果は以下のようになります。
{
"aud": "api://<snowflake-mcp-resource_CLIENT_ID>",
"iss": "https://sts.windows.net/<TENANT_ID>/",
"sub": "xxxxxxxxxxxxxxxxxxxxxxxx",
"roles": [
"session:role:MCP_ROLE"
],
...
}
特に、session:role:MCP_ROLE が入っていない場合は、アプリ ロール、API のアクセス許可、管理者の同意を確認します。
後続で使用する sub と iss の値を控えておきます。
6. sub を Snowflake USER へマッピングする
sub の値を Snowflake USER の LOGIN_NAME に設定します。
Snowflake で以下を実行します。
CREATE OR REPLACE USER MCP_USER
TYPE = SERVICE
LOGIN_NAME = '<sub と一致する値>'
DEFAULT_ROLE = MCP_ROLE
DEFAULT_WAREHOUSE = MCP_WH;
ロールを付与します。
GRANT ROLE MCP_ROLE
TO USER MCP_USER;
7. External OAuth Security Integration を作成する
Snowflake に External OAuth Security Integration を作成します。
CREATE OR REPLACE SECURITY INTEGRATION MCP_DEMO_OAUTH
TYPE = EXTERNAL_OAUTH
ENABLED = TRUE
EXTERNAL_OAUTH_TYPE = AZURE
EXTERNAL_OAUTH_ISSUER =
'<iss と一致する値>'
EXTERNAL_OAUTH_JWS_KEYS_URL =
'https://login.microsoftonline.com/<TENANT_ID>/discovery/v2.0/keys'
EXTERNAL_OAUTH_AUDIENCE_LIST =
('api://<snowflake-mcp-resource_CLIENT_ID>')
EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM = 'sub'
EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE = 'LOGIN_NAME';
DESC SECURITY INTEGRATION MCP_DEMO_OAUTH;
8. Snowflake MCP Server に External OAuth をバインドする
MCP Server が存在する Schema に設定します。
ALTER SCHEMA POC_DB.MCP
SET
OAUTH_AUTHORIZATION_SERVER = MCP_DEMO_OAUTH
OAUTH_SCOPES_SUPPORTED = 'session:role:MCP_ROLE';
SHOW PARAMETERS LIKE 'OAUTH_%'
IN SCHEMA POC_DB.MCP;
9. Databricks HTTP Connection を作成
Databricks で HTTP Connectionを作成します。
Databricks アクセス用アプリ登録の Client ID と Client Secret は Databricks Secret に保管して利用しています。
from databricks.sdk import WorkspaceClient
from databricks.sdk.service import catalog
w = WorkspaceClient()
# Databricks アクセス用アプリ登録の Client ID と Client Secret
client_id = dbutils.secrets.get(catalog="<CATALOG_NAME>", schema="<SCHEMA_NAME>", key="<CLIENT_ID_SECRET_NAME>")
client_secret = dbutils.secrets.get(catalog="<CATALOG_NAME>", schema="<SCHEMA_NAME>", key="<CLIENT_SECRET_SECRET_NAME>")
connection = w.connections.create(
name="connection_snow_sql_mcp_server_m2m",
connection_type=catalog.ConnectionType.HTTP,
parent="schemas/<CATALOG_NAME>.<SCHEMA_NAME>",
options={
"host": "https://<SNOWFLAKE_ACCOUNT_URL>",
"port": "443",
"base_path": "/api/v2/databases/<DATABASE>/schemas/<SCHEMA>/mcp-servers/<MCP_SERVER>",
"client_id": client_id,
"client_secret": client_secret,
"oauth_scope": 'api://<snowflake-mcp-resource_CLIENT_ID>/.default',
"token_endpoint": "https://login.microsoftonline.com/<TENANT_ID>/oauth2/v2.0/token",
},
comment="Snowflake 管理 MCP サーバーへの M2M 接続",
)
print(connection.full_name)
10. MCP サービスの作成
次に MCP サービスを作成します。
以下の記事の「MCP サービスの作成」をご参照ください。
MCP サービス経由で Python でツール一覧を取得できることを確認しました。
%pip install -U databricks-mcp nest_asyncio
dbutils.library.restartPython()
import nest_asyncio
nest_asyncio.apply()
from databricks_mcp import DatabricksMCPClient
from databricks.sdk import WorkspaceClient
w = WorkspaceClient()
host = w.config.host
mcp_url = f"{host}/ai-gateway/mcp-services/<MCP_SERVICE_NAME>"
client = DatabricksMCPClient(
server_url=mcp_url,
workspace_client=w
)
tools = client.list_tools()
for t in tools:
print("Tool: ", t.name)
print("Description: ", t.description)
print("Schema: ", t.input_schema)
print("-----")
トライアル環境で発生したエラー
トライアル環境では tools/list までは成功しましたが、MCP ツールの実行で以下のエラーが発生しました。
MCP error calling tool sql_exec_tool:
Agent error (code 399504):
Access denied for trial accounts.
ツール実行まで検証する場合は、通常のアカウントでの再検証が必要です。
認証から MCP ツールの実行までの流れは以下です。
11. アクセス確認
ログイン履歴を確認できます。
MCP_USER としてログインしていることが確認できました。
ALTER SESSION SET TIMEZONE = 'Asia/Tokyo';
SELECT
*
FROM TABLE(
INFORMATION_SCHEMA.LOGIN_HISTORY(
TIME_RANGE_START => DATEADD('hour', -1, CURRENT_TIMESTAMP()),
TIME_RANGE_END => CURRENT_TIMESTAMP(),
RESULT_LIMIT => 100
)
)
ORDER BY EVENT_TIMESTAMP DESC;
ドキュメントには OAuth ログインを許可した Security Integration も確認できる列がありそうでしたが、対象列を確認できませんでした。
https://docs.snowflake.com/en/sql-reference/functions/login_history
Snowflake OAuth による認証(U2M)
1. OAuth Security Integration を作成する
Snowflake に OAuth Security Integration を作成します。
CREATE OR REPLACE SECURITY INTEGRATION MCP_OAUTH_DATABRICKS
TYPE = OAUTH
OAUTH_CLIENT = CUSTOM
ENABLED = TRUE
OAUTH_CLIENT_TYPE = 'CONFIDENTIAL'
OAUTH_REDIRECT_URI =
'https://<Databricks Workspace>/login/oauth/http.html';
作成後、OAUTH_CLIENT_ID と OAUTH_CLIENT_SECRET を控えておきます。
SELECT SYSTEM$SHOW_OAUTH_CLIENT_SECRETS(
'MCP_OAUTH_DATABRICKS'
);
また、OAUTH_AUTHORIZATION_ENDPOINT と OAUTH_TOKEN_ENDPOINT の値を控えておきます。
DESC SECURITY INTEGRATION MCP_OAUTH_DATABRICKS;
2. Databricks HTTP Connectionを作成
Databricks で HTTP Connectionを作成します。
Snowflake OAuth Security Integration の OAUTH_CLIENT_ID と OAUTH_CLIENT_SECRET は Databricks Secret に保管して利用しています。
from databricks.sdk import WorkspaceClient
from databricks.sdk.service import catalog
w = WorkspaceClient()
# Snowflake OAuth Security Integration の Client ID と Client Secret
client_id = dbutils.secrets.get(catalog="<CATALOG_NAME>", schema="<SCHEMA_NAME>", key="<CLIENT_ID_SECRET_NAME>")
client_secret = dbutils.secrets.get(catalog="<CATALOG_NAME>", schema="<SCHEMA_NAME>", key="<CLIENT_SECRET_SECRET_NAME>")
connection = w.connections.create(
name="connection_snow_sql_mcp_server_u2m",
connection_type=catalog.ConnectionType.HTTP,
parent="schemas/<CATALOG_NAME>.<SCHEMA_NAME>",
options={
"host": "https://<SNOWFLAKE_ACCOUNT_URL>",
"port": "443",
"base_path": "/api/v2/databases/<DATABASE>/schemas/<SCHEMA>/mcp-servers/<MCP_SERVER>",
"client_id": client_id,
"client_secret": client_secret,
"authorization_endpoint": "<OAUTH_AUTHORIZATION_ENDPOINT>",
"token_endpoint": "<OAUTH_TOKEN_ENDPOINT>",
},
comment="Snowflake 管理 MCP サーバーへの U2M 接続",
)
print(connection.full_name)
作成後、HTTP Connection の UI 画面で Snowflake にサインインします。
高権限ロールによるアクセスエラー
※本番環境では専用ロールを推奨
デフォルトロールが ACCOUNTADMIN の場合、サインイン時に以下のようなエラーが発生します。
The role requested has been explicitly blocked
for use with this application by an administrator.
Please try logging in with a different role,
or contact your administrator.
Snowflake ではデフォルトで以下の高権限ロールが OAuth 利用からブロックされています。
ACCOUNTADMIN
SECURITYADMIN
ORGADMIN
GLOBALORGADMIN
高権限ロールの OAuth 利用を許可し、Security Integration の許可ロールに追加します
ALTER ACCOUNT SET
OAUTH_ADD_PRIVILEGED_ROLES_TO_BLOCKED_LIST = FALSE;
ALTER SECURITY INTEGRATION <SECURITY_INTEGRATION_NAME>
SET ALLOWED_ROLES_LIST = (
'ACCOUNTADMIN'
);
DESC SECURITY INTEGRATION MCP_OAUTH_DATABRICKS;
3. MCP サービスの作成
次に MCP サービスを作成します。
以下の記事の「MCP サービスの作成」をご参照ください。
MCP サービス経由で Python でツール一覧を取得できることを確認しました。
%pip install -U databricks-mcp nest_asyncio
dbutils.library.restartPython()
import nest_asyncio
nest_asyncio.apply()
from databricks_mcp import DatabricksMCPClient
from databricks.sdk import WorkspaceClient
w = WorkspaceClient()
host = w.config.host
mcp_url = f"{host}/ai-gateway/mcp-services/<MCP_SERVICE_NAME>"
client = DatabricksMCPClient(
server_url=mcp_url,
workspace_client=w
)
tools = client.list_tools()
for t in tools:
print("Tool: ", t.name)
print("Description: ", t.description)
print("Schema: ", t.input_schema)
print("-----")
4. アクセス確認
ログイン履歴を確認できます。
個別ユーザーとしてログインしていることが確認できました。
ALTER SESSION SET TIMEZONE = 'Asia/Tokyo';
SELECT
*
FROM TABLE(
INFORMATION_SCHEMA.LOGIN_HISTORY(
TIME_RANGE_START => DATEADD('hour', -1, CURRENT_TIMESTAMP()),
TIME_RANGE_END => CURRENT_TIMESTAMP(),
RESULT_LIMIT => 100
)
)
ORDER BY EVENT_TIMESTAMP DESC;



















