このページは AI の支援を受けて英語から翻訳されています。内容が異なる場合は英語版が正となります。
mcp
StackQL を Model Context Protocol(MCP)サーバーとして起動するコマンドです。AI エージェントやアシスタントが StackQL のクエリ機能を使用してクラウドインフラストラクチャを操作できるようになります。
Model Context Protocol (MCP) は、AI アプリケーションが外部のデータソースやツールとやり取りする方法を標準化するオープンなプロトコルです。StackQL を MCP サーバーとして実行すると、AI エージェント(Claude、Cursor、Continue、カスタムエージェントなど)が自然言語を使用して、複数のプロバイダーにわたるクラウドインフラストラクチャをクエリし、管理できるようになります。
構文
スタンドアロンの MCP サーバーには stackql mcp [flags] を使用します。
MCP サーバーを PostgreSQL ワイヤプロトコルサーバーと同じプロセスで実行するには stackql srv [flags] を使用します。
デプロイモード
StackQL の MCP サーバーは、さまざまなアーキテクチャ要件に合わせて 3 つの構成でデプロイできます。以下の例では "allow_unauthenticated": true で認証なしの提供にオプトインしており、これはローカル開発に適しています。他のプロセスやホストから到達できる場合は、代わりに Bearer トークンを設定してください(HTTP クライアント認証を参照)。
1. スタンドアロン MCP サーバー
指定したポートで、StackQL を専用の MCP サーバーとして実行します。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}'
使用場面:MCP プロトコルによるアクセスのみが必要で、PostgreSQL ワイヤプロトコルとの互換性が不要な場合に使用します。
2. MCP + PostgreSQL サーバー(インメモリ)
MCP サーバーと PostgreSQL サーバーを同時に実行し、両者間でインメモリ通信を行います。
stackql srv \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}' \
--pgsrv.port 5665
使用場面:AI エージェント向けの MCP プロトコルによるアクセスと、従来のデータベースクライアント向けの PostgreSQL ワイヤプロトコルの両方が必要で、インメモリ通信による最大のパフォーマンスを得たい場合に使用します。
3. MCP + PostgreSQL サーバー(リバースプロキシ)
TCP ベースの通信で両方のサーバーを実行します。分散デプロイと TLS 暗号化をサポートします。
stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9004", "allow_unauthenticated": true}, "backend": {"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"}}' \
--pgsrv.port 5446
TLS 暗号化を使用する場合:
stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{"server": {"tls_cert_file": "/path/to/server_cert.pem", "tls_key_file": "/path/to/server_key.pem", "transport": "http", "address": "127.0.0.1:9004", "auth_token_env_var": "STACKQL_MCP_TOKEN"}, "backend": {"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"}}' \
--pgsrv.port 5446
TLS はトランスポートを暗号化しますが、クライアントを認証しないため、この例では STACKQL_MCP_TOKEN に保持された Bearer トークンも必要です。
使用場面:MCP と PostgreSQL のワークロードを異なるプロセスやホストに分離する必要がある場合、または MCP エンドポイントに TLS 暗号化が必要な場合に使用します。
設定オプション
MCP サーバータイプ
| タイプ | 説明 |
|---|---|
http | 直接 HTTP サーバーモード:MCP リクエストは StackQL エンジンによってプロセス内で処理されます。 |
reverse_proxy | リバースプロキシモード:MCP リクエストは、設定された DSN を介してバックエンドの PostgreSQL サーバーに送られます。stackql srv と組み合わせて使用します。 |
stdio | 標準入出力トランスポート:サーバーは stdin からリクエストを読み取り、stdout にレスポンスを書き込みます。エディターに組み込まれた MCP クライアント(Claude Desktop、Cursor など)が使用します。 |
MCP ログ形式
--mcp.log.format フラグで監査ログのエンコーディングを選択します。値は jsonl(デフォルト)または otel(OpenTelemetry OTLP/JSON ログレコード)です。設定オブジェクトの server.audit.format より優先されます。ログ形式を参照してください。
MCP プロトコルバージョン
--mcp.protocol.version フラグは、サーバーが公開する最新のプロトコルリビジョンを設定します。値は auto(デフォルト、サポートされているすべてのリビジョン)、2026-07-28(セッションレスのみ)、または 2025-11-25 などの古いリビジョン(そのリビジョンとそれ以前)です。設定オブジェクトの server.protocol_version より優先されます。リビジョンの固定を参照してください。
MCP 設定オブジェクト
--mcp.config フラグは、次の構造を持つ JSON オブジェクトを受け付けます。
サーバー設定
| フィールド | 説明 | 必須 |
|---|---|---|
server.transport | トランスポートプロトコル:http または stdio。 | はい |
server.address | MCP サーバーをバインドするアドレスとポート(例:127.0.0.1:9912)。HTTP トランスポートのみ。 | http の場合 |
server.tls_cert_file | HTTPS 用の TLS 証明書ファイルのパス。 | いいえ |
server.tls_key_file | HTTPS 用の TLS 秘密鍵ファイルのパス。 | いいえ |
server.auth_token_env_var | 事前共有された Bearer トークンを保持する環境変数の名前。設定すると、すべての HTTP リクエストに Authorization: Bearer <token> が必要になります。変数が未設定または空の場合、サーバーは起動を拒否します。HTTP クライアント認証を参照してください。 | http の場合、これか allow_unauthenticated のいずれか |
server.allow_unauthenticated | クライアント認証なしで HTTP トランスポートを提供するための明示的なオプトイン。デフォルトは false です。 | http の場合、これか auth_token_env_var のいずれか |
server.mode | ミューテーションとライフサイクル操作をゲート制御する安全コントラクト。read_only、safe(デフォルト)、delete_safe、full_access のいずれか。サーバーモードを参照してください。 | いいえ |
server.read_only | mode: read_only のレガシーなブール値エイリアス。両方のフィールドが設定されている場合は mode が優先されます。 | いいえ |
server.stateless | セッションなし(Mcp-Session-Id なし)で Streamable HTTP を提供します。プロトコルリビジョン 2026-07-28 は HTTP 上でこの方式で提供されます。デフォルトは false です。stdio では無視されます。プロトコルリビジョンのサポートを参照してください。 | いいえ |
server.protocol_version | 公開する最新のプロトコルリビジョン:auto(デフォルト)、2026-07-28、または 2025-11-25 などの古いリビジョン。2026-07-28 を指定すると、Streamable HTTP では stateless が暗黙的に有効になります。リビジョンの固定を参照してください。 | いいえ |
server.audit | 監査サブシステムの設定。audit.format(jsonl または otel)を含みます。監査ログを参照してください。 | いいえ |
バックエンド設定(リバースプロキシモードのみ)
| フィールド | 説明 | 必須 |
|---|---|---|
backend.dsn | バックエンドの StackQL サーバーへの PostgreSQL 接続文字列。 | はい(reverse_proxy の場合) |
最適な互換性を得るため、バックエンド DSN には default_query_exec_mode=simple_protocol パラメーターを含めてください。
許可リスト
| フィールド | 説明 |
|---|---|
enabled_tools | サーバーが公開を許可されるツール名の配列。省略した場合または空の場合は、すべての組み込みツールが登録されます。限られたサブセットだけを公開する場合に使用します(例:読み取り専用のインベントリサーバー)。 |
enabled_prompts | プロンプト名の配列。enabled_tools と同じセマンティクスで、プロンプトに適用されます。 |
server_info と list_providers のみを公開するサーバーの例:
{
"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true},
"enabled_tools": ["server_info", "list_providers"]
}
プロトコルリビジョンのサポート
プロトコルリビジョン 2026-07-28、server.stateless、otel 監査ログ形式は StackQL v0.11.660 以降で利用できます。server.protocol_version と --mcp.protocol.version フラグは StackQL v0.12.732 以降で利用できます。
サーバーは Go MCP SDK がサポートする Model Context Protocol のすべてのリビジョンに対応し、クライアントごとにネゴシエーションします。そのため、異なるリビジョンのクライアントが混在していても 1 つのサーバーで動作します。
| リビジョン | ライフサイクル | 承認リクエスト(safe / delete_safe) |
|---|---|---|
2026-07-28(公開リビジョン) | ハンドシェイクなし:server/discover の後、すべてのリクエストが _meta に io.modelcontextprotocol/protocolVersion と io.modelcontextprotocol/clientCapabilities を含めます(HTTP では、さらに Mcp-Protocol-Version、Mcp-Method、Mcp-Name ヘッダーも含めます)。 | input_required 結果。クライアントが inputResponses を付けて再試行します(SEP-2322)。 |
2025-11-25、2025-06-18 | initialize / notifications/initialized ハンドシェイク。 | サーバーから開始される elicitation/create リクエスト。 |
2025-03-26、2024-11-05 | 同上。 | 同上。 |
stdio は 1 つのプロセスですべてのリビジョンを提供します。2026-07-28 クライアントの最初のリクエストはハンドシェイクなしで処理され、古いクライアントの initialize も引き続き動作します。Claude Desktop、npm / PyPI ランチャー、Docker イメージでは設定は不要です。
Streamable HTTP のデフォルトは、クライアントごとにセッションを持つステートフルなモデル(Mcp-Session-Id)で、SDK は 2025-11-25 までのリビジョンでこのモデルを提供します。2026-07-28 のリクエストには JSON-RPC エラー -32022(サポートされていないプロトコルバージョン。v0.12.718 までのリリースでは単なる HTTP 400)が返され、その data.supported にはハンドシェイク方式のリビジョンが列挙されます。server/discover も同じ内容を公開します。そのため、クライアントは下位のリビジョンでネゴシエーションし、既存の HTTP 連携はセッションと承認リクエストを変わらず維持します。HTTP で 2026-07-28 をネイティブに提供するには、server.stateless を設定します(または、後述のとおりリビジョンを 2026-07-28 に固定します)。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "stateless": true}}'
セッションレスのサーバーは Mcp-Session-Id を発行せず、GET と DELETE には 405 を返し(破棄するセッションがないため)、tools/list、prompts/list、resources/list の結果を接続に依存しないものに保ち、承認のラウンドトリップを input_required で処理します。古いクライアントの initialize も引き続き受け付け、読み取りも提供します。ただし、そのクライアントが初期化時に宣言したエリシテーション(elicitation)機能を保持できません(リクエストごとに一時的なセッションが割り当てられるため)。そのため、セッションレスのサーバーでは、古いクライアントは承認が必要な書き込みを承認できません。現行リビジョンのホストには stateless を、古いクライアントがまだ含まれる環境にはデフォルトを選択してください。
サーバーは呼び出しをまたぐ状態を保持しません。モード、監査、プロバイダーの認証情報はプロセスレベルの設定であるため、明示的なハンドルの背後に移す必要のあるものはありません。
リビジョンの固定
デフォルトでは、サーバーはサポートされているすべてのリビジョンを公開し、クライアントごとにネゴシエーションします。--mcp.protocol.version フラグ、または設定オブジェクトの server.protocol_version(フラグが優先されます)で、公開する最新のリビジョンを設定します。
# sessionless only; stateless Streamable HTTP is implied
stackql mcp \
--mcp.server.type=http \
--mcp.protocol.version=2026-07-28 \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}'
# handshake lifecycle only
stackql mcp --mcp.server.type=stdio --mcp.protocol.version=2025-11-25
| 値 | 公開されるリビジョン | 効果 |
|---|---|---|
auto(デフォルト)または未指定 | サポートされているすべてのリビジョン。 | 上記のとおりネゴシエーションします。双方が対応する最も新しいリビジョンが選ばれます。 |
2026-07-28 | 2026-07-28 のみ。 | セッションレスのみで、Streamable HTTP では stateless が暗黙的に有効になります。古いクライアントの initialize には 2025-11-25 が返されます。これは、そのレスポンスを新しいライフサイクルとして解釈せず、切断するようクライアントに促す合図です。 |
2025-11-25(またはそれより古いリビジョン) | そのリビジョンとそれ以前のすべてのリビジョン。 | ハンドシェイク方式のライフサイクルのみ:2026-07-28 のリクエストには、公開リビジョンを data.supported に列挙した JSON-RPC エラー -32022 が返されるため、クライアントは再ネゴシエーションできます。古いハンドシェイク方式のクライアントは自身のリビジョンを維持します。 |
それ以外の値は起動時の設定検証で失敗し、エラーには有効な値が示されます。
トランスポートの制限
Streamable HTTP のリクエストボディの上限は 4 MiB(超えると HTTP 413)、1000 階層より深くネストされた JSON は解析前に拒否され、stdio の 1 フレームの上限は 8 MiB です。これらの制限はいずれも設定できません。いずれも、サーバーが受け付ける SQL 文よりはるかに大きな値です。
認証情報の(再)読み込み(--env.file + reload_credentials)
--env.file と reload_credentials ツールは StackQL v0.10.542 より後のリリースで利用できます。
プロセスの環境ブロックは起動時に固定されます。このため、MCP サーバーには 2 つの問題が生じます。
- 認証情報の環境変数がない状態でデスクトップクライアント(Claude Desktop、Cursor など)から起動された MCP
stdioサーバーは、それらの変数を参照できません。クライアントは自身の環境をサブプロセスに渡すためです。 - ローテーションされた短期間有効な認証情報は、長時間実行されているサーバーセッションに反映されません。
--env.file フラグは、変更可能な認証情報ストアとして機能する dotenv 形式のファイルを指定することで、両方の問題を解消します。
stackql mcp --mcp.server.type=stdio --env.file /path/to/stackql-credentials.env
読み込みのセマンティクス
このファイルは、すべてのエントリポイント(exec、shell、srv、registry、mcp)で起動時にプロセス環境に読み込まれます。
- フラグが空または未設定の場合は何も行われません。認証情報はリクエスト時にプロセス環境から遅延解決され、従来の動作とまったく同じです。
- 指定したパスにファイルが存在しない場合は、何もせずに許容されます(ファイルは後から作成できます)。
- 形式が不正なファイルや読み取れないファイルは、起動時の致命的なエラーになります。
- 値が空でないキーのみが設定されます。既存のプロセス環境変数は上書きされます(ファイルが信頼できる唯一の情報源です)。設定が解除されることはありません。
- このフラグはコマンドラインでのみ指定できます。
.stackqlrcからは読み込まれません。
ファイル形式は 1 行に 1 つの KEY=VALUE です。# コメント、空行、省略可能な export プレフィックス、値を囲む省略可能な一重引用符または二重引用符、CRLF 改行はすべて許容されます。
# stackql-credentials.env
export OKTA_SECRET_KEY="00abc...xyz"
STACKQL_GITHUB_USERNAME=myuser
STACKQL_GITHUB_PASSWORD='ghp_mytoken'
reload_credentials
reload_credentials ツールは、セッションの途中で --env.file のファイルをプロセス環境に再読み込みし、プロバイダーごとの認証情報の解決状況を報告します。シークレットの値は返されず、ログにも監査にも記録されません。記録されるのは名前とステータスのみです。--env.file が設定されていない場合、このツールは単なるステータス確認になります。
認証情報の解決でクエリが失敗すると、MCP エラーには reload_credentials を呼び出して再試行するようエージェントに指示するヒントが含まれます。そのため、エージェント型のクライアントは自己回復します。認証情報をファイルに書き込み、エージェントに再読み込みを依頼すれば、失敗したクエリは再試行で成功します。サーバーの再起動は不要です。
reload_credentials は reverse_proxy バックエンドモードではサポートされていません。クエリはリモートの stackql サーバープロセスで実行されるため、このツールはバックエンドのサーバーで再読み込みするようユーザーに指示するエラーを返します。
Windows と Claude Desktop
setx が書き込むのはレジストリであり、実行中のプロセスではありません。また、Claude Desktop は自身の(古い)環境を MCP サブプロセスに渡します。そのため、認証情報を変更するには通常 Claude Desktop を完全に再起動する必要があります。--env.file を使用すると、認証情報ファイルはいつでも作成またはローテーションでき、reload_credentials が再起動なしでそれを読み込みます。設定例については、Claude Desktop で StackQL を使用するを参照してください。
HTTP クライアント認証
server.auth_token_env_var と server.allow_unauthenticated は StackQL v0.12.742 以降で利用できます。
HTTP トランスポートにはクライアント認証が必要です。server.auth_token_env_var には、事前共有された Bearer トークンを保持する環境変数の名前を指定します。すべてのリクエストには Authorization: Bearer <token> が必要で、ない場合は 401 が返されます。トークンは環境から読み取られるため、--mcp.config やプロセスの引数に現れることはありません。
export STACKQL_MCP_TOKEN="$(openssl rand -hex 32)"
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "auth_token_env_var": "STACKQL_MCP_TOKEN"}}'
トークンなしでの提供は明示的なオプトインです。server に "allow_unauthenticated": true を設定してください。どちらのキーもない場合、サーバーは両方のキーを示すメッセージを出して起動時に終了します。トークンの変数が未設定または空の場合も終了します。v0.12.742 リリース以降、http トランスポートを使用する場合は、server に auth_token_env_var または "allow_unauthenticated": true のいずれかを追加する必要があります。
TLS(tls_cert_file / tls_key_file)はトランスポートを暗号化しますが、クライアントを認証しません。ループバック以外のリスナーでは、TLS とトークンを組み合わせてください。クロスオリジンのブラウザーリクエスト(Origin の不一致、またはクロスサイトの Sec-Fetch-Site)は、認証の有無にかかわらず 403 で拒否されます。同梱の stackql_mcp_client は Authorization ヘッダーを送信しないため、これを使用するサーバーは認証なしの提供にオプトインする必要があります。
v1.0 以降、--access.config を指定してサーバーを起動すると、共有トークンによるゲートが呼び出し元ごとの認証に置き換わります。各 HTTPS リクエストは、設定された JWT、静的 Bearer トークン、または相互 TLS の方式で検証され、ポリシールールに照らして認可されます。この場合、サーバーの TLS は必須で、HTTP 経由の local_os 認証は拒否されます。また、認証情報のないリクエストがサーバーの環境トークンにフォールバックすることはありません。アクセス管理は reverse_proxy サーバータイプでは利用できません。
サーバーモード
server.mode で 4 つの安全コントラクトのいずれかを選択します。4 つすべてで SELECT とメタデータの読み取りが許可されます。違いはミューテーションとライフサイクル操作の扱いです。
| モード | SELECT / メタデータ | INSERT / UPDATE / REPLACE | DELETE | EXEC(ライフサイクル) |
|---|---|---|---|---|
read_only | 許可 | 拒否 | 拒否 | 拒否 |
safe(デフォルト) | 許可 | 承認が必要 | 承認が必要 | 承認が必要 |
delete_safe | 許可 | 許可 | 承認が必要 | 承認が必要 |
full_access | 許可 | 許可 | 許可 | 許可 |
拒否の場合は、クライアントに即座にエラーが返されます。
承認が必要の場合は、ネゴシエーションされたプロトコルリビジョンに応じた MCP エリシテーションフローが使用されます。
- クライアントがエリシテーション機能を公開している場合(初期化時、または
2026-07-28ではリクエストごとの_metaのクライアント機能で)、サーバーは短いメッセージ(ツール名、クエリクラス、SQL)で操作の承認をユーザーに求めます。2026-07-28では、承認リクエストは IDstackql_approvalのelicitation/create入力リクエストを含むinput_required結果として返され、クライアントは回答をinputResponsesに入れて呼び出しを再試行します。それより前のリビジョンでは、サーバーが呼び出しの途中でelicitation/createリクエストを自ら送信します。ユーザーは承認、拒否、またはキャンセルします。 - クライアントがエリシテーションを公開していない場合、ツールは拒否され、その理由を説明し運用者に
full_accessモードを案内するメッセージが返されます。
承認にはクライアントが応答するため、承認はエージェントがユーザーの関与なしに動作することを防ぐものであり、信頼できない呼び出し元を防ぐものではありません。呼び出し元が信頼できない場合は、HTTP トランスポートにクライアント認証を組み合わせてください。
モードはサーバーごとにグローバルです。ツールごとの上書きはありません。
v1.0 以降、run_select_query は full_access を含むすべてのモードで INSERT、UPDATE、REPLACE、DELETE、EXEC を拒否し、エラーでは run_mutation_query または run_lifecycle_operation が示されます。また、すべてのツールには title と、4 つの MCP 動作ヒントが明示的なブール値として付与されます(readOnlyHint、destructiveHint、idempotentHint、openWorldHint)。これらは、ポリシーゲートが適用するのと同じ分類から導出されます。openWorldHint は、レジストリまたはプロバイダーのエンドポイントにアクセスする list_registry、pull_provider、run_select_query、run_mutation_query、run_lifecycle_operation では true、ローカルの状態のみを読み取るツールでは false です。ヒントはクライアントの UX 向けの参考情報であり、強制は引き続きポリシーゲートが行います。
リリース v0.12.742 以降、複数の文を含むペイロードは、すべてのモードで最も権限の高い文によってゲート制御されます。そのため、SELECT 1; DELETE ... は DELETE として扱われ、監査レコードの query_class は mutation_delete になります。validate_select_query は 1 つの文のみを受け付けます。
デフォルトモードの動作変更
以前のリリースでは、安全性は単一の read_only: true/false フラグでのみ適用され、そのデフォルトは「適用なし」でした。現在のデフォルト(mode: safe)では、初期状態でミューテーションにユーザーの承認が必要です。エリシテーションに対応したクライアント(Claude Desktop、Cursor、Continue など)を使用している運用者には、ミューテーションごとに 1 回の承認リクエストが表示されます。自動化を実行している運用者や、同梱の stackql_mcp_client(エリシテーションを公開しません)を使用している運用者は、ミューテーションとライフサイクル操作を実行するために mode: full_access に明示的にオプトインする必要があります。
レガシーの read_only: true JSON / YAML キーは後方互換性のために引き続き受け付けられ、mode: read_only と同等に扱われます。
例
# Read-only: SELECTs proceed; mutations and lifecycle refused immediately.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "read_only"}}'
# Delete-safe: INSERT/UPDATE proceed; DELETE and EXEC need approval.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "delete_safe"}}'
# Full access: everything proceeds without prompting. Use only with trusted
# clients and operators.
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "mode": "full_access"}}'
監査ログ
すべてのツール呼び出しは、設定された監査シンクに 1 件のレコードを書き込みます。形式はデフォルトで JSONL、または OpenTelemetry ログレコードです(ログ形式を参照)。監査はデフォルトで有効です。監査が答えるのは「エージェントが何をしたか」であり、「エージェントが何を見たか」ではありません。SELECT 文の結果行は、どちらの形式でも意図的に記録されません。
記録される内容
| フィールド | 説明 |
|---|---|
timestamp | 呼び出し開始時刻(RFC3339)。 |
tool | ツール名(例:run_select_query)。 |
mode | 呼び出し時に有効なサーバーモード。 |
decision | allow / refuse_immediate / needs_approval_accepted / needs_approval_declined / needs_approval_cancelled / needs_approval_unavailable. |
query_class | select / mutation_create / mutation_delete / lifecycle / unknown。複数の文を含むペイロードでは、最も権限の高い文のクラス。 |
sql | クエリツール(run_select_query、run_mutation_query、run_lifecycle_operation、validate_select_query)の SQL 文字列。 |
args | メタデータツール(list_*、describe_method)では階層フィールド、クエリツールでは SQL + row_limit。 |
duration_ms | ゲート + ハンドラーの実経過時間。 |
error | ツールがエラーになった場合、または拒否された場合のエラーメッセージ。 |
SELECT 文の結果行は意図的に除外されています。結果行は非常に大きくなる可能性があり、機密データを含む場合もあるためです。
ファイルシンク
現在提供されているシンクは file のみです。1 行に 1 つの JSON オブジェクトを書き込み、レコードごとに fsync し、サイズ / 経過日数 / バックアップ数に基づく lumberjack 方式のローテーションを行います。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"allow_unauthenticated": true,
"audit": {
"file": {
"path": "/var/log/stackql-mcp.log",
"max_size_mb": 100,
"max_backups": 5,
"max_age_days": 30
}
}
}
}'
場所は 2 つの方法で指定できます。
audit.file.path:完全なファイルパス(絶対パス、または cwd からの相対パス)。audit.file.dir:ディレクトリ。シンクはその中のベース名としてstackql_mcp_server_<RFC3339-utc-second>.logを選択します。
mcp.config でどちらも設定されていない場合、MCP サーバーは dir のデフォルトを cwd にするため、既存の運用者には従来と同じ動作になります。基盤となる汎用シンクパッケージ自体は、ディレクトリを暗黙に選択することを拒否します。「ログをどこに出力するか」は常に呼び出し元が決定します。
解決された絶対パスは、起動時に sink file: /path/to/file.log として stderr にログ出力されます。
ログ形式
監査ストリームには 2 つのエンコーディングがあり、どちらも同じファイルシンクに書き込まれます。
stackql mcp --mcp.server.type=stdio --mcp.log.format=jsonl # default, unchanged
stackql mcp --mcp.server.type=stdio --mcp.log.format=otel # OTLP/JSON log records
このフラグは mcp.config の server.audit.format("audit": {"format": "otel"})より優先されます。jsonl は上記のレコードとバイト単位で互換性があります。otel は 1 行に 1 つの OTLP/JSON LogsData オブジェクトを書き込みます。これは OpenTelemetry Collector の otlp_json_file レシーバーがそのまま取り込める形式であるため(otelcol-contrib 0.160.0 で検証済み)、ストリームは transform プロセッサーなしで任意の OTLP パイプラインに届きます。
receivers:
otlp_json_file:
include: [/var/log/stackql-mcp.log]
exporters:
debug: {}
service:
pipelines:
logs:
receivers: [otlp_json_file]
exporters: [debug]
各ツール呼び出しは 1 件のログレコードを生成します。承認ゲートを通過した呼び出しでは、エリシテーションの決定について 2 件目のレコードが生成されます。1 回の呼び出しのレコードは gen_ai.tool.call.id とトレース ID を共有します。呼び出し元が params._meta で W3C traceparent を指定した場合はそれが使用されます。指定がない場合は MCP セッションごとに 1 つのトレース ID が生成されるため、エージェントのセッションのレコードを関連付けることができます。
出力される属性セットはバージョン管理されたインターフェイスです。インストルメンテーションスコープは github.com/stackql/stackql/pkg/mcp_server/audit(バージョン 1.0.0)で、schemaUrl は安定版の規約を https://opentelemetry.io/schemas/1.44.0 に固定します。gen_ai.* と mcp.* の属性は GenAI および MCP のセマンティック規約に従います。これらの規約は Development ステータスです。属性セットが変更されるとスコープのバージョンが上がります。
| 属性 | レコード | 値 |
|---|---|---|
service.name、service.version | リソース | stackql、StackQL のバージョン |
gen_ai.operation.name | ツール呼び出し | execute_tool |
mcp.method.name | 両方 | ツール呼び出しレコードでは tools/call、決定レコードでは elicitation/create |
gen_ai.tool.name | 両方 | ツール名 |
gen_ai.tool.call.id | 両方 | 呼び出しごとに生成され、両方のレコードで共有 |
mcp.protocol.version | 両方 | ネゴシエーションされたリビジョン |
mcp.session.id | 両方 | セッション ID(セッションレスの HTTP リクエストでは存在しない) |
stackql.mode | 両方 | サーバーモード |
stackql.decision | 両方 | 上の表の decision の値 |
stackql.query | ツール呼び出し | クエリツールの場合、そのままの SQL |
stackql.query_class | ツール呼び出し | query_class の値 |
stackql.provider | ツール呼び出し | メタデータツールの場合、プロバイダー |
stackql.query.source | ツール呼び出し | 指定された場合、Query Library のエントリ ID |
stackql.duration_ms | ツール呼び出し | 実経過時間 |
stackql.rows_returned | ツール呼び出し | 行を返すツールの場合、行数 |
error.type、error.message | ツール呼び出し | 失敗時:拒否した決定、またはゲート通過後の場合は tool_error |
Body は execute_tool <tool> / elicitation <tool> で、重大度は INFO、呼び出しが失敗または拒否された場合は ERROR です。秘匿化のコントラクトはどちらの形式でも同じです。結果の値はシリアル化されず、その結果を生成した文のみがシリアル化されます。
障害モード
シンクがエラーを返した場合のレスポンスの動作は、audit.failure_mode によって決まります。
| failure_mode | 効果 |
|---|---|
strict(デフォルト) | 基になるツールが成功した場合でも、ツール呼び出しはクライアントに監査エラーを返します。これは意図的な動作です。検出されない DELETE よりも、クライアントへの曖昧なレスポンスのほうが望ましいためです。 |
strict_mutations | SELECT / メタデータの読み取りは stderr に注記を出力して続行し、ミューテーションとライフサイクル操作は監査エラーを返します。 |
best_effort | 常に stderr にログを出力して続行します。 |
実行順序
監査の書き込みは、ツールの実行(またはゲートによる除外)の後、クライアントにレスポンスが返される前に行われます。strict モードでは、成功した DELETE で監査の書き込みが失敗すると、行は削除されていてもクライアントはエラーを受け取ります。これは、監査されないままのミューテーションが発生しないようにするための設計です。
監査の無効化
監査を完全に無効にするには、次のように設定します(PR2 より前の動作)。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true, "audit": {"disabled": true}}}'
利用可能な MCP ツール
MCP サーバーとして実行すると、StackQL は設定された enabled_tools 許可リストの範囲で次のツールを公開します。各ツールは、レンダリングされたテキストビュー(LLM 向け)と型付きの構造化ペイロード(プログラムから利用するクライアント向け)の両方を返します。デフォルトのテキストレンダリングは、複数行の均一な結果では markdown の表、まばらな結果や単一レコードの結果では markdown の KV ブロックです。引数を持つツールは、省略可能な format(markdown または json)による上書きを受け付けます。指定しない場合はサーバーのレンダリング設定が使用されます。以下の入力はタスク固有の引数を示し、? は省略可能な入力を表します。
ツール名をクリックすると、入力、ゲート制御の動作、プロンプトの例を含む完全なリファレンスページが表示されます。
| ツール | レンダラー | 説明 | 入力 |
|---|---|---|---|
server_info | KV | サーバーの識別情報とランタイム:stackql のバージョン、基盤の SQL エンジン、プロバイダーレジストリの場所、モード、読み取り専用フラグ。セッション開始時に 1 回呼び出します。 | なし |
list_providers | テーブル | ローカルキャッシュにプル済みのプロバイダー(階層の最上位)。 | なし |
list_services | テーブル | プロバイダー配下のサービス。 | provider |
list_resources | テーブル | provider.service 配下のリソース。 | provider, service |
list_methods | テーブル | リソースのアクセスメソッド(HTTP 操作)と、それぞれが対応する SQL 動詞および必須パラメーター。クエリを書く前に呼び出します。必須の WHERE パラメーターはここから推定されます。 | provider, service, resource |
describe_method | KV | 1 つのメソッドの完全な I/O コントラクト(常に EXTENDED):必須および省略可能な入力と、SELECT が参照できる出力フィールド。 | provider, service, resource, method |
query_library_search | テーブル | 自然言語の意図から厳選されたクエリテンプレートを検索します。読み取り専用です。ミューテーションのエントリはオプトインが必要で、read_only モードでは除外されます。 | intent, provider?, service?, tags?, include_mutations?, limit? |
query_library_get | KV | テンプレートとそのパラメーター宣言を取得します。params が空でない場合は、値を検証し、実行せずにレンダリングされた SQL と next_tool を返します。 | id, params? |
validate_select_query | KV | 単一の SELECT を実行せずに解析し、計画を作成します。{valid, errors} を返します。SELECT のみで、文は 1 つだけです。 | sql |
run_select_query | テーブル | SELECT を実行します。{rows} を返します。読み取りのみ。 | sql, row_limit? |
run_mutation_query | KV | プロバイダーに対して INSERT/UPDATE/REPLACE/DELETE を実行します。実際の副作用があります。 {messages, timestamp} を返します。サーバーのモードによってゲート制御されます。 | sql |
run_lifecycle_operation | KV | stackql の EXEC ライフサイクル操作を実行します。{messages, timestamp} を返します。サーバーのモードによってゲート制御されます。 | sql |
list_registry | テーブル | 設定されたレジストリで利用可能なプロバイダー(とそのバージョン)。プル済みのプロバイダーのみを一覧表示する list_providers とは異なります。 | provider? |
pull_provider | KV | レジストリから 1 つのプロバイダーをローカルキャッシュにインストールします。影響はローカルキャッシュの状態のみで、クラウドのコントロールプレーンやデータプレーンには影響しません。 | provider, version? |
reload_credentials | テーブル | --env.file の dotenv ファイルから認証情報をプロセス環境に再読み込みし、プロバイダーごとの解決状況(ok、unresolved、not_checked)を報告します。シークレットの値は返しません。すべてのモードで許可されます。 | provider? |
SQL を一から書く前に query_library_search を確認し、次に query_library_get を使用して一致するテンプレートを確認し、レンダリングしてください。クエリツールは、ライブラリのエントリ ID を含む省略可能な source も受け付けます。これは帰属を示すためだけのもので、実行には通常のサーバーモードと承認ポリシーが引き続き適用されます。
describe_resource は StackQL v0.12.732 で廃止されました。これを呼び出していた MCP クライアント、プロンプト、エージェントの指示は、代わりに list_methods を呼び出し、続けて describe_method を呼び出してください。各アクセスメソッドが独自の形式を返すため、リソースには単一のフィールドリストがありません。そのため、列名は、クエリのルーティング先のメソッドに対する describe_method から取得します。SQL の DESCRIBE 文は変更されていません。
利用可能な MCP プロンプト
静的なプロンプトが 1 つ公開されています。
| プロンプト | 説明 |
|---|---|
write_safe_select | stackql のリソースに対して安全な SELECT クエリを書くためのガイダンス。SHOW METHODS IN <provider>.<service>.<resource> を使用して、適切な読み取りメソッドと必須の WHERE パラメーターを見つける方法を説明します。 |
フラグ
| フラグ | 説明 |
|---|---|
--mcp.server.type | MCP サーバータイプ:http、stdio、または reverse_proxy(後者は stackql srv と組み合わせて使用)。 |
--mcp.config | MCP サーバーの JSON 設定オブジェクト。YAML も受け付けます。 |
--mcp.protocol.version | 公開する最新のプロトコルリビジョン:auto(デフォルト)、2026-07-28、または 2025-11-25 などの古いリビジョン。リビジョンの固定を参照してください。 |
--env.file | 起動時に読み込まれ、reload_credentials ツールによって必要に応じて再読み込みされる dotenv 形式の認証情報ファイル。認証情報の(再)読み込みを参照してください。 |
--pgsrv.port | PostgreSQL ワイヤプロトコルサーバーの TCP ポート(stackql srv と組み合わせて使用)。 |
-H, --help | ヘルプ情報を表示します。 |
-v, --verbose | 追加の出力を含む詳細モードで実行します。 |
その他のオプションについては、グローバルフラグを参照してください
MCP サーバーを起動する前に、プロバイダーの認証に必要な環境変数を設定するか、--env.file で dotenv 形式の認証情報ファイルを指定する必要があります。詳細については、プロバイダーの使用を参照してください。
例
基本的なスタンドアロン MCP サーバー
プロバイダーの認証と、クライアント用の Bearer トークンを設定して、スタンドアロン MCP サーバーを起動します。
export GOOGLE_CREDENTIALS=$(cat /path/to/google-credentials.json)
export STACKQL_MCP_TOKEN="$(openssl rand -hex 32)"
stackql mcp \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "auth_token_env_var": "STACKQL_MCP_TOKEN"}}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'
MCP サーバーと PostgreSQL サーバー(インメモリ)
MCP サーバーと PostgreSQL サーバーの両方を実行し、2 つのプロトコルでアクセスできるようにします。
export GOOGLE_CREDENTIALS=$(cat /path/to/google-credentials.json)
stackql srv \
--mcp.server.type=http \
--mcp.config '{"server": {"transport": "http", "address": "127.0.0.1:9912", "allow_unauthenticated": true}}' \
--pgsrv.port 5665 \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'
既知のパスに監査ログを出力する読み取り専用のインベントリサーバー
変更を一切行わないインベントリスキャン用のエージェントに適しています。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"allow_unauthenticated": true,
"mode": "read_only",
"audit": {"file": {"path": "/var/log/stackql-mcp-audit.log"}}
}
}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'
フルアクセスの自動化サーバー
ミューテーションが必要で、エリシテーションリクエストに応答できない、信頼できる自動化パイプライン向けです。パイプラインは STACKQL_MCP_TOKEN に保持された Bearer トークンを提示します。
stackql mcp \
--mcp.server.type=http \
--mcp.config '{
"server": {
"transport": "http",
"address": "127.0.0.1:9912",
"auth_token_env_var": "STACKQL_MCP_TOKEN",
"mode": "full_access"
}
}' \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'
TLS を使用したセキュアな MCP サーバー
リバースプロキシモードで、TLS 暗号化を有効にした MCP サーバーを起動します。
まず、TLS 証明書を生成します(開発用の自己署名証明書)。
openssl req -x509 -newkey rsa:4096 -keyout server_key.pem -out server_cert.pem -days 365 -nodes
次に、サーバーを起動します。
stackql srv \
--mcp.server.type=reverse_proxy \
--mcp.config '{
"server": {
"tls_cert_file": "server_cert.pem",
"tls_key_file": "server_key.pem",
"transport": "http",
"address": "127.0.0.1:9004",
"auth_token_env_var": "STACKQL_MCP_TOKEN"
},
"backend": {
"dsn": "postgres://stackql:stackql@127.0.0.1:5446?default_query_exec_mode=simple_protocol"
}
}' \
--pgsrv.port 5446 \
--registry='{"url": "https://registry.stackql.io/providers"}' \
--auth='{"google": {"type": "service_account", "credentialsfilepath": "/path/to/google-credentials.json"}}'
MCP サーバーのテスト
リポジトリには、スクリプトや回帰テスト用の開発用 MCP クライアント(stackql_mcp_client)が含まれています。次のコマンドでビルドします。
python cicd/python/build.py --build-mcp-client
これにより ./build/stackql_mcp_client が生成されます。
stackql_mcp_client は Authorization ヘッダーを送信しないため、対象のサーバーでは "allow_unauthenticated": true を設定する必要があります(上記の例のとおり)。トークンで保護されたサーバーは 401 を返します。また、MCP のエリシテーション機能も公開しません。非対話型のスクリプト用だからです。safe または delete_safe のサーバーに対しては、ミューテーションとライフサイクルの呼び出しで「client does not support elicitation」による拒否を受け取ります。エリシテーションリクエストを使用した対話型のテストには、エディターに組み込まれた MCP クライアント(Claude Desktop、Cursor、Continue)を使用してください。
# List all available tools
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912
# Server identity, mode, audit / registry context
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action server_info
# Re-source the --env.file credentials file and report per-provider
# credential status - a good first diagnostic when queries fail on auth
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action reload_credentials
# List providers already pulled into the local cache
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_providers
# List providers (and versions) available in the registry
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_registry
# Install a provider from the registry into the local cache
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action pull_provider \
--exec.args '{"provider": "kafka"}'
# List services for a provider
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_services \
--exec.args '{"provider": "google"}'
# List access methods for a resource (this is how an agent finds required
# WHERE parameters before writing a query)
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action list_methods \
--exec.args '{"provider": "google", "service": "compute", "resource": "networks"}'
# Validate a SELECT without executing
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action validate_select_query \
--exec.args '{"sql": "select name from google.compute.networks where project = '"'"'my-project'"'"';"}'
# Execute a SELECT
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action run_select_query \
--exec.args '{"sql": "select name from google.compute.networks where project = '"'"'my-project'"'"';"}'
# Mutation - succeeds only against a full_access server, or against
# delete_safe (for INSERT/UPDATE) or safe with an elicitation-capable client.
./build/stackql_mcp_client exec \
--client-type=http \
--url=http://127.0.0.1:9912 \
--exec.action run_mutation_query \
--exec.args '{"sql": "delete from google.compute.firewalls where project = '"'"'my-project'"'"' and firewall = '"'"'old-rule'"'"';"}'
レスポンスの例
server_info(デフォルトモードのサーバーに対して):
{
"version": "0.10.444",
"commit": "abc1234",
"build_date": "2026-05-16T10:47:33Z",
"platform": "linux/amd64",
"transport": "http",
"sql_backend": "sqlite3",
"provider_registry": "https://registry.stackql.io/providers",
"mode": "safe",
"is_read_only": false
}
run_select_query:
{
"rows": [
{"name": "default"},
{"name": "pathfinders-test-01"},
{"name": "returning-test-03"}
]
}
run_mutation_query(full_access サーバーに対して):
{
"messages": ["The operation was despatched successfully"],
"timestamp": "2026-05-16T10:47:33+10:00 AEST"
}
同じミューテーションの監査ログ行の例:
{"timestamp":"2026-05-16T00:47:33Z","tool":"run_mutation_query","mode":"full_access","decision":"allow","query_class":"mutation_delete","sql":"delete from google.compute.firewalls where project = 'my-project' and firewall = 'old-rule';","args":{"sql":"delete from google.compute.firewalls where project = 'my-project' and firewall = 'old-rule';","row_limit":0},"duration_ms":42}
AI アシスタントとの統合
StackQL の MCP サーバーを AI アシスタントと統合するには、アシスタントの設定で stackql を MCP サーバーとして登録します。エディターに組み込まれたほとんどの MCP クライアントは、stdio 経由でサーバーを実行します。その場合は --mcp.server.type=stdio を使用し、アシスタントがプロセスを直接起動します。HTTP に対応したスタンドアロンのエージェントは、長時間実行されている stackql mcp --mcp.server.type=http プロセスに接続できます。
Claude Desktop については、Anthropic Connector Directory への掲載(推奨されるインストール方法)、ダウンロード可能な MCP Bundle(.mcpb)、手動設定を含め、Claude Desktop で StackQL を使用するを参照してください。
設定ファイルの場所は、オペレーティングシステムと AI アシスタントによって異なります。正しいパスと形式については、AI アシスタントのドキュメントを参照してください。
アーキテクチャに関する考慮事項
デプロイモードを選択する際は、次の点を考慮してください。
- スタンドアロン(
stackql mcp):最もシンプルな構成で、開発や、stdio経由のエディター組み込みクライアントに最適です。 - インメモリのデュアルサーバー(
mcp.server.type=httpを指定したstackql srv):1 つのプロセスで MCP と PostgreSQL ワイヤプロトコルの両方を提供します。最高のパフォーマンスが得られ、ほとんどの本番デプロイに適しています。 - リバースプロキシ(
mcp.server.type=reverse_proxyを指定したstackql srv):- プロセスやホストをまたいだワークロードの分離が可能
- セキュアな MCP エンドポイントのための TLS 暗号化をサポート
- MCP と PostgreSQL のインターフェイスを個別にスケーリング可能
- エンタープライズ CA との統合に柔軟に対応(注:エンタープライズ CA のサポートは実験的機能)
また、安全性については次の点を考慮してください。
- デフォルトの
mode: safeから始めてください。エリシテーションに対応したクライアント(Claude Desktop、Cursor、Continue)は、ミューテーションの前にユーザーに確認を求めます。 - 書き込みを行うべきでないインベントリ用や分析用のエージェントには、
mode: read_onlyを固定します。 - 作成や更新は自由に行いたいが、破壊的な操作には人間の確認を挟みたい場合は、
mode: delete_safeを固定します。 mode: full_accessは信頼できる自動化パイプライン専用とし、誰かがレビューする監査ログと組み合わせる場合にのみ使用します。- 他のプロセスやホストから到達できる HTTP リスナーには、
server.auth_token_env_varを設定します。allow_unauthenticatedはローカル開発用です。TLS だけではクライアントは認証されません。
エンタープライズ認証局(CA)で TLS を使用する場合は、追加の設定が必要になることがあります。この機能は実験的なもので、使用する CA の実装に応じて調整が必要になる場合があります。
参考資料
- パッケージ開発者向けのリファレンスは、stackql リポジトリの
pkg/mcp_serverREADME です。 - コントリビューター向けの技術ドキュメントは stackql リポジトリの
docs/mcp.mdにあり、すべてのツールについてのレスポンス例が含まれています。