db-access-mcp について
db-access-mcpは、トンネル経由でデータベースに接続し、クエリ、実行計画、ファイル出力を提供するAIエージェント向けMCPサーバーです。認証情報の保護、読み取り専用制御、インスタンス間の分離を備えています。
主な機能
- 01PostgreSQL、MySQL、Redshift、SQL Server対応
- 02SSHおよびAWS SSMトンネル
- 03クエリ、実行計画、ストリーム出力
- 04複数のシークレットプロバイダー
- 05設定の再読み込みとインスタンス分離
活用シーン
- 01踏み台経由でプライベートDBに接続
- 02SQLの実行計画を確認
- 03大量のクエリ結果をCSVやJSONLに出力
- 04稼働中に接続設定を反映
MCP 対応
stdio経由でMCPクライアントにデータベース操作ツールを提供します。接続管理、クエリ、トンネル管理、設定再読み込みに対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
11掲載時のツール一覧 · 2 週間前に更新
このツールにパラメーターはありません。
詳細
db-access-mcp
AI エージェント(Claude Code、Claude Desktop、あらゆる MCP クライアント)が設定済みデータベースにアクセスできる、MCP(Model Context Protocol)stdio サーバーです。
- PostgreSQL(≥ 10)
- MySQL(≥ 5。読み取り専用セッションには ≥ 5.6 が必要です)
- Amazon Redshift
- Microsoft SQL Server(tedious 経由)
SSH / AWS SSM トンネル、プラグイン可能なシークレットプロバイダー(環境変数、HashiCorp Vault、AWS Secrets Manager)、厳格なインスタンス単位の分離に対応しています。同じマシン上で多数の MCP インスタンスを同時に実行しても、接続やトンネルは共有されません。また、インスタンスがクラッシュしても孤立したトンネルプロセスが残ることはありません。
主な機能
ツール: connection_list / connection_find / connection_test、query、
query_plan(EXPLAIN)、query_to_file(モデルコンテキストを経由しないストリーミング CSV/JSONL エクスポート)、up_tunnel / down_tunnel / tunnel_list、config_reload
(再起動せずに新しい接続やトンネルを反映)。
セキュリティを最優先した設計:
- 検証済み SSH トンネル — 踏み台ホストの鍵を
host_key_sha256のピンまたはknown_hostsと照合し、不一致の場合は安全側に倒して接続を失敗させます(MITM 防御)。無条件に信頼することはありません。 read_onlyによる保護と、デフォルトでの単一ステートメント実行により、SET session read-only off; INSERT …による回避も防ぎます。- ファイルエクスポートの範囲を制限 —
query_to_fileが書き込めるのはエクスポートディレクトリ、またはallow_export_pathsで指定したルート配下のみです。~/.ssh、ドットファイル、設定ディレクトリを上書きすることはできません。 - シークレットを外部に漏らしません — ツールはスタックトレースや認証情報を返しません。ログではキー名による編集に加え、
user:password@host形式の URI もインラインで秘匿します。 - プラグイン可能なシークレットプロバイダー — 環境変数、HashiCorp Vault(自動更新とプールのアトミックな切り替えに対応した動的リース)、AWS Secrets Manager、RDS IAM 認証トークン、一時的な Redshift 認証情報。
トンネルとクラッシュ時の安全性: プロセスとともに終了するプロセス内 SSH(孤立したポートを残しません)と、ウォッチドッグの監視下で動作する AWS SSM(SIGKILL 時も終了します)に対応し、AWS SSO のブートストラップも利用できます。 各インスタンスのプールとトンネルは分離されており、クラッシュしたインスタンスのトンネルは次回起動時に終了されます。
クイックスタート
// Claude Code / Claude Desktop MCP config
{
"mcpServers": {
"db-access-mcp": {
"command": "npx",
"args": ["-y", "@rheopyrin/db-access-mcp"]
}
}
}
初回起動時、サーバーは作業ディレクトリ ~/.db_acess_mcp
(意図的なスペルです。製品の仕様として定められています)を作成します。このディレクトリには、空の config.json、空の conf.d/ ディレクトリ、およびすべての方言、シークレットプロバイダー、トンネルタイプを網羅した完全な config.example.json が含まれます。エクスポートディレクトリ(デフォルトは
/tmp/db-access-mcp/exports)は事前に作成されません。query_to_file が初回のエクスポート時に必要に応じて作成します。~/.db_acess_mcp/config.json を編集して MCP サーバーを再起動すれば完了です。
MCP との統合
このサーバーは stdio 経由で MCP 通信を行います。npx -y @rheopyrin/db-access-mcp(ローカルビルドの場合は node <path>/dist/cli.js)を起動できるクライアントであれば、どれでも利用できます。
起動した各インスタンスは、独自のプール、トンネル、アイドルタイマーを持ち、完全に分離されています。そのため、複数のクライアントやセッションに同時に登録しても安全です。
Claude Code
# current project only (writes .mcp.json in the project root)
claude mcp add db-access-mcp -- npx -y @rheopyrin/db-access-mcp
# for all your projects
claude mcp add --scope user db-access-mcp -- npx -y @rheopyrin/db-access-mcp
# with options (custom config dir, verbose logs, extra env file)
claude mcp add db-access-mcp -- npx -y @rheopyrin/db-access-mcp --workdir ~/.db_acess_mcp --log-level debug --env-file ~/.db_acess_mcp/secrets.env
セッション内で /mcp を使って確認します(サーバーの状態確認、再接続)。サーバーの stderr ログは
~/Library/Caches/claude-cli-nodejs/<project-slug>/mcp-logs-db-access-mcp/
(macOS)に保存されます。config.json を編集した後は、サーバーを再接続してください(/mcp)。設定は起動時にのみ読み込まれます。
または、プロジェクトの .mcp.json に直接定義できます。
{
"mcpServers": {
"db-access-mcp": { "command": "npx", "args": ["-y", "@rheopyrin/db-access-mcp"] }
}
}
Claude Desktop
設定ファイルに同じ mcpServers ブロックを追加し、アプリを再起動します。
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Windows:
%APPDATA%\Claude\claude_desktop_config.json
Cursor / その他の MCP クライアント
同じ形式で、stdio に対応する任意のクライアントを使用できます。コマンドは npx、引数は ["-y", "@rheopyrin/db-access-mcp"] です(Cursor の場合:~/.cursor/mcp.json、同じ mcpServers
形式)。次の 2 点に注意してください。
- stdout はプロトコルです — クライアントに JSON-RPC の解析エラーが表示される場合は、コマンドに余計な出力を追加するものがないことを確認してください。サーバーのログはすべて stderr に出力されます。
- CLI オプションは
argsで渡します。例:["-y", "@rheopyrin/db-access-mcp", "--workdir", "/opt/mcp-db", "--log-level", "warn"]
ローカルビルド(開発)
git clone <repo> && cd db_access_mcp && npm ci && npm run build
claude mcp add db-access-mcp-dev -- node /abs/path/db_access_mcp/dist/cli.js --log-level debug
クライアントを使わずに試す
npx -y @modelcontextprotocol/inspector npx -y @rheopyrin/db-access-mcp
すべてのツールを呼び出しフォームとリアルタイムの stderr とともに一覧表示するウェブ UI を開きます。最初のセッションでは、次の順序がおすすめです:dialect_list → connection_list →
connection_test(いずれか 1 つの接続で実行)→ query。
ホストの要件
- Node.js ≥ 20.19。
- ssm トンネルの場合:AWS CLI と session-manager-plugin が PATH 上に必要です。SSO の初期設定にはブラウザーが必要です(ログイン時に対話形式で開きます)。
- ssh トンネルの場合:追加のものは不要です(プロセス内の ssh2 クライアント)。
CLI オプション
db-access-mcp [workdir] [exportdir] [--workdir <dir>] [--exportdir <dir>] [--config <file>] [--env-file <file>]... [--log-level <level>]
| オプション | 環境変数 | デフォルト |
|---|---|---|
--workdir(または最初の位置引数) | DB_ACCESS_MCP_WORKDIR | ~/.db_acess_mcp |
--exportdir(または 2 番目の位置引数) | DB_ACCESS_MCP_EXPORTDIR | /tmp/db-access-mcp/exports |
--config | DB_ACCESS_MCP_CONFIG | 検出先:<workdir>/config.json + <workdir>/conf.d/*.json |
--env-file(複数回指定可能) | — | なし |
--log-level(debug|info|warn|error|silent) | DB_ACCESS_MCP_LOG_LEVEL | info |
workdir には、config.json、conf.d/、config.example.json と、実行時の instances/ および sso/ の状態が保存されます(以前のリリースから変更ありません)。exportdir は query_to_file がエクスポートを書き込む場所です(起動時ではなく、必要に応じて作成されます)。allow_export_paths を指定すると、書き込み可能なルートを追加できます。
ログはすべて stderr に JSON 行形式で出力されます(stdout は MCP プロトコル用です)。password、token、secret、privateKey などに一致するキーの値はマスキングされます。
MCP ツール
| ツール | 機能 |
|---|---|
dialect_list | 対応しているデータベース方言を一覧表示します。名前(接続の type 値)、デフォルトポート、query_plan が生成するプラン形式が含まれます。 |
connection_list | 設定済みの接続を一覧表示します。キー、タイプ、説明、read_only、ホスト/ポート/データベース、トンネル名、メタデータが含まれます。認証情報が返されることはありません(許可リスト方式でサニタイズし、接続文字列から解析するのはホスト/ポート/データベースのみです)。 |
connection_find | host、port、database、type、read_only、および/または metadata のキーと値のペアで接続を検索します。すべてのフィルターは AND で結合されます。user/password フィルターは無視され、その旨がレスポンスに記録されます。 |
connection_test | エンドツーエンドのヘルスチェックです。シークレット → トンネル → プール → 1 行のサーバー情報クエリの順に確認します。成功時はサーバーのバージョン/ユーザー/データベース/レイテンシとともに ok: true を返し、失敗時は失敗コードとヒントとともに ok: false を返します(DB に接続できないことは有効な結果であり、ツールエラーではありません)。 |
query | 接続に対して SQL を実行します。connection、query、任意の database(複数データベース接続を参照)、max_rows、timeout_ms の上書きを受け付けます。結果は行数上限に合わせて切り詰められ、truncated: true が設定されます。 |
query_to_file | クエリを実行し、モデルのコンテキストではなくファイルに結果を書き込みます(拡張子から csv/jsonl を判定)。file_path はエクスポートディレクトリ(デフォルトは /tmp/db-access-mcp/exports、必要に応じて作成)の相対パス、またはエクスポートディレクトリ内もしくは設定済みの allow_export_paths ルート内の絶対パス/~ パスを指定します。範囲外への書き込みは拒否されます。既存のファイルには overwrite: true が必要です。postgres/mysql は行をストリーミングします(デフォルトでは上限なし)。redshift/mssql はバッファリングし、10 万行が上限です。 |
query_plan | クエリを実行せずに実行プランを返します。postgres は EXPLAIN (FORMAT JSON)、mysql は EXPLAIN FORMAT=JSON、redshift はテキスト形式の EXPLAIN、mssql は SHOWPLAN_XML を使用します。 |
up_tunnel | 接続に設定されたトンネルを開く(または再利用する)と、{host, port, tunnel_id, reused} を返します。任意の local_port を指定すると、ローカルポートを固定できます。トンネルがすでに別のポートで開いている場合、またはポートが使用中の場合、エラーに現在のポートを含めて呼び出しは失敗します。 |
down_tunnel | tunnel_id でトンネルを閉じます。デフォルトでは up_tunnel のピンのみが解放されます。クエリプールがトンネルを保持している場合、トンネルは開いたままとなり、remaining_holders が返されます。force: true を指定すると、保持しているプールをドレインして無条件にトンネルを閉じます。 |
tunnel_list | この MCP インスタンスで現在開いているトンネルを、ライブのヘルスプローブとともに一覧表示します。tunnel_id、トンネル名/タイプ、ローカルおよびリモートのエンドポイント、healthy、保持しているプール(connections)、up_tunnel の pins、外部 PID が含まれます。 |
config_reload | 設定ファイルを実行中のサーバーに再読み込みし、ディスク上で追加または編集された接続/トンネルを再起動せずに使用できるようにします。稼働中の状態に影響を与えることはありません。以下を参照してください。 |
config_reload
config.json/conf.d/*.json(または --config ファイル)を編集して config_reload を呼び出すと、次の connection_list、query、up_tunnel、…で新しい定義が反映されます。
ファイルは再読み込みされ、再検証(スキーマ+セマンティクス+方言チェック)され、何かが切り替わる前に config の env_files が再適用されます。無効な設定によって何も変更されることはありません。サーバーは以前の設定で実行を続け、ツールは検証エラーを返します。
リロードは意図的に非破壊的です。開いているプールや実行中のトンネルは、定義が変更された場合やファイルから削除された場合でも、閉じられたり、排出されたり、再作成されたり、再設定されたりすることはありません。通常の方法(アイドルタイムアウト、down_tunnel、サーバー終了)で閉じられるまで、作成時の定義が維持されます。その後に作成されるプール/トンネルには新しい定義が使われます。このようなケースはすべて、応答の warnings に記載されます。
応答には、files(読み込まれたファイル)、{added, removed, changed, unchanged} 形式の connections と tunnels、pool_defaults_changed/limits_changed/env_files_changed フラグ、warnings が含まれます。呼び出し単位および接続単位の limits は呼び出し時に読み込まれるため、即座に反映されます。pool 設定は、リロード後に作成されたプールにのみ適用されます。
query_to_file に関するセキュリティ上の注意:書き込み先はエクスポートディレクトリ(デフォルトは /tmp/db-access-mcp/exports)と、allow_export_paths に指定されたルート(例:["/tmp", "~/data_files"])に限定されます。指定したルート以下のすべてのサブパスは許可され、それ以外は拒否されるため、このツールが ~/.ssh、ドットファイル、作業ディレクトリの内容を上書きすることはありません。ファイルの作成のみを行い(読み取りや追記は行いません)、明示的に overwrite: true が指定されない限り、上書きは拒否されます。セルの内容はそのまま書き込まれるため、Excel でエクスポートを開く際は CSV インジェクションに注意してください。
設定リファレンス
スキーマは厳密です。不明なキーは、わかりやすいエラーとともに起動時に拒否されます(タイプミス防止)。接続の options 内のすべての内容は、そのままデータベースドライバーに渡されます。
{
"vault": { /* named Vault servers */ },
"aws_secret_profiles": { /* named AWS Secrets Manager profiles */ },
"env_files": [ /* extra .env files applied at startup */ ],
"pool": { /* global pool defaults */ },
"limits": { /* global query limits */ },
"tunnels": { /* named tunnel definitions */ },
"connections": { /* named connections */ }
}
設定ファイル:単一ファイルまたは分割ファイル(conf.d)
--config を指定しない場合、サーバーは <workdir>/config.json(任意)に加えて、<workdir>/conf.d/*.json(名前順、再帰なし、ドットファイルを無視)をすべて読み込み、マージします。
- 名前付きレコードのセクション(
vault、aws_secret_profiles、tunnels、connections)は、ファイル間で統合されます。同じ名前が2つのファイルにある場合は、両方のファイル名を示す起動エラーとなり、暗黙的に上書きされることはありません。 - スカラーセクション(
pool、limits、env_files)は、最大1つのファイルにのみ記述できます。 --config <file>を指定すると、そのファイルのみが読み込まれます。conf.dは検索されません。
すべてを単一の config.json に記述することもできます(例ではこの方法を使用しています)。設定が大きくなった場合に、チーム/プロジェクトごとに分割するための仕組みが conf.d です。
環境変数参照値
以下で指定されている場所では、設定値にインライン文字列または環境変数への参照を指定できます。必要になった時点で遅延的に解決されます。
"token": "hvs.inline" // inline
"token": { "env": "VAULT_2_TOKEN" } // read from the environment at use time
変数が存在しない場合、その変数を実際に必要とする接続のみが失敗し、エラーには変数名が示されます。
connections.<key>
| フィールド | 必須 | 説明 |
|---|---|---|
type | はい | postgres | mysql | redshift | mssql |
options | はい | ドライバーにそのまま渡すオプション(以下の方言別の注意事項を参照)。任意の文字列値に ${provider.path} 形式のシークレットプレースホルダーを含めることができます。database および/または空でない databases リストを宣言する必要があります(connectionString/uri 接続では、文字列内にデータベースが指定されています)。 |
description | いいえ | connection_list に表示される自由記述の説明です。 |
read_only | いいえ | セッションレベルで読み取り専用を強制します(以下の動作を参照)。デフォルトは false です。 |
metadata | いいえ | connection_find で使用されるフラットマップ(値は string/number/boolean)です。 |
pool | いいえ | 接続ごとのプール設定の上書きです。 |
limits | いいえ | 接続ごとの制限設定の上書きです。 |
tunnel | いいえ | { "target": "<tunnel name>", "localPort": 25432? }。localPort が指定されていない場合、20000~45000 の範囲からランダムな空きポートが選択されます。 |
secrets | いいえ | 接続ごとにプロバイダーを1 つだけ指定します:{ "<provider>": <spec> }。 |
方言別の options
- postgres / redshift — node-postgres が受け付けるすべての設定:
host、port、database、user、password、ssl、…、または単一のconnectionString(postgres://user:pass@host:5432/db)。 - mysql — mysql2 が受け付けるすべての設定:
host、port、database、user、password、またはuri(mysql://…)。multipleStatementsには以下の共通ルールが適用されます。 - mssql — mssql が受け付けるすべての設定:
server(またはhostエイリアス)、port、database、user、password、options: { encrypt, trustServerCertificate, … }、またはconnectionString(mssql://…URL または ADO 形式のServer=…;Database=…)。
options.multipleStatements(デフォルトでは無効)
デフォルトでは、query 呼び出しは単一のステートメントを実行します。接続の
options に "multipleStatements": true を設定すると、1 回の呼び出しで
; 区切りの複数のステートメントを実行できます。SQL の解析ではなく、エンジンによって強制されます。
- mysql — ドライバー固有の
multipleStatementsフラグを使用します。 - postgres / redshift — 無効の場合、クエリは拡張プロトコルで実行されるため、
サーバー自体が 2 つ目のステートメントを拒否します(
42601)。SQL の分割は行いません。 - mssql — プロトコルレベルでは強制できないため(T-SQL バッチ)、ここでは 常に複数ステートメントが許可されます。読み取り専用の DB ユーザーを使用してください。
無効のままにしておくと、read_only 接続での
SET session-read-only off; INSERT … による回避も防げます(書き込みを 2 つ目のステートメントとして実行できません)。read_only と同様、これは安全対策です。実際の保証は読み取り専用の DB ユーザーによって得られます。
複数データベース接続(options.databases)
1 台のサーバーが複数のデータベースをホストしていることはよくあります。接続を 重複して定義する代わりに、すべてのデータベースを宣言できます。
"shared-mysql": {
"type": "mysql",
"options": { "host": "...", "port": 3306,
"databases": ["app", "reporting", "audit"],
"user": "...", "password": "..." }
}
ルール(query、query_plan、query_to_file、connection_test は省略可能な
database パラメーターを受け付けます):
databaseパラメーターなし →options.databaseが使用されます。接続でdatabasesリストのみが宣言されている場合、暗黙のデフォルトはありません。 使用可能な名前を列挙したDATABASE_NOT_FOUNDエラーで呼び出しが失敗します。- 渡された
databaseはoptions.databaseと一致するか、options.databasesのメンバーである必要があります。一致しない場合はDATABASE_NOT_FOUNDになります。 databaseとdatabasesは同時に宣言できます。すべての接続でどちらか一方以上を 宣言する必要があります(そうでない場合は設定エラーになります)。- 接続とデータベースの各組み合わせに独自のプールが割り当てられます。接続のすべての プールは 1 つのトンネルを共有し、最後のプールが閉じられると解放されます。
connection_list/connection_findではdatabasesが公開され、database検索フィルターは単一のプロパティ、またはリスト内のいずれかの値に一致します。databasesはconnectionString/uriと組み合わせられません。
pool(グローバルおよび接続単位)
| フィールド | デフォルト | 意味 |
|---|---|---|
max | 5 | プール内の最大接続数です。 |
min | 0 | 維持されるアイドル接続の最小数です。 |
idle_timeout_ms | 30000 | プール内での、ドライバーレベルのアイドルクライアントタイムアウトです。 |
connection_timeout_ms | 10000 | 新しい接続を待つ時間です。 |
limits(グローバル、接続単位、呼び出し単位)
| フィールド | デフォルト | 意味 |
|---|---|---|
max_rows | 1000 | 結果セットごとの行数上限です。超過した場合は行が切り詰められ、truncated: true になります。query 呼び出しごとに上書きできます。 |
query_timeout_ms | 30000 | クエリのタイムアウトです。postgres/redshift:サーバー側の statement_timeout。mysql:クライアント側の無通信タイムアウト(接続は破棄されますが、サーバーで文の実行が完了する場合があります)。mssql:クライアント側の request.cancel()。query 呼び出しごとに上書きできます。 |
idle_close_ms | 600000 | インスタンスごとのアイドルタイマーです。この時間だけ未使用の接続は、プールが閉じられ、さらにトンネルが解放されます。 |
解決順序:ツール呼び出しの引数 → 接続の limits → グローバルの limits → デフォルト値。
方言別の read_only の動作
| 方言 | 仕組み | 適用 |
|---|---|---|
| postgres | チェックアウトごとに SET default_transaction_read_only = on を実行 | 強制 — サーバーが書き込みを拒否します(25006)。 |
| mysql ≥ 5.6 | チェックアウトごとに SET SESSION TRANSACTION READ ONLY を実行 | 強制。5.5 ではこの文が失敗し、警告がログに記録されます。適用はされません。 |
| redshift | 試行されますが、Redshift はこれをサポートしていません | ベストエフォート:警告がログに記録されます。読み取り専用の DB ユーザーを使用してください。 |
| mssql | readOnlyIntent 接続オプション | Availability Group の読み取りレプリカでのみ有効です。警告がログに記録されます。読み取り専用の DB ユーザーを使用してください。 |
確実な保証が必要な場合は、常に読み取り専用のデータベースユーザーを優先してください。 read_only はシートベルトであり、セキュリティ境界ではありません。
シークレット
接続ごとにプロバイダーを 1 つ指定します。プレースホルダーはプロバイダー名で名前空間が分けられ、解析済みのシークレットオブジェクトに対して解決されます:${env.userName}、${vault.data.password}、${aws.password}。文字列全体がプレースホルダーの場合は、元の値の型が維持されます(数値は数値のままです)。文字列の一部に含まれるプレースホルダーは、文字列に置換されます。一致しない名前空間は、設定の読み込み時に拒否されます。
env — 環境変数
"options": { "user": "${env.userName}", "password": "${env.password}" },
"secrets": { "env": { "userName": "PG_USER_ENV_VAR", "password": "PG_PASSWORD_ENV_VAR" } }
仕様では、プレースホルダーのキーを環境変数名に対応付けます。環境変数がない場合は、不足しているものの正確な一覧を示して失敗します。静的であり、再読み込みされることはありません。
vault — HashiCorp Vault(複数サーバー)
"vault": {
"vault-main": { "address": "https://vault.example.com:8200", "token": "hvs...." },
"vault-dr": { "address": { "env": "VAULT_DR_ADDR" }, "token": { "env": "VAULT_DR_TOKEN" } }
},
...
"secrets": { "vault": { "target": "vault-dr", "path": "secret/data/databases/db4" } }
vaultは名前付きサーバーのマップです。address/token/namespaceは環境変数参照を受け付け、追加のキーは node-vault に渡されます。secrets.vault.targetでサーバーを選択します。targetを指定しない場合は、VAULT_ADDR/VAULT_TOKEN(/VAULT_NAMESPACE)のみから構築される暗黙のデフォルトクライアントが使用されます。これらは node-vault の標準変数です。暗黙のデフォルトは名前付きマップには含まれません。"default"という名前を付けたエントリは、通常の名前付きエントリとして扱われます。- KV v2 のレスポンスは展開されます。プレースホルダーはシークレットのペイロードを直接参照します。
- 動的シークレット(例:
database/creds/<role>)にはリースが付与されます。リースは TTL の約 80% の時点で(ジッターを加えて)更新されます。更新に失敗した場合(最大 TTL に達した場合)、新しい認証情報が要求されます。認証情報が変わっていれば、接続プールがアトミックに切り替えられます(新しいクエリはすぐに新しいプールを使用し、実行中のクエリは古いプールで完了した後、古いプールがドレインされます)。 - リース期限を過ぎても Vault に到達できない場合、シークレットは期限切れとしてマークされ、次回使用時に遅延再解決されます。期限切れのシークレットで認証に失敗した場合は、再解決と再接続が強制的に 1 回実行されます。
aws — AWS Secrets Manager(名前付きプロファイル)
"aws_secret_profiles": {
"aws-prod": { "aws_profile": "prod", "aws_region": "us-east-1", "reload_interval_ms": 3600000 },
"aws-dev": { "aws_profile": { "env": "AWS_DEV_PROFILE" }, "aws_region": { "env": "AWS_DEV_REGION" } }
},
...
"secrets": {
"aws": {
"secret_id": "prod/erp/mssql", // name or full ARN
"target": "aws-prod", // optional: aws_secret_profiles entry
"version_stage": "AWSCURRENT" // optional
}
}
aws_profile、aws_region、reload_interval_ms は、名前付きの
aws_secret_profiles エントリーに記述します(値は環境変数参照を受け付けます)。target がない場合は、
デフォルトの AWS SDK 認証情報チェーン(環境変数、共有設定、SSO、IMDS など)が使用され、シークレットは静的になります。シークレット値は JSON オブジェクト(SecretString)である必要があり、そのキーは ${aws.*} 名前空間になります。AWS Secrets Manager にはリースがないため、再読み込みはプロファイルの reload_interval_ms(最小 10 秒)でオプトインします。この間隔でシークレットが再取得され、Vault と同じアトミックなプール切り替えによってローテーションが反映されます。
env_files — 追加の .env ファイル
"env_files": ["~/.db_acess_mcp/secrets.env"]
シークレットの解決前、起動時に適用されます。--env-file <file>(複数回指定可能)を使うと、設定リストに追加されます。ファイルには標準的な dotenv 構文を使用します。ルール(セキュリティ):
| ルール | 理由 |
|---|---|
| 実環境の値が常に優先されます。プロセス起動時に存在する変数は、ファイルで上書きされません。 | 実行中の構成で、環境ファイルから VAULT_ADDR/AWS_* の参照先を変更できないようにします。 |
PATH、NODE_OPTIONS、NODE_EXTRA_CA_CERTS、LD_*/DYLD_* は警告とともにスキップされます。 | 起動するプロセス(aws CLI)に対するバイナリ/ローダー/TLS 信頼の乗っ取りを防ぎます。 |
後のファイルが前のファイルを上書きします(設定の env_files が先で、その後に --env-file を指定順に適用)。 | 優先順位を確定できます。 |
グループ/その他のユーザーが読み取り可能な環境ファイルには、POSIX で警告が記録されます(chmod 600 を推奨)。 | シークレットを適切に管理するためです。 |
値はログに記録されず、キーのみが debug レベルで記録されます。 | シークレットを適切に管理するためです。 |
aws_iam — パスワードレスの RDS/Aurora(IAM 認証トークン)
"options": {
"host": "pg.abc.us-east-1.rds.amazonaws.com", "port": 5432, "database": "appdb",
"user": "${aws_iam.username}", "password": "${aws_iam.token}",
"ssl": { "rejectUnauthorized": false } // SSL is MANDATORY for IAM auth
},
"secrets": { "aws_iam": { "username": "readonly", "target": "aws-prod" } }
パスワードはどこにも保存されません。15 分間有効な SigV4 認証トークンをローカルで生成し、パスワードとして使用します。標準の更新パイプラインで有効期限前に再署名し、プールをアトミックに切り替えます。トークンは常に options の実際の RDS ホスト/ポートに対して署名されます(トンネルの 127.0.0.1 ではありません)。そのため、トンネルも変更せずに使用できます。この機能では接続文字列はサポートされません。仕様の host/port は任意でエンドポイントを上書きできます(例:リーダーエンドポイント)。
AWS 側の前提条件:
- インスタンス/クラスターで IAM 認証が有効になっていること(
IAMDatabaseAuthenticationEnabled)。 - DB ユーザーが IAM にバインドされていること — postgres:
GRANT rds_iam TO readonly;mysql:CREATE USER readonly IDENTIFIED WITH AWSAuthenticationPlugin AS 'RDS'; - 呼び出し元に
arn:aws:rds-db:<region>:<acct>:dbuser:<resource-id>/readonlyに対するrds-db:connect権限があること。 - RDS for SQL Server ではサポートされていません。すべての接続は CloudTrail で監査できます。
aws_redshift_creds — 一時的な Redshift 認証情報
"options": { "host": "cluster....redshift.amazonaws.com", "port": 5439, "database": "dwh",
"user": "${aws_redshift_creds.username}", "password": "${aws_redshift_creds.password}" },
"secrets": { "aws_redshift_creds": { "cluster_id": "my-cluster", "db_user": "readonly",
"target": "aws-prod", "duration_seconds": 3600 } }
redshift:GetClusterCredentials は、一時的なユーザー名とパスワードのペア(900~3600 秒)を発行します。返されるユーザー名には IAM: プレフィックスが付いており、そのままサーバーに送信されます。有効期間は API の有効期限に基づき、同じ自動更新+プール切り替えパイプラインに渡されます。
AWS プロファイルの SSO ブートストラップ
aws_secret_profiles エントリーには、ssm トンネルと同じ sso ブロックを指定できます。
"aws_secret_profiles": {
"aws-prod": { "aws_profile": "my-profile", "aws_region": "us-east-1",
"sso": { "session": "my-sso-session", "timeout_ms": 300000 } }
}
プロファイルを参照するプロバイダー(aws、aws_iam、
aws_redshift_creds)が認証情報を使用する前に、セッションは
aws sts get-caller-identity で検証されます。セッションの有効期限が切れている場合は aws sso login
(ブラウザー)が起動し、解決処理は timeout_ms まで待機します。sso.profile のデフォルト値は
エントリーの aws_profile です。ログインの重複はセッション名で判定されます。同じセッションを使うトンネルと
シークレット解決では、ブラウザーによるログインを共有します。
プロバイダーの追加
SecretProvider(src/interfaces/secret-provider.ts)を実装し、src/composition/modules/secrets.module.ts にバインディングを 1 行追加します。プロバイダーの name は、secrets 配下の設定キーとプレースホルダーの名前空間の両方に使用されます。
トンネル
"tunnels": {
"bastion-ssm": { "type": "ssm", "options": { "target": "i-0123...", "region": "us-east-1", "profile": "default" } },
"bastion-ssh": { "type": "ssh", "options": { "host": "bastion", "port": 22, "username": "ec2-user", "privateKey": "~/.ssh/id_ed25519" } }
}
- ssh — MCP プロセス内で実行されます(
ssh2ライブラリ経由)。ローカルリスナーが SSH チャネルを通じて TCP を転送します。プロセス内で実行されるため、SIGKILL を受けた場合もプロセスとともに終了し、ポートが孤立することはありません。オプション:host、port(22)、username、password、privateKey(ファイルパス。~使用可)、passphrase、agent(trueはプラットフォームのデフォルトエージェント、または明示的なソケット/パイプのパス)、ready_timeout_ms。 バスティオンのホストキーは検証されます(MITM 対策)。デフォルトでは~/.ssh/known_hosts(プレーンテキストおよびハッシュ化されたエントリ、標準以外のポートでは[host]:port)を照合します。host_key_sha256(ssh-keygen -lfのフィンガープリント。SHA256:プレフィックスの有無は問いません)で明示的に固定するか、known_hostsに別のファイルを指定するか、strict_host_key: falseを設定してすべてのキーを許可できます(安全ではありません。オプトアウトする場合に限ります)。未知のキーや変更されたキーは拒否されます。 - ssm — 小規模なウォッチドッグプロセスの下で
aws ssm start-session --document-name AWS-StartPortForwardingSessionToRemoteHostを起動します。ウォッチドッグは MCP プロセスからの stdin パイプを保持します。MCP プロセスが何らかの理由(SIGKILL を含む)で終了すると、OS がパイプを閉じ、ウォッチドッグが aws/session-manager-plugin のプロセスツリー全体を終了します(Windows ではtaskkill /T /F、POSIX ではプロセスグループを終了)。PATH 上に AWS CLI と session-manager-plugin が必要です。オプション:target(インスタンス ID)、region、profile、document_name。
AWS SSO のブートストラップ(ssm トンネル)
"bastion-ssm": {
"type": "ssm",
"options": { "target": "i-...", "region": "us-east-1", "profile": "prod" },
"sso": { "session": "my-sso", "profile": "prod", "timeout_ms": 300000 } // all fields optional
}
トンネルに sso ブロックがある場合、トンネルを開く前に aws sts get-caller-identity --profile <profile> でセッションを検証します。セッションがないか期限切れの場合は、ログインを開始します(ブラウザー経由)。sso.session が設定されている場合は aws sso login --sso-session <name> を実行します(IAM Identity Center の正式な形式です。1 つのセッションを複数のプロファイルで使用できます)。それ以外の場合は aws sso login --profile <profile> を実行します。セッションが有効になるまで 3 秒ごとにポーリングして待機します。timeout_ms(デフォルトは 5 分)を超えた場合は、正確な手動コマンドを含むヒントとともに TUNNEL_FAILED が返されます。sso.profile のデフォルトはトンネルの options.profile です。重複排除/マーカーのキーには、セッション名がある場合はその名前を使用します。
- このサーバーが SSO セッションを終了することはありません。ログインプロセスはウォッチドッグの管理対象外で、終了されることはなく、MCP インスタンス終了後も存続します。
- 同時ログインは重複排除されます。インスタンス内ではプロファイル単位で、インスタンス間では
<workdir>/sso/<profile>.login.jsonマーカーを介して重複排除されます。2 つ目のインスタンスは別のブラウザータブを開かず、1 つ目のログインを待機します(終了したプロセスのマーカーは PID と開始時刻のチェックによって無視されます)。 - SSO トークンと
~/.aws/sso/cacheが読み取り、解析、またはログに記録されることはありません。固定引数を使用した aws CLI の呼び出しのみを使用し、シェルは使用しません。
動作:
- トンネルのリモートエンドポイントは、接続の
options(バスティオンから見たホスト/ポート)から取得します。 - トンネルはインスタンスごとにキャッシュされ、
(tunnel name, remote host:port)をキーとして管理されます。同じバスティオン経由で同じデータベースに接続する場合、1 つのトンネルを共有します。query/up_tunnelは、すでに開いていて正常なトンネルを再利用します。 - 参照カウントにより、最後にそのトンネルを使用している接続が閉じられると(アイドルタイマーによる終了を含む)、トンネルも終了します。
- 各インスタンスは、トンネルの PID を記録した
<workdir>/instances/<pid>-<startTime>.jsonを書き込みます。起動時と 10 分ごとに、各インスタンスは終了したインスタンスのファイルを確認してクリーンアップします。その際、PID の生存確認、OS プロセスの開始時刻による PID 再利用の防止、終了前のコマンドラインの整合性チェックを行います。 queryの実行中に接続エラーが発生すると、トンネルの健全性を確認し、必要に応じて再接続して、接続プールを再構築したうえでクエリを再試行します。指数バックオフを適用し、最大 3 回まで試行します。認証エラーは再試行されません。
分離モデル
すべての npx -y @rheopyrin/db-access-mcp プロセスは完全に分離されています。それぞれ独自の設定スナップショット、接続プール、トンネル、アイドルタイマーを持ちます。インスタンス間で共有されるものはありません。インスタンスごとのレジストリファイルは、後続のインスタンスがクラッシュしたインスタンスをクリーンアップできるようにするためだけに存在します。同じデータベースに接続する2つのインスタンスは、それぞれ独立したプールを保持します(データベースの max_connections に注意してください。プールのデフォルトの max は、インスタンスごとに接続あたり5です)。
エラーコード
ツールは、構造化されたペイロードとともに isError: true を返します。生のスタックトレースや認証情報は返しません。
| コード | 意味 |
|---|---|
CONFIG_INVALID | 設定スキーマまたは意味上の違反(不正なトンネル参照、プレースホルダーの名前空間など)。 |
CONNECTION_NOT_FOUND | 不明な接続キーです。 |
DATABASE_NOT_FOUND | 要求されたデータベースがその接続に宣言されていないか、複数データベース対応の接続で database パラメーターを指定せずに呼び出されています(使用可能な名前はヒントに表示されます)。 |
SECRET_RESOLUTION_FAILED | プロバイダーがシークレットを取得できませんでした(環境変数の欠落、Vault/AWS のエラー、不正なパス)。 |
TUNNEL_FAILED | トンネルを開けませんでした/ポートが使用中です/CLI が見つかりません。 |
CONNECTION_FAILED | 再試行後もデータベースに到達できないか、認証に失敗しました。 |
QUERY_FAILED | SQL エラーです。 |
QUERY_TIMEOUT | クエリが timeout_ms を超えました。 |
Windows に関する注意事項
- パスには
os.homedir()を使用します。CLI 引数とprivateKey内の~は手動で展開されます。 - トンネルツリーは
taskkill /T /Fで終了します。プロセスの検査には PowerShell を使用します(wmicは Windows 11 では廃止されています)。 - AWS CLI v2(
aws.exe)と v1(aws.cmd)の両方に対応しています。 - SSH エージェントのデフォルトのパイプ:
\\.\pipe\openssh-ssh-agent
開発
npm ci
npm run lint # eslint (typescript-eslint, type-checked)
npm run typecheck # tsc --noEmit
npm test # unit tests (fast, no docker)
npm run test:integration # requires Docker: postgres:16, mysql:8, testcontainers/sshd
npm run test:e2e # builds, then drives dist/cli.js over real stdio MCP
npm run build # tsup -> dist/cli.js + dist/watchdog.js
アーキテクチャ:inversify DI コンテナーを使用しています。すべての拡張ポイント(ダイアレクトドライバー、シークレットプロバイダー、トンネルプロバイダー、MCP ツール)は複数バインド可能なインターフェースとしてレジストリに集約されます。実装の追加に必要なのは、クラス1つとバインディング1行だけです。src/composition/ を参照してください。
自動統合テストの対象外です(モックを使った単体テスト済み。手動で確認してください): Redshift 固有の機能、SSM トンネル(実際の AWS 環境が必要)、稼働中サーバーを使用した MSSQL、稼働中サービスを使用した Vault/AWS Secrets Manager。
手動検証チェックリスト
npx -y @rheopyrin/db-access-mcpの初回実行 → workdir、config.json、config.example.jsonが作成されます。- 実際の接続を追加 →
connection_list、query(SELECT 1)、query_plan。 - トンネル接続 →
up_tunnelが127.0.0.1:<port>を返します。psql -h 127.0.0.1 -p <port>が動作します。 kill -9 <mcp pid>→ トンネルプロセスが数秒以内に消えます(ウォッチドッグ)。次回の起動時に、古いインスタンスファイルが削除されます。- Vault の動的認証情報:リース TTL の約80%の時点で、ログに
secret refreshed/pool swapped after credential rotationが記録されることを確認します。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。