クイックアンサー:自律型AIエージェント向けの postgres mcp サーバーをスケールさせるには、読み取りクエリをPostgreSQLリードレプリカへ分散し、PgBouncerまたはSupavisorをトランザクションモード(ポート6543)で配置し、厳格な statement_timeout(2,000〜5,000ms)を設定し、実行前に EXPLAIN クエリプラン解析を行ってフルテーブルスキャンを遮断する必要があります。
1. はじめに:自律型データベースAIエージェントのスケーラビリティ危機
2026年、Claude Code、Cursor Composer、PydanticAI といった自律型AIエージェントは、Model Context Protocol(MCP) を介してリレーショナルデータベースと直接通信するようになりました。開発者が手作業でクエリを書くのを待つことなく、自律型の postgresql ai agent はテーブル定義を自律探索し、外部キー制約を解析し、リアルタイムに複雑な分析SQLを実行します。
しかし、無保護な database mcp server を本番のPostgreSQLプライマリノードに直結すると、致命的な障害が発生します:
- コネクション枯渇: 自律エージェントのループが多数のサブタスクを並行起動。標準PostgreSQLはプロセスごとに5〜10MBのRAMを消費するため、瞬時に
max_connectionsに達し、FATAL: remaining connection slots are reservedエラーで通常APIを巻き込んでダウンします。 - プライマリノードのロック競合とCPU枯渇: エージェントがインデックスのない巨大テーブルのスキャン(Seq Scan)や直積結合を含む重いSQLを書き込み用マスター上で直接実行し、業務トランザクションを麻痺させます。
- 暴走クエリ(Runaway Queries): 適切なタイムアウト制御がない場合、モデルのハルシネーションによる無限集計クエリがリソースを占有し続けます。
- ブラインド実行リスク: 従来のMCPツールはLLMが生成したSQLをノーチェックで実行するため、事前コスト検証が欠落しています。
安全にAIエージェントを運用するには、リードレプリカ負荷分散、PgBouncer/Supavisorによるトランザクションプーリング、厳格なタイムアウト設定、そして 事前EXPLAIN解析 を組み合わせたエンタープライズ級 mcp tool アーキテクチャが不可欠です。
2. 高可用性アーキテクチャ:リードレプリカの負荷分散とルーティング
エンタープライズPostgreSQLは、単一の読み書きPrimary(Master)ノードと複数のストリーミングRead Replicaで構成されます。Postgres MCPサーバーはインテリジェントルーターとして機能し、読み取り専用の探索処理とデータ更新トランザクションを厳密に分離します。
+----------------------------------------------------------------------------------------------------+
| ホスト AI エージェント実行基盤 |
| (Claude Code CLI, Cursor Composer, LangGraph, PydanticAI) |
| |
| +------------------------------------------------------------------------------------------+ |
| | MCP クライアント機構 | |
| | - JSON-RPC 2.0 ツール呼び出しの送信 (execute_sql, explain_query, describe_schema) | |
| +---------------------------------------------+--------------------------------------------+ |
+--------------------------------------------------|-------------------------------------------------+
| stdio / ストリーミング SSE (HTTP/2)
v
+----------------------------------------------------------------------------------------------------+
| POSTGRESQL MCP サーバー & インテリジェントルーター |
| |
| +------------------------+ +------------------------+ +--------------------------------+ |
| | SQL AST & 構文解析器 | | 事前コスト評価ガード | | レプリカ健全性・遅延監視 | |
| | - SELECT -> レプリカ | | - EXPLAIN (COSTS ON) | | - pg_last_xact_replay_ts() | |
| | - WRITE -> プライマリ | | - 最大コスト閾値: 1.5万| | - 自動フェイルオーバー | |
| +-----------+------------+ +-----------+------------+ +---------------+----------------+ |
+----------------|----------------------------|--------------------------------|---------------------+
| 動的ルーティング判定 +--------------------------------+
|
+---------------------------------------+
| |
v (更新トランザクション: DDL/DML) v (読み取りクエリ: SELECT/EXPLAIN)
+-----------------------------------+ +------------------------------------------------------------+
| プライマリ PGBOUNCER (Port 6543) | | レプリカ負荷分散 PGBOUNCER プール (Port 6544) |
| モード: Transaction | | ラウンドロビン / 最小接続数アルゴリズム |
+-----------------+-----------------+ +--------------+------------------------------+--------------+
| | |
v v v
+-----------------------------------+ +------------------------------+ +-------------------------+
| POSTGRESQL プライマリ (WRITER) | | POSTGRES リードレプリカ 1 | | POSTGRES リードレプリカ 2|
| - WAL ストリーミング配信元 |==>| - Hot Standby (Streaming) |==>| - Hot Standby (Replica) |
| - 高スループット書き込みトランザクション | - エージェント分析クエリ担当 | | - スキーマ定義・探索担当 |
+-----------------------------------+ +------------------------------+ +-------------------------+
Postgres MCPレイヤーでのルーティング規則
エージェントが execute_sql を呼び出した際、MCPサーバーはSQL構文木(AST)を解析します:
- スキーマ情報・カタログ取得(
\d,information_schema): 100% レプリカプールへルーティング。 - 分析SELECTクエリ: 健全なリードレプリカへラウンドロビン方式で均等分散。
- 実行前コスト評価(
EXPLAIN ...): レプリカ上で本番統計情報を元に実行し、プライマリのバッファキャッシュを保護。 - 書き込み・DDL(
INSERT,UPDATE,CREATE): 明示的な書き込み権限が付与されている場合のみプライマリへルーティング。
3. コネクションプーリング:PgBouncer / Supavisor 設定
数十〜数百のエージェントスレッドをPostgreSQLポート 5432 に直接繋ぐと即座に障害へ直結します。プーラーの導入は必須要件です。
セッションモードとトランザクションモードの比較
| アーキテクチャ指標 | 直接接続 (ポート 5432) | PgBouncer セッションモード | PgBouncer / Supavisor トランザクションモード (6543) |
|---|---|---|---|
| バックエンドメモリ消費 | 接続ごとに 5〜10 MB | 5〜10 MB (セッション固定) | < 50 KB (プール接続をミリ秒で再利用) |
| 最大同時クライアント | 100〜300 (メモリ上限) | 500〜1,000 | 10,000+ 仮想エージェント同時接続 |
| 接続確立オーバーヘッド | 30〜80 ms | 15〜30 ms | < 1.5 ms チェックアウト速度 |
| プリペアドステートメント | 完全対応 | 完全対応 | プロトコルレベルの匿名ステートメント対応が必要 |
| セッション変数 (SET) | 永続 | セッション中保持 | トランザクション内で SET LOCAL を使用 |
| 本番推奨基準 | AIエージェントでは厳禁 | メンテ作業時のみ | 本番運用の必須スタンダード |
最適化された pgbouncer.ini 設定例
[databases]
;; プライマリ書き込み先
postgres_primary = host=10.0.0.1 port=5432 dbname=production auth_user=pgb_auth pool_mode=transaction max_db_connections=40
;; レプリカ読み取り専用ロードバランスターゲット
postgres_replica = host=10.0.0.2 port=5432 dbname=production auth_user=pgb_auth pool_mode=transaction max_db_connections=80
[pgbouncer]
logfile = /var/log/postgresql/pgbouncer.log
pidfile = /var/run/postgresql/pgbouncer.pid
listen_addr = 0.0.0.0
listen_port = 6543
auth_type = scram-sha-256
auth_file = /etc/pgbouncer/userlist.txt
;; AIエージェント向け高並行プール設定
pool_mode = transaction
max_client_conn = 10000
default_pool_size = 25
min_pool_size = 5
reserve_pool_size = 5
reserve_pool_timeout = 3
;; コネクション再利用とステートメント破棄
server_reset_query = DISCARD ALL
server_check_query = SELECT 1
server_check_delay = 10
max_user_connections = 500
query_timeout = 10.0
idle_transaction_timeout = 5.0
4. ベンチマーク検証:直結 vs プーリング vs レプリカ分散
LLMPodium開発チームは、3種類のPostgreSQL構成下で自律型AIエージェントの負荷テストを実施しました。
検証環境と測定手法
- データベース環境: AWS Aurora PostgreSQL 17(Primary 1台 + Replica 2台、
db.r7g.xlarge各4 vCPU、32 GB RAM)。 - エージェントクライアント: Claude Code CLI および LangGraph による並行100ワーカー。
- クエリ内訳: 70% 結合・集計分析クエリ、20% スキーマメタデータ取得、10%
pgvectorHNSW 近傍検索。
+-------------------------------------------------------------------------------------------------------------------------+
| POSTGRESQL MCP スケーラビリティ&パフォーマンスベンチマーク (2026) |
+------------------------------------+------------------+------------+------------+-------------+------------+------------+
| 構成アーキテクチャ | 同時実行数 (Ops) | QPS | レイテンシp50 | レイテンシp99 | 接続切断率 | マスターCPU|
+------------------------------------+------------------+------------+------------+-------------+------------+------------+
| 1. 単一ノード直結 (Port 5432) | 100 Agents | 412 req/s | 84.5 ms | 1,420 ms | 18.4% | 94.2% |
| 2. PgBouncer プール (Primaryのみ) | 100 Agents | 1,280 req/s| 28.1 ms | 142.0 ms | 0.0% | 88.6% |
| 3. レプリカ分散 + PgBouncer (MCP) | 100 Agents | 3,850 req/s| 8.4 ms | 24.8 ms | 0.0% | 12.1% |
| 4. レプリカ + 事前EXPLAINガード | 100 Agents | 3,790 req/s| 9.1 ms | 21.2 ms | 0.0% | 11.8% |
+------------------------------------+------------------+------------+------------+-------------+------------+------------+
ベンチマークからの重要知見
- 接続切断の完全解消: 直結構成では接続上限超過により 18.4% が失敗。トランザクションプール導入により失敗率は 0.0% に激減。
- マスターCPU負荷の極小化: 読み取り処理をレプリカへ分散させた結果、マスターのCPU使用率は 88.6% から 12.1% へ劇的に低下。
- p99テールレイテンシが98%削減: 1,420 ms から 24.8 ms へ短縮され、エージェント側のタイムアウト連鎖を防止。
5. セキュリティガードレールとクエリタイムアウト制御
AIエージェントにスーパーユーザー権限を与えてはなりません。PostgreSQL標準のロールとタイムアウト機能で多層防御を構築します。
-- 1. エージェント専用の読み取りロールを作成
CREATE ROLE agent_readonly WITH LOGIN PASSWORD 'StrictAgentSecret2026!';
-- 2. データベース接続およびスキーマ参照権限の付与
GRANT CONNECT ON DATABASE production TO agent_readonly;
GRANT USAGE ON SCHEMA public TO agent_readonly;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO agent_readonly;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON ALL TABLES TO agent_readonly;
-- 3. DDLおよびデータ変更権限を厳格に剥奪
REVOKE CREATE ON SCHEMA public FROM agent_readonly;
REVOKE ALL ON ALL FUNCTIONS IN SCHEMA public FROM agent_readonly;
-- 4. ロールレベルでフェイルセーフ設定を適用
ALTER ROLE agent_readonly SET statement_timeout = '4000ms';
ALTER ROLE agent_readonly SET lock_timeout = '1000ms';
ALTER ROLE agent_readonly SET idle_in_transaction_session_timeout = '3000ms';
ALTER ROLE agent_readonly SET default_transaction_read_only = on;
-- 5. 1クエリノードあたりのメモリ上限を設定しOOMを防ぐ
ALTER ROLE agent_readonly SET work_mem = '32MB';
6. 事前 EXPLAIN クエリプラン解析の実装
database mcp server において最も画期的な性能向上策は、実行前EXPLAIN検証(Pre-Flight EXPLAIN) です。SQLを実行する前に、MCPサーバーはリードレプリカ上で EXPLAIN (COSTS ON, FORMAT JSON) を実行し、推定実行コストとスキャン方式を検査します。
+----------------------------------------------------------------------------------------------------+
| 事前 EXPLAIN クエリプラン評価フロー |
+----------------------------------------------------------------------------------------------------+
エージェントが execute_sql(query) を呼出
|
v
+-----------------------------------+
| EXPLAIN (FORMAT JSON) を実行 |
+-----------------+-----------------+
|
v
+-----------------------------------+
| 計画ノード解析: コストとスキャン |
+-----------------+-----------------+
|
+------------------------+------------------------+
| |
推定コスト > 15,000 推定コスト <= 15,000
または巨大テーブルの Seq Scan かつ全経路でインデックス使用
| |
v v
+-------------------------------+ +-------------------------------+
| クエリの実行をブロック | | リードレプリカ上で安全に実行 |
| エージェントへ修正指示を返送: | | 取得データをエージェントの |
| "実行拒否: orders テーブルで | | コンテキスト窓へストリーミング|
| 全表走査 (Cost: 84,200)。 | +-------------------------------+
| 検索条件にインデックスを追加。"|
+-------------------------------+
TypeScript による事前評価ガードの実装
import { Pool } from 'pg';
const replicaPool = new Pool({
connectionString: process.env.DATABASE_REPLICA_URL, // PgBouncerポート 6543
statement_timeout: 4000,
});
const MAX_ALLOWED_QUERY_COST = 15000;
interface ExplainPlanNode {
'Node Type': string;
'Relation Name'?: string;
'Total Cost': number;
Plans?: ExplainPlanNode[];
}
export async function executeSafeAgentQuery(sql: string) {
// 1. SELECTおよびWITHクエリのみを許可
const trimmed = sql.trim().toUpperCase();
if (!trimmed.startsWith('SELECT') && !trimmed.startsWith('WITH')) {
throw new Error('拒否: レプリカ上では SELECT および WITH クエリのみ許可されます。');
}
// 2. 事前 EXPLAIN 評価
const explainSql = `EXPLAIN (FORMAT JSON, COSTS ON) ${sql}`;
const explainResult = await replicaPool.query(explainSql);
const plan: ExplainPlanNode = explainResult.rows[0]['QUERY PLAN'][0]['Plan'];
// 3. 実行計画ツリーの走査とコスト閾値チェック
const violations: string[] = [];
function inspectNode(node: ExplainPlanNode) {
if (node['Total Cost'] > MAX_ALLOWED_QUERY_COST) {
violations.push(`推定コスト ${node['Total Cost']} が上限値 ${MAX_ALLOWED_QUERY_COST} を超過`);
}
if (node['Node Type'] === 'Seq Scan' && node['Total Cost'] > 3000) {
violations.push(`テーブル '${node['Relation Name']}' に対するフルテーブルスキャンを検出`);
}
if (node.Plans) {
node.Plans.forEach(inspectNode);
}
}
inspectNode(plan);
if (violations.length > 0) {
return {
status: 'rejected',
error: 'クエリプランが安全基準を満たしていません。',
reasons: violations,
suggested_action: 'インデックス付きカラムで絞り込むか、取得範囲を限定してください。',
};
}
// 4. 安全な本番実行
const startTime = Date.now();
const result = await replicaPool.query(sql);
return {
status: 'success',
duration_ms: Date.now() - startTime,
rowCount: result.rowCount,
rows: result.rows,
};
}
7. Claude Code および Cursor での接続設定
Claude Code CLI での登録 (~/.claude.json)
# プール経由のリードレプリカを登録
claude mcp add postgres-cluster -- npx -y @modelcontextprotocol/server-postgres \
"postgresql://agent_readonly:StrictAgentSecret2026!@pgbouncer.internal:6543/production?sslmode=require"
詳細ルーティング設定 (claude_desktop_config.json):
{
"mcpServers": {
"postgres-cluster": {
"command": "node",
"args": ["/usr/local/bin/postgres-mcp-router/dist/index.js"],
"env": {
"PRIMARY_DB_URL": "postgresql://agent_writer:SecretWrite2026@primary-pooler.internal:6543/production?sslmode=require",
"REPLICA_DB_URL": "postgresql://agent_readonly:StrictAgentSecret2026!@replica-pooler.internal:6543/production?sslmode=require",
"STATEMENT_TIMEOUT_MS": "4000",
"MAX_EXPLAIN_COST": "15000",
"ENABLE_EXPLAIN_GUARD": "true"
}
}
}
}
Cursor Composer での設定 (.cursor/mcp.json)
{
"mcpServers": {
"database-agents": {
"command": "npx",
"args": [
"-y",
"@supabase/mcp-server-supabase",
"--db-url",
"postgresql://agent_readonly:StrictAgentSecret2026!@aws-0-us-east-1.pooler.supabase.com:6543/postgres?sslmode=require"
]
}
}
}
8. インフラ TCO コスト分析と投資対効果
+----------------------------------------------------------------------------------------------------+
| AIエージェントDBクラスタの月間運用TCO |
+------------------------------------+--------------------------+------------------+-----------------+
| インフラ構成要素 | スペック | 想定ワークロード | 月額コスト |
+------------------------------------+--------------------------+------------------+-----------------+
| AWS Aurora Serverless v2 主ノード | 2〜8 ACU (4〜16 GB RAM) | コア業務の書き込み | $120.00 |
| Aurora リードレプリカ (2台構成) | 各 2〜4 ACU (4〜8 GB RAM)| エージェント分析 | $140.00 |
| PgBouncer 独立コンテナクラスタ | 2x AWS Fargate (0.5 vCPU)| 10,000 クライアント| $22.00 |
| Supabase チームプラン(代替候補) | Pro + コンピュート追加 | プーラー内包 | $85.00 |
| Claude 3.7 Sonnet 推論費用 | 入力1.5億 / 出力2,000万 | 5,000タスク実行 | $675.00 |
| DeepSeek V3 推論費用(コスト重視) | 入力1.5億 / 出力2,000万 | 5,000タスク実行 | $27.30 |
+------------------------------------+--------------------------+------------------+-----------------+
| 合計月額コスト (Claude 3.7運用) | エンタープライズ構成 | 5,000タスク/月 | $957.00 |
| 合計月額コスト (DeepSeek V3運用) | コスト最適化構成 | 5,000タスク/月 | $309.30 |
+------------------------------------+--------------------------+------------------+-----------------+
9. 本番運用チェックリストとまとめ
- トランザクションモード必須化: エージェントの接続はすべて PgBouncer/Supavisor ポート
6543経由とし、5432直結を禁止する。 - リードレプリカへの完全オフロード:
SELECT、スキーマ探索、ベクトル検索をストリーミングレプリカに限定する。 - タイムアウトのロール固定:
statement_timeout = '4000ms'、lock_timeout = '1000ms'を設定する。 - EXPLAIN事前ガードの配備: 推定コスト15,000超または大テーブルのフルスキャンを自動遮断する。
- 読み取り専用属性の強制:
default_transaction_read_only = onをエージェントロールに適用する。 - レプリケーション遅延の監視:
pg_last_xact_replay_timestamp()を監視し、データ鮮度を保証する。