mcpField
L
Lagaam

Lagaam

ローカル
github.comデータベース13 週間前に更新

Lagaam について

Lagaamは、共有データクラスター上のクエリを制御する、TrinoとApache Pinot向けのMCPサーバーです。実行前にテーブル権限とクエリコストを確認し、呼び出しを監査します。

主な機能

  1. 01実行前のクエリコスト確認
  2. 02テーブル単位のアクセス許可
  3. 03読み取り専用SQLの検証
  4. 04結果の検証と件数制限
  5. 05JSONL監査ログの記録

活用シーン

  1. 01高コストなスキャンや結合の防止
  2. 02エージェントの許可テーブルへの制限
  3. 03監査ログでのクエリ判定確認

MCP 対応

MCPクライアントに list_catalogs、describe_table、query_data のツールを公開し、これら以外の方法でエージェントがデータベースへアクセスできないようにします。

設定

ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。

mcp.json · 共通設定
{
"mcpServers": {
"lagaam-ai-lagaam": {
"command": "uvx",
"args": [
"lagaam"
],
"env": {
"LAGAAM_ALLOWED_TABLES": "<LAGAAM_ALLOWED_TABLES>",
"LAGAAM_ALLOW_ALL_TABLES": "<LAGAAM_ALLOW_ALL_TABLES>",
"LAGAAM_ENGINE": "<LAGAAM_ENGINE>",
"TRINO_HOST": "<TRINO_HOST>",
"TRINO_PORT": "<TRINO_PORT>",
"TRINO_USER": "<TRINO_USER>",
"PINOT_CONTROLLER_URL": "<PINOT_CONTROLLER_URL>",
"PINOT_BROKER_URL": "<PINOT_BROKER_URL>",
"PINOT_USER": "<PINOT_USER>",
"PINOT_PASSWORD": "<PINOT_PASSWORD>",
"LAGAAM_AGENT_NAME": "<LAGAAM_AGENT_NAME>",
"LAGAAM_MAX_SCAN_BYTES": "<LAGAAM_MAX_SCAN_BYTES>",
"LAGAAM_MAX_ROWS": "<LAGAAM_MAX_ROWS>",
"LAGAAM_MAX_INTERMEDIATE_ROWS": "<LAGAAM_MAX_INTERMEDIATE_ROWS>",
"LAGAAM_MAX_RETURNED_ROWS": "<LAGAAM_MAX_RETURNED_ROWS>",
"LAGAAM_QUERY_TIMEOUT": "<LAGAAM_QUERY_TIMEOUT>",
"LAGAAM_METADATA_TTL": "<LAGAAM_METADATA_TTL>",
"LAGAAM_AUDIT_LOG": "<LAGAAM_AUDIT_LOG>"
}
}
}
}
起動コマンドuvx lagaam
設定が必要な環境変数
LAGAAM_ALLOWED_TABLESComma list of catalog.schema.table grants; the server will not start without it
LAGAAM_ALLOW_ALL_TABLEStrue to run with no grant at all: an explicit opt-out, off by default
LAGAAM_ENGINEWhich adapter to run
TRINO_HOSTTrino coordinator host
TRINO_PORTTrino coordinator port
TRINO_USERTrino user
PINOT_CONTROLLER_URLPinot controller URL
PINOT_BROKER_URLPinot broker URL
PINOT_USERPinot user; unset means no auth
PINOT_PASSWORDシークレットPinot password; unset means no auth
LAGAAM_AGENT_NAMEIdentity stamped on the audit trail
LAGAAM_MAX_SCAN_BYTESScan-bytes budget per query, checked before it runs (default 50 GiB)
LAGAAM_MAX_ROWSScanned-row estimate budget per query; unset means ungated
LAGAAM_MAX_INTERMEDIATE_ROWSRows the engine would build at its widest step, not rows returned, so a LIMIT doesn't lower it
LAGAAM_MAX_RETURNED_ROWSRows returned to the agent per query, capped at 100000; a bigger LIMIT in the query is lowered to it
LAGAAM_QUERY_TIMEOUTWall-clock seconds per query
LAGAAM_METADATA_TTLMetadata cache TTL, seconds
LAGAAM_AUDIT_LOGAudit JSONL file path; unset means stderr

ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。

パッケージ
pypilagaam0.2.5

ツール

ツール一覧はまだ取得されていません

ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。

詳細

Lagaam — 実行前にすべてのクエリの料金を算出

エージェントのクエリひとつで、共有の Trino を止めてはいけません。 クラスターを共有している場合、パーティションフィルターの付け忘れや誤ったクロス結合による損害は、請求額にとどまりません。他のユーザーのクエリにも影響します。Lagaam は、AI エージェントとデータレイクハウス(Trino と Apache Pinot)の間に配置する MCP サーバーです。すべてのクエリはスキーマに基づいて作成され、エンジン独自の実行計画から実行前にコストが算出され、予算と照合されて監査されます。問題のあるクエリは実行前に拒否され、エージェントが対処できる修正案が提示されます。

Lagaam のデモ:SELECT * を拒否し、過大な結合を実行前にブロックし、範囲を限定したクエリを実行

実際のセッション、実際の Trino、モックなし — uv run --project server python examples/demo.py で再現できます。

Lagaam のデモ:フラッシュしきい値に達する Pinot セグメントをコスト算出し、キーのない結合をブロックし、同じ結合を実証済みの upsert キーで許可

実際のセッション、実際の Pinot 1.5.1 リアルタイムテーブル、モックなし — uv run --project server python examples/demo_pinot.py で再現できます。

問題

エージェントは構文的には正しくても、壊滅的な結果を招く SQL を作成します。共有クラスターでは、その被害を受けるのはエージェントだけではありません。パーティションフィルターを付け忘れると全件スキャンになり、すべてのワーカーを占有します。誤ったクロス結合はワーカーのメモリを使い果たし、その間、他のユーザーのクエリは待たされます。リトライループがあれば、同じクエリが再び実行されます。SELECT * は、2列あれば足りるコンテキストウィンドウに40列を読み込みます。通常の解決策は、エージェントにデータベースへのアクセスを一切許可しないことです。

Lagaam なら、制御を効かせたうえでアクセスを許可できます。

  • コストは請求額ではなく、事前の見積もりです。 すべてのクエリは、実行前にエンジン独自の実行計画からコストが算出されます。スキャンするバイト数には EXPLAIN (TYPE IO) を、オペレーターが構築する行数の最大値(クロス結合で膨らみ、LIMIT では隠せない数値)には EXPLAIN (TYPE LOGICAL) を使用します。予算超過の場合は、数値と修正案を示してブロックします。
  • 推定できないクエリは許可されません。 テーブル統計がない場合、自己結合によって推定が崩れる場合、プランナーが把握できないパススルーがある場合は、推測に頼らず安全側に倒してゲートを失敗させます。
  • AST によって読み取り専用を徹底します。 許可されるのは単一の SELECT のみです。DDL/DML、複数ステートメントのインジェクション、SELECT *、テーブル関数のパススルーは許可されず、LIMIT がない場合は挿入されます。検証済みの SQL は再レンダリングされるため、実行されるのは検証された内容と完全に一致します。
  • エージェントは自分で情報を確認できます。 list_catalogs と describe_table は、正確な名前、型、行数の推定値を返します。エージェントに許可されたテーブルの範囲に限定されるため、アクセスを許可されていない名前を知ることはありません。
  • 結果は信頼する前に検証されます。 0件の結果、切り詰められたページ、すべての値が NULL の列がある場合、エージェントには誤解を招く回答を黙って返すのではなく、次の対応を示す警告が提示されます。
  • すべての呼び出しが監査されます。 ツール呼び出しごとに、実行者、内容、許可または拒否の結果、その理由を記録した JSONL 行が1行出力されます。

Trino ですでに制限されているのでは?

Trino はクエリの実行開始後に制限します。Lagaam は実行開始前に拒否します。 両方を併用してください。

動作エージェントに表示される内容読み取り量が少ないクロスジョインも検出するか
query.max-scan-physical-bytes実行中:スキャンしたバイト数が上限に達すると終了クエリの失敗いいえ — 読み取ったバイト数を数えるもので、生成された行数ではありません
query.max-execution-time実行中:指定時間が経過すると終了クエリの失敗その時間だけクラスターを占有した後に限ります
リソースグループ(hardPhysicalDataScanLimit、softMemoryLimit、…)次のクエリから:グループの割り当て分を超えると、新しいクエリはキューに入ります後続のクエリは待機しますいいえ — 実行中のクエリは継続します
Lagaam実行前:EXPLAIN に基づきます数値と対処方法を添えた拒否はい — 最も幅の広いステップで生成される行数を見積もります

Trino 476 での測定結果:SELECT o.orderkey, l.partkey FROM tpch.tiny.orders o CROSS JOIN tpch.tiny.lineitem l LIMIT 10 は、Trino 独自のプランで 676,575 バイトを読み取ります。そのため、スキャン上限が 0.7 MB を超えていれば実行され、902,625,000 行を生成することになります。Lagaam は実行前にこれを拒否します:「このクエリは最も幅の広いステップで 902,625,000 行を生成します。上限の 50,000,000 を超えています……LIMIT では解決しません。個別の値の種類がより多い列で結合するか、結合前に各テーブルを絞り込んでください。」

クラスターに到達したクエリすべてに対する最後の防御策として、リソースグループは引き続き利用できます。Lagaam はエージェントからのトラフィックをその前段で制御します。

ほかのデータベース MCP サーバーはどうですか?

優れたサーバーですが、役割が異なります。エージェントを読み取り専用にし、返されるデータ量を制限します。Lagaam も同じことを行い、さらにクエリを事前に見積もります。

読み取り専用行数の上限タイムアウト実行前にプランを確認
tuannvm/mcp-trinoデフォルトで有効取得中に結果を切り詰めます(TRINO_MAX_ROWS)実行中(TRINO_QUERY_TIMEOUT)いいえ — explain_query はエージェントにプランを表示しますが、execute_query の実行を制御しません
startreedata/mcp-pinot常に有効。実行前に解析します実行前に LIMIT を書き換え、結果をページ分割します実行中(PINOT_QUERY_TIMEOUT、60 s)いいえ
bytebase/dbhubオプトイン(readonly):キーワードのチェックと、データベース独自の読み取り専用トランザクションオプトイン(max_rows)。LIMIT/TOP を挿入しますオプトイン(query_timeout)。実行中いいえ — オプトインの explain_sql はプランを表示しますが、execute_sql の実行を制御しません
Lagaam常に有効。実行前に解析しますデフォルトで 1,000。これを超える LIMIT は実行前に引き下げられます実行中(LAGAAM_QUERY_TIMEOUT、300 s)はい — EXPLAIN に基づくスキャンバイト数と最も幅の広いステップの行数を確認し、上限超過時は拒否します

検出率

LLM エージェントが現実的に生成しうる 11 個のクエリです。全件スキャン、SELECT *、DDL、インジェクションの試行、過大な結合、許可範囲外の読み取りが含まれます。MCP の単純なラッパーは、これらすべてをエンジンに送信します。Lagaam は、適切な範囲に収まる対照クエリはそのまま実行しつつ、11 件すべてを実行前に停止します。 再現方法:benchmarks/catch_rate.py → 結果。

クイックスタート

すでに利用している Trino に接続する場合(TRINO_PORT/TRINO_USER が 8080/lagaam ではない場合):

TRINO_HOST=trino.internal LAGAAM_ALLOWED_TABLES=hive.sales.orders uvx lagaam   # MCP server on stdio

デモ用データウェアハウスで試す場合:

git clone https://github.com/lagaam-ai/lagaam && cd lagaam
docker compose -f examples/docker-compose.yml --profile trino up -d   # demo warehouse
cd server && uv sync
LAGAAM_ALLOWED_TABLES=tpch.tiny.orders,tpch.tiny.lineitem \
  uv run python -m lagaam                                             # MCP server on stdio

Pinot の場合、--profile pinot でバッチ版のクイックスタートが起動し、--profile pinot-realtime up -d で Kafka からデータを取り込むストリーミング版が起動します。その後、examples/pinot-realtime/bootstrap.sh を実行してトピック、テーブル、データフィードを作成してください。次に、LAGAAM_ENGINE=pinot を指定してサーバーを起動します。

任意の MCP クライアント(Claude Code、Claude Desktop、または独自のエージェント)に接続します:

{
  "mcpServers": {
    "lagaam": {
      "command": "uvx",
      "args": ["lagaam"],
      "env": {
        "TRINO_HOST": "localhost",
        "LAGAAM_MAX_SCAN_BYTES": "5368709120",
        "LAGAAM_ALLOWED_TABLES": "hive.sales.orders,hive.sales.customers"
      }
    }
  }
}

Claude Code では、代わりにプラグインとしてインストールします:

/plugin marketplace add lagaam-ai/lagaam
/plugin install lagaam@lagaam

アクセスを許可するテーブル(LAGAAM_ALLOWED_TABLES)と、Trino のホスト、ポート、ユーザーを指定するよう求められます(変更しない場合は localhost/8080/lagaam です)。シェルからは、フラグとして渡します:

claude plugin marketplace add lagaam-ai/lagaam
claude plugin install lagaam@lagaam \
  --config allowed_tables=hive.sales.orders --config trino_host=trino.internal

Pinot の場合は、engine=pinot を選択し、コントローラーとブローカーの URL を設定します(変更しない場合は http://localhost:9000/http://localhost:8000 です):

claude plugin install lagaam@lagaam --config engine=pinot \
  --config allowed_tables=pinot.default.baseballStats \
  --config pinot_controller_url=http://pinot.internal:9000 \
  --config pinot_broker_url=http://pinot.internal:8099

その他の LAGAAM_* 設定と、認証を有効にした Pinot 用の PINOT_USER/PINOT_PASSWORD は、claude を起動した環境から読み込まれます。

エージェントが利用できるツールは list_catalogs、describe_table、query_data の3つで、それ以外の方法でエンジンにアクセスすることはできません。

設定

環境変数意味デフォルト
LAGAAM_ALLOWED_TABLES許可する catalog.schema.table のカンマ区切りリスト必須
LAGAAM_ALLOW_ALL_TABLEStrue にすると、許可リストなしで実行します無効
LAGAAM_AGENT_NAME監査ログに記録される IDanonymous
LAGAAM_MAX_SCAN_BYTESクエリごとの実行前のスキャンバイト数の上限50 GiB
LAGAAM_MAX_ROWSクエリごとのスキャン行数の推定上限制限なし
LAGAAM_MAX_INTERMEDIATE_ROWSエンジンが最大幅の処理ステップで 生成する 行数。返される行数ではないため、LIMIT では減りません50,000,000
LAGAAM_MAX_RETURNED_ROWSクエリごとにエージェントへ返す行数。未設定の場合、サーバーが独自に1000行の上限を適用し、クエリ内の LIMIT がこれを超える場合は実行前に引き下げます1000(最大 100000)
LAGAAM_QUERY_TIMEOUTクエリごとの実時間のタイムアウト(秒)300
LAGAAM_METADATA_TTLメタデータキャッシュの TTL(秒)300
LAGAAM_AUDIT_LOG監査 JSONL ファイルのパスstderr
TRINO_HOST/TRINO_PORT/TRINO_USERTrino コーディネーターlocalhost/8080/lagaam

LAGAAM_ALLOWED_TABLES が設定されていないと、サーバーは起動しません。 すべてのカタログ内のすべてのテーブルにアクセスできるエージェントを防ぐことが、この仕組みの目的です。そのため、許可を明示する必要があります。全テーブルへのアクセスを許可する場合は、LAGAAM_ALLOW_ALL_TABLES=true を設定してください。

上記の予算上限は、設定の有無にかかわらず適用されます。 LAGAAM_MAX_SCAN_BYTES と LAGAAM_MAX_INTERMEDIATE_ROWS を未設定にしても、デフォルト値が適用され、制限がなくなるわけではありません。設定されていないサーバーは、処理能力を超えるクエリを通すのではなく拒否します。クエリが拒否され、制限がないはずだと思っていた場合は、それが理由です。引き上げたい上限を設定してください。

コストの見積もりはエンジン独自のプラン推定に基づき、推定にはテーブル統計が必要です。統計のないテーブルはコストを算出できないため、そのテーブルへのクエリは推測で通すのではなく拒否されます。エージェントからアクセスさせる前に、テーブルに対して ANALYZE を実行してください。統計情報が一切ないコネクターは、このゲートを通じて実質的に利用できません。共有クラスターを停止させるのは、コストを見積もれないクエリにほかならないため、これは意図した動作です。

動作の仕組み

Trino アダプターとネイティブ Pinot アダプターを備えた QueryEngine ポートです。OFFLINE と REALTIME の両テーブルを対象に、根拠付け、実行、推定コスト見積もりを行います。すべての query_data 呼び出しは、次のパイプラインを通ります。検証(sqlglot AST)→ テーブル許可リスト → コスト見積もり → 予算ゲート → 実行(行数上限+タイムアウト)→ 検証 → 監査。

Trino では、見積もりは SQL テキストからの推測ではなく、エンジン自身のプランに基づきます。EXPLAIN (TYPE IO) はクエリがスキャンするバイト数を見積もり、EXPLAIN (TYPE LOGICAL) はいずれかのオペレーターが生成する最大行数を見積もります。これは、クロス結合によって膨れ上がり、LIMIT では隠せない数値です。

Pinot にはそのようなプランがありません。すべてのテーブルスキャンは、テーブルのサイズにかかわらず同じプレースホルダーの行数を報告し、バイト数を報告するエンドポイントもありません。そのため、見積もりは静的なセグメントメタデータ、ブローカー独自のプルーニングオラクル(述語を通過するセグメント数)、プランの結合/ユニオン構造から合成されます。コントローラーが処理中に空として報告する処理中(REALTIME)セグメントには、ゼロではなくストリーム独自のフラッシュしきい値が見積もりとして適用されます。カタログで結合キーを証明できる場合、結合には直積ではなく上限値が課金されます。ADR 0008 と ADR 0009 をご覧ください。

詳細は docs/architecture.md、全体像は docs/vision.md をご覧ください。

ステータス

v0.2.5 — PyPI では lagaam として公開され、MCP Registry には io.github.lagaam-ai/lagaam として登録されています。Claude Code プラグイン(lagaam@lagaam)としてインストールできます。Trino アダプター、スキーマツール、プランベースのコストガード、クエリ予算、読み取り専用の強制、エージェントごとの許可リスト、結果検証、監査ログを備えています。単体テスト 1,189 件と統合テスト 212 件(ライブ Trino 476 および Pinot 1.5.1、バッチとリアルタイム)を実施済みで、mypy strict に対応しています。LAGAAM_ENGINE=pinot を設定すると、ネイティブ Pinot アダプターが起動します。OFFLINE と REALTIME の両テーブルを対象に、根拠付け、実行、セグメントメタデータとブローカー独自のプルーニングオラクルから合成した見積もりを提供します。処理中セグメントにはストリームのフラッシュしきい値が課金され、カタログがキーを証明できる場合、結合には直積ではなく上限値が課金されます。準備中の項目(ロードマップ):監査ログへの実行後の実績値の追加、続いて Kubernetes コントロールプレーン — エージェントを CRD として管理し、トークン/ドル予算とキルスイッチを備えます。

Apache 2.0。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。