pgops について
pgopsは、AIアシスタントによるPostgreSQL操作をガードするMCPサーバーです。スキーマ調査、クエリとマイグレーション、性能診断、環境情報に加え、リスクの高い操作には人による確認と監査ログを適用します。
主な機能
- 01スキーマ確認とガード付きクエリ実行
- 02実行計画の解析と診断
- 03マイグレーションの計画と管理
- 04インデックス提案とデータベース状態の確認
- 05コンテナと環境トポロジーの調査
- 06危険な操作に確認を要求
活用シーン
- 01PostgreSQLのスキーマ確認とクエリ実行
- 02遅いクエリやインデックスの必要性を診断
- 03変更適用前のマイグレーションリスク評価
- 04AIによるデータベース操作の監査や制限
MCP 対応
MCPクライアントにPostgreSQLのツール、リソース、プロンプトを公開し、危険な操作ではユーザーへの確認を行います。stdioと認証付きHTTPに対応し、リモートアクセスではスコープ付きエージェントトークンを利用できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
uvx pgops-mcpPGOPS_DSNシークレットPostgreSQL connection string for the database to operate on.PGOPS_READONLY_DSNシークレットOptional separate DSN for the read-only pool. Use a role with no write grants to enforce read-only at the database rather than only in the server.PGOPS_READ_ONLYSet to 1 to withhold every mutating tool. Write tools are not registered at all, so an agent cannot call them.PGOPS_APPROVAL_MODESet to 1 to register container.restart and container.exec. Off by default: Docker socket access is root-equivalent on the host.PGOPS_AUDIT_LOGPath to the append-only JSONL audit log.PGOPS_DEFAULT_TIMEOUT_MSStatement timeout applied to every query unless a tool call overrides it.PGOPS_MAX_TIMEOUT_MSCeiling a caller-supplied timeout is clamped to.PGOPS_DEFAULT_ROW_LIMITRows returned by query.read when the caller does not specify a limit.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
pgops-mcp
AI アシスタントに PostgreSQL データベースを操作させても、データを台無しにさせることはありません。
Claude、Cursor、または VS Code をデータベースに接続して、自然な英語で質問できます。アシスタントは、スキーマの調査、クエリの実行、遅いクエリの診断、マイグレーションの計画に使える 18 個のツールを利用できます。一方で、データをこっそり破壊する手段は与えられません。
実際の動作例
以下の数値はすべて、このリポジトリのデモデータベース(120 万行、114 MB)で実際に出力されたものです。
あなた:
orders.statusにインデックスを作成したい
アシスタント: (
migration.planを呼び出す)
CREATE INDEX "idx_orders_status" ON "orders" (status)
risk=medium estimate=4000ms confidence=medium
blocks: writes yes, reads no
SAFER: CREATE INDEX CONCURRENTLY "idx_orders_status" ON "orders" (status)
アシスタント: 通常のインデックス作成では、約 4 秒間、書き込みがブロックされます。
CONCURRENTLYを使うと全体的には時間がかかりますが、書き込みは継続できます。どちらにしますか?
このツールは、モデルが解釈するための生のプランを返すのではなく、判定、正直な信頼度を添えた所要時間の推定値、そしてより安全な代替案を返します。
query.explain も同様に機能します。JSON を渡す代わりに、次のような内容を伝えます。
planner overestimated rows by 5833x (estimated 239,160, actual 40)
-> run ANALYZE; if it persists the columns may be correlated, consider CREATE STATISTICS
実際に危険な操作の場合
あなた: orders テーブルを空にして
アシスタント: (
DELETE FROM ordersを指定してquery.writeを呼び出す)
CONFIRMATION_REQUIRED
DELETE has no WHERE clause and would affect every row in the table
クライアントが対応している場合、承認プロンプトが表示されるのはアシスタントではなく、あなたです。人間が応答するまで何も実行されず、承認するかどうかにかかわらず、拒否の内容も監査ログに記録されます。
これが重要な点です。危険な操作の承認を求められるのはアシスタントではないため、アシスタントが自分の操作を承認することはできません。 クライアントがプロンプトを表示できない場合は、そのステートメントだけに紐付いた 1 回限りのトークンに切り替わります。「許可済み」になることはありません。
開発の背景
ほとんどの Postgres MCP サーバーは、イントロスペクションと SELECT を行うだけの薄いクエリラッパーです。ロックへの影響分析を伴うマイグレーションを処理できるものも、EXPLAIN と pg_stat_statements からパフォーマンスを診断できるものもなく、データベースが実行されているコンテナーを理解するものもありません。現在、データベースを操作するエージェントは、ガードレールなしで手探りの状態です。
pgops-mcp は、運用を支援する中核です。スキーマの把握 → ガード付きクエリ → マイグレーションエンジン → パフォーマンス診断 → 環境の把握を提供し、あらゆる操作を分類、確認、監査できる安全性アーキテクチャを備えています。
AI/ML 拡張機能のネイティブサポート: pgops は脆弱な正規表現による解析ではなく、Postgres のコアカタログを基盤としているため、pgvector のようなカスタム型や拡張機能をネイティブにサポートします。migration.plan や query.explain などのツールは、ベクター型(vector(384))や hnsw インデックスを、設定なしですぐに扱えます。
初めての方へ: docs/GETTING_STARTED.md では、MCP の知識がなくても参加できる、15 分で読めるガイド付きツアーをご覧いただけます。
ツール一覧
| グループ | ツール |
|---|---|
| スキーマ | schema.inspect |
| クエリ | query.read、query.write(ガード付き)、query.explain(解析済みプラン+判定) |
| パフォーマンス | index.advise、db.health |
| マイグレーション | migration.plan(ドライラン+ロック分析)、migration.describe(平易な説明)、migration.apply、migration.rollback、migration.history |
| 環境 | env.topology、env.correlate、container.logs、container.stats |
| ゲート付き | container.restart、container.exec |
* サーバーを --approval-mode 付きで実行しない限り、登録されません。実行した場合でも、呼び出しごとに確認トークンが必要です。さらに container.exec は、読み取り専用の診断コマンドの許可リストを適用しており、シェルは提供しません。Docker ソケットはホスト上で root と同等の権限を持つため、デフォルトでは読み取り専用アクセスとなります。
安全性モデル(最大の差別化要因)
- 読み取り専用と読み書き可能な接続ロールを分離し、ツールを適切なロールに紐付けます
- 実行前にステートメントを分類し、無条件の
DELETE/UPDATEをブロックします - 破壊的な操作には明示的な確認トークンが必要です
- 実行されたすべてのステートメントを、実行時間と判定を含む追記専用の監査ログに記録します
- タイムアウト段階を設定し、実行時間が長すぎるクエリをキャンセルします
MCP の機能
| プリミティブ | 内容 |
|---|---|
| ツール | 17 — スキーマ、クエリ、説明、アドバイス、移行、環境 |
| リソース | pgops://schema、schema/summary、schema/{table}、health、migrations、audit/recent、config |
| プロンプト | diagnose-slow-query、plan-safe-migration、incident-triage、review-index-health、explain-safety-model |
| エリシテーション | 危険な操作ではエージェント経由ではなく、ユーザーに直接確認します。確認トークンは代替手段です |
| サンプリング | migration.describe は お使いの モデルを使って、英語の説明を計画に変換します。このサーバーに API キーは含まれていません |
| 補完 | pgops://schema/{table} のテーブル名オートコンプリート |
| 進捗/ログ記録 | 時間のかかる操作中にベストエフォートで通知します |
リモートアクセスとエージェントトークン
stdio では認証は不要です。サーバーはクライアントが起動するサブプロセスであり、開放ポートはありません。 HTTP では認証が必要なため、キーがないと起動を拒否します。
pgops-mcp keygen # RS256 keypair
pgops-mcp issue-token --subject my-agent # read-only by default
pgops-mcp issue-token --subject deploy-bot --scope pgops:read --scope pgops:write
pgops-mcp scopes # which scope each tool needs
pgops-mcp --transport http --public-key ~/.pgops/keys/pgops_public.pem
サーバーが保持するのは公開鍵だけなので、トークンを検証できますが、発行することはできません。
スコープ(pgops:read/pgops:write/pgops:admin)はガードレールと同じ危険度に対応し、スコープのエントリがないツールには admin が必要です。デフォルトでは拒否されます。指定がない限り、ループバックにバインドします。
インストール
pgops-mcp は Python ライブラリではなく MCP サーバーです。インポートを目的としたものではなく、pgops.* に API の安定性は保証されません。他の MCP サーバーと同じ方法でインストールします。クライアントからサーバーを指定してください。
Claude Desktop/Cursor/VS Code:
{
"mcpServers": {
"pgops": {
"command": "uvx",
"args": ["pgops-mcp"],
"env": { "PGOPS_DSN": "postgresql://user:pass@localhost:5432/mydb" }
}
}
}
uvx は一時的な環境に取得して実行するため、事前のインストールは不要で、プロジェクト自体の依存関係にも追加されません。
コンテナーを実行する方法もあります。データベースに接続するマシンに Python ツールチェーンを置きたくない場合に便利です。
{
"mcpServers": {
"pgops": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "PGOPS_DSN",
"-v", "pgops-audit:/var/lib/pgops",
"ghcr.io/arzharch/pgops-mcp:latest"
],
"env": { "PGOPS_DSN": "postgresql://user:[email protected]:5432/mydb" }
}
}
}
コンテナーを使うと変わる点が 2 つあります。/var/lib/pgops にボリュームをマウントしないと、コンテナーの終了時に監査ログが失われます。また、コンテナー内の localhost はコンテナー自体を指します。host.docker.internal または compose のサービス名を使用してください。
クライアントに接続する前に、接続を確認してください。
uvx pgops-mcp --selfcheck --dsn "postgresql://user:pass@localhost:5432/mydb"
どちらの方法でも同じサーバーがインストールされ、MCP Registry のエントリにまとめて掲載されていますが、それぞれ異なるユーザーに適しています。uvx は事前インストールが不要ですが、ホストで Python を実行できることを前提としています。コンテナーでは Docker だけを前提とします。
設定、HTTP トランスポート、エージェントトークン、トラブルシューティングについては SETUP.md を、ソースをチェックアウトして実行する方法については CONTRIBUTING.md を参照してください。
ドキュメント
PyPI のプロジェクトページと GitHub のどちらからも参照できるよう、リンクは絶対パスにしています。
使い方
| ドキュメント | 内容 |
|---|---|
| はじめに | 最初の15分間。MCP の知識は不要です |
| ツールリファレンス | 18個すべてのツール:パラメーター、戻り値、エラーコード、スコープ |
| セットアップと設定 | クライアント、HTTP 認証、オブザーバビリティ、トラブルシューティング |
| 環境変数 | すべての設定項目を解説 |
| セキュリティモデル | 実行できること、拒否すること、既知の制限 |
| 変更履歴 | リリースごとの変更内容 |
仕組み
| ドキュメント | 内容 |
|---|---|
| アーキテクチャ | システム設計とトレードオフ |
| システム設計 | 図解付きの安全性確保パイプライン |
| 意思決定記録 | 各選択の理由と、その代償 |
| ベンチマーク | 測定内容と比較対象 |
コントリビューション
| ドキュメント | 内容 |
|---|---|
| コントリビューション | ソースコードのチェックアウト、ゲート、リリースプロセス |
| モジュール構成 | 各モジュールの役割 |
検証方法
471件のテストがあり、重要なテストはモックではなく、コンテナー内の実際の PostgreSQL 16 に対して実行されます。これは意図的な判断です(ADR-005):偽物に対してしか検証されていないガードレールは、検証対象を間違えています。注目すべき失敗例である default_transaction_read_only、ロックのエスカレーション、トランザクション内の DDL、書き換え時の relfilenode の変更は、実際のデータベースの動作です。
| テストスイート | 検証内容 |
|---|---|
| ガードレールと分類器 | 実稼働中の Postgres に対するすべての拒否ルール |
| プロパティベース(Hypothesis) | 誰も書こうと思わなかった入力に対する、不変条件そのもの |
| レッドチーム | 悪意あるエージェントが試みる15個の攻撃を指定し、それぞれを拒否し監査 |
| ライブサーバー | 実際の HTTP サーバーと JWT を使ったエンドツーエンドテスト |
| ベンチマーク | CI アーティファクトとして公開される、回帰検知用のレイテンシ予算 |
レッドチームのテストスイートは実際のバグを発見しており、それこそがこのテストスイートを設ける理由です。拒否されたステートメントに対して発行された確認トークンが別のステートメントに使えてしまう問題と、スコープテーブルが適用ではなくドキュメントとしてしか機能しておらず、pgops:read トークンで query.write を呼び出せる問題を検出しました。
既知の制限
後から判明することのないよう、ここに明記します。
- セッションごとのデータベース分離はありません。 認証によって呼び出し元を識別し、スコープによって実行可能な操作を制限しますが、すべての呼び出し元が1つの接続マネージャーと1つの監査ログを共有します。1人のエンジニアと少数のデータベース向けに作られており、マルチテナントの SaaS 向けではありません。
index.adviseが示すのは、シーケンシャルスキャンの対象となっているテーブルであり、インデックスを作成すべき列ではありません。 その特定にはステートメントごとのプラン検査が必要です。推測でCREATE INDEXを生成せず、その旨を伝えます。DROP INDEX/DROP CONSTRAINTはロールバックできません。 削除前にオブジェクトの定義を取得していないためです。ロールバックでは推測をもとに再構築せず、拒否して理由を説明します。
120万行の orders テーブルで型を変更した場合に migration.plan が返す内容の例:
ALTER TABLE "orders" ALTER COLUMN "total_cents" TYPE bigint
op=table_rewrite risk=high estimate=4800ms confidence=medium
why: rewrites every row and rebuilds every index, holding AccessExclusiveLock
SAFER: add a new column of the target type, backfill in batches, sync with a
trigger, swap the names, then drop the old column
独自のデータベースを用意せずに試す
上記のすべての例で使用している、120 万行の orders テーブルをシードしたスタックです。ホストポートは
5435 なので、ポート 5432 のローカルの Postgres と競合しません。
git clone https://github.com/arzharch/pgops-mcp && cd pgops-mcp
docker compose up -d
uvx pgops-mcp --selfcheck --dsn "postgresql://pgops:pgops_dev@localhost:5435/pgops_demo"
MIT ライセンスです。コントリビューションを歓迎します。詳しくは CONTRIBUTING.mdをご覧ください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。