Claude Codeでデータベースに接続する方法 — MCPと読み取り専用ユーザーの安全設計
Claude Codeでデータベースに接続するには、MCPサーバーのDBHubを読み取り専用ユーザーで登録します。permissionsルールで書き込みを止める設計と、プラグイン・claude mcp addの使い分けまで扱います。
Claude Codeでデータベースに接続するには、MCP(Model Context Protocol)サーバーを登録します。1台のDBに読み取り専用でつなぐだけならDBHubプラグインを/plugin installで入れるのが最短で、複数DBやSSH経由ならclaude mcp addで登録します。どちらの経路でも、接続には読み取り専用のDBユーザーを使います。PostgreSQLやMySQLのスキーマを読み、集計クエリを自然文で投げられます。問題は逆方向です。同じ接続経路でINSERTやDELETEも通せてしまうため、最初の設計を誤ると本番データを壊すエージェントになりかねません。DBHub(@bytebase/dbhub)を例に、読み取り専用から始めてどこまで許可を広げるかを手順で確認します。MCPを使わずBashから直接SQLを書かせる場合の権限設計はClaude Code SQLと正規表現を安全に書かせる勘所にまとめています。
MCPでデータベースに接続するとできること
MCPは、AIエージェントとツール・データソースをつなぐオープンな標準プロトコルです。プロトコル自体の仕組みはMCPとは — AIと外部ツールをつなぐ標準プロトコルに譲り、ここではデータベース接続の文脈に絞ります。
Claude Code公式ドキュメントは「PostgreSQLデータベースを使い、機能ENG-4521を使ったユーザー10人のメールアドレスを探して」という例を挙げています。テーブル名やJOIN条件を覚えなくても、スキーマを読ませて自然文で聞けば済みます。集計・異常値の発見・スキーマ探索が主な用途で、書き込みが必要な場面は限られます。索引提案やヘルスチェックのようなPostgreSQL固有の分析まで踏み込みたい場合は、専用サーバーを扱うPostgreSQL MCPサーバーの使い方が参考になります。分析用のデータウェアハウスが対象なら、Googleが提供するBigQuery MCPサーバーで同じ発想の自然言語問い合わせができます。手順はBigQueryをClaudeで自然言語のまま分析するにまとめています。SQLiteをエッジで運用するTursoにはOAuthだけで繋がる専用サーバーがあり、Turso MCPサーバーガイドで扱います。
接続前に決めること — 読み取り専用ユーザーとDSNの用意
手順に入る前に、データベース側で2つ準備します。
- 読み取り専用のDBユーザーを作る。本番の管理者権限アカウントを接続文字列にそのまま書かない
- 接続文字列(DSN)を
postgres://user:password@host:port/dbnameの形で用意する。パスワードはgitに残さない前提で扱う
Claude Code公式ドキュメントの実例も、この前提で書かれています。
claude mcp add --transport stdio db -- npx -y @bytebase/dbhub \
--dsn "postgresql://readonly:pass@prod.db.com:5432/analytics"readonlyというユーザー名は説明用の例ですが、狙いは明確です。接続に使うDB権限そのものを読み取り専用に絞ることが、後述するMCP側の許可ルールより先に効く1段目のガードレールになります。
手順1: DBHubプラグインで最短接続する
DBHubはPostgreSQL・MySQL・MariaDB・SQL Server・Oracle・SQLiteに対応するオープンソースのMCPサーバーです。Claude Code向けにはプラグイン形式の導入が最も速く、しかも既定で読み取り専用です。
/plugin marketplace add bytebase/dbhub
/plugin install dbhub@dbhubインストール時にDSNの入力を求められますが、この値は設定ファイルに書かれず、Claude Codeのセキュアストレージに保存されます。プラグインはexecute_sqlにreadonly = trueとmax_rows = 1000をあらかじめ設定し、データベースエンジン側の読み取り専用モードも合わせて効かせる構成です。加えて/dbhub:setupが接続文字列づくりとトラブルシュートを担当します。/dbhub:exploreはスキーマ探索(名前一覧 → 概要 → 詳細の3段階)をトークン効率よく進めるスキルです。
1台のDBに読み取り専用でつなぐだけなら、この経路で設定ファイルは1つも要りません。
ただし、経路によってツールの呼び名が変わる点に注意が必要です。プラグインに同梱されたMCPサーバーのツールはmcp__plugin_<プラグイン名>_<サーバー名>__<ツール名>という長い名前になります。名前に使えない文字は_に置き換わります。後述のpermissionsやフックのmatcherにmcp__db__execute_sqlと書いても、プラグイン経由のツールには一致しません。
入れ方で変わる権限ルールの書き方
プラグイン経由
ツール名はmcp__plugin_<プラグイン名>_<サーバー名>__execute_sqlの形式です。実際の名前は/mcpの画面で確かめてからルールに書きます。
claude mcp add経由
登録時に付けた名前がそのまま入り、dbと名付ければmcp__db__execute_sqlになります。ルールが短く、チームで共有しやすい形です。
手順2: claude mcp addでTOML設定を直接登録する
複数DBへの同時接続、SSHトンネル経由の接続、書き込みが必要な運用系ツールなど、プラグインの既定を超える場合はclaude mcp addでTOML設定を直接登録します。
claude mcp add dbhub -- npx -y @bytebase/dbhub@latest \
--transport stdio --config /path/to/dbhub.tomlTOML側では、データソースとツールごとの許可を個別に書けます。次の例は本番DBに対してexecute_sqlを読み取り専用・最大100行に絞り、スキーマ探索用のsearch_objectsだけを別途有効にしたものです。
[[sources]]
id = "production"
dsn = "postgres://readonly:pass@prod.db.com:5432/analytics"
[[tools]]
name = "execute_sql"
source = "production"
readonly = true
max_rows = 100
[[tools]]
name = "search_objects"
source = "production"readonly = trueは、SQL文をキーワード分類器で判定する層と、データベース自身の読み取り専用モードの両方で強制されます。1つの設定項目が2つの独立した仕組みで裏打ちされている点が、単純な文字列フィルタより信頼できる理由です。
execute_sql自体を渡さずsearch_objectsだけを公開すれば、書き込みツールを提示すらしない、さらに保守的な構成も組めます。
[[sources]]
id = "production"
dsn = "postgres://readonly:pass@prod.db.com:5432/analytics"
[[tools]]
name = "search_objects"
source = "production"DSNを設定ファイルに直書きしたくない場合は、環境変数の展開が使えます。.mcp.jsonはチームで共有する前提のファイルなので、パスワードは${DB_URL}のような変数参照にして、実値は各自の環境変数側に置きます。
実際にclaudeのv2.1.286で、空のフォルダに変数参照つきで登録してみました。
claude mcp add --scope project --transport stdio db \
-e DB_URL='${DB_URL}' -- npx -y @bytebase/dbhub --dsn '${DB_URL}'${DB_URL}はシングルクォートで囲みます。ダブルクォートにするとシェルが先に展開してしまい、実値が.mcp.jsonに書き込まれます。生成された.mcp.jsonは次のとおりです。
{
"mcpServers": {
"db": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@bytebase/dbhub", "--dsn", "${DB_URL}"],
"env": { "DB_URL": "${DB_URL}" }
}
}
}claude mcp add --helpでは、-s, --scopeの既定がlocalと表示されます。.mcp.jsonに書き出すのはprojectを明示したときだけです。-eなどのオプションはサーバー名の後ろ、--より前に置けます。-eの直後にサーバー名を置くと、名前まで環境変数のペアとして読まれて拒否されます。--より後ろは、サーバー起動コマンドの引数としてそのまま渡されます。
展開の書式には既定値つきの${VAR:-default}もあります。未設定で既定値もない変数は、サーバーが読み込まれたうえで${VAR}の文字列が展開されないまま残り、claude mcp listと/mcpに変数名つきの警告が出ます。接続エラーの原因が環境変数の設定漏れだった、という切り分けにも使えます。
本番DBが踏み台サーバーの先にしかない構成なら、DBHubはSSHトンネルにも対応します。--ssh-host・--ssh-user・--ssh-key(または--ssh-password)・--ssh-portをDSNと合わせて渡します。Claude Codeを動かすマシンから直接DBに到達できない環境でも、これで接続を張れます。踏み台を経由した多段の構成には--ssh-proxy-jumpも用意されています。
DBHubにはexecute_sql・search_objects以外にオプトインのツールが2つあります。explain_sqlはクエリを実際には実行せず実行計画だけを見せるツールで、複雑なクエリを投げる前の安全確認に向きます。health_checkはコネクションプールの状態とバッファキャッシュのヒット率を返し、接続まわりの異常検知に使えます。どちらもTOMLの[[tools]]に明示しない限り有効になりません。
登録後はclaude mcp listで状態を確認します。✔ Connectedならすぐ使えますが、✘ Failed to connectならDSNの誤りかネットワーク到達性を疑います。プロジェクトスコープの.mcp.json経由で追加した場合は⏸ Pending approvalと表示されることがあります。この状態では接続の確認もされず、対話モードでclaudeを起動して承認するまでツールが使えません。v2.1.196以降は、ワークスペースを信頼するダイアログを承認するまで、リポジトリにコミットされた設定ファイルによる自動承認も効きません。クローンしただけのリポジトリが、自分で自分のMCPサーバーを承認できないようにするための仕様です。
読み取り専用の設計を多重化する — DBの権限とMCPの許可ルール
書き込みを止める3つの層
- 1
DBのユーザー権限
接続に使うアカウントそのものを読み取り専用にします。後ろの2層が壊れても、ここで書き込みが拒否されます。
- 2
MCPサーバーの設定
DBHubの
readonly = trueとmax_rowsで、ツールの側から書き込みと大量取得を止めます。 - 3
Claude Codeのpermissions
ツール呼び出しの前に確認を挟むか、ツールを文脈から外します。ここから先はこの層の書き方です。
3層目のpermissionsでは、ルールをmcp__<サーバー名>__<ツール名>という形式で書きます。
{
"permissions": {
"allow": ["mcp__db__search_objects"],
"ask": ["mcp__db__execute_sql"]
}
}この設定なら、スキーマ確認はプロンプトなしで通り、クエリ実行のたびに確認を求められます。mcp__db__execute_sqlをdenyに入れれば、TOML側の設定に関係なくClaude Codeの文脈からツールごと消えます。設計の詳細はClaude Code settings.json完全ガイドにまとめています。
ルールの評価はdeny、ask、allowの順で、最初に一致したものが結果を決めます。mcp__db__*をaskにしてmcp__db__search_objectsだけをallowに入れる書き方は、一見うまくいきそうで失敗します。askが先に一致して毎回確認が出るからです。allowは、denyやaskの例外としては働きません。上の例のようにツールごとに別々のルールを書くほうが意図どおりになります。
もう1つの制約は、settings.jsonのmcp__ルールに括弧を付けられない点です。mcp__db__execute_sql(DELETE *)のようにSQLの中身で絞ることはできず、括弧つきのルールは設定の読み込み時に読み飛ばされます。起動フラグ--disallowedToolsならパラメータの完全一致で拒否できますが、SQL文の完全一致では実用になりません。読み飛ばされたルールは、対話セッション開始時のダイアログとclaude doctorの出力に表示されます。SQLの文面で止めたい場合は、MCPサーバー側のキーワード判定か、DBユーザーの権限に任せることになります。
監査ログが要る場合は、mcp__db__.*に一致するPreToolUseフックで呼び出しを記録できます。プラグイン経由のツールでは、matcherにmcp__db__を書いても一度も発火しません。長い名前のほうに合わせます。
MCPデータベース連携の使い分け早見表
| 用途 | おすすめ度 | 理由 |
|---|---|---|
| 1DBへの読み取り専用接続 | おすすめ度◎ | 理由DBHubプラグインで設定ファイル不要、既定で読み取り専用 |
| 複数DBの同時接続 | おすすめ度◎ | 理由TOMLの[[sources]]を複数書ける。プラグインは非対応 |
| SSHトンネル経由の接続 | おすすめ度◯ | 理由claude mcp addで、DSN方式なら--ssh-host系オプション、TOML方式ならssh_host系フィールドを使う |
| 運用系の書き込み(INSERT等) | おすすめ度△ | 理由readonlyを外す判断は必要最小限の対象に限定してから |
| 出所不明のDB系MCPサーバー | おすすめ度✕ | 理由接続前に提供元を確認する。プロンプトインジェクション経路になり得る |
よくあるつまずき
- プラグインと手動登録が二重に動く: プラグイン版と
claude mcp add版を両方入れると同じDBに2つのMCPサーバーが接続する。手動側を使うなら/pluginメニューでプラグインのMCPサーバーを無効化する - スキーマ出力が途中で切れる: MCPツールの出力は10,000トークンを超えると警告が出て、既定の上限は25,000トークン。大きなスキーマを毎回全文読みたい場合は
MAX_MCP_OUTPUT_TOKENS環境変数を引き上げる。ただしこの変数は、サーバー側がanthropic/maxResultSizeCharsで独自の上限を宣言していないツールにだけ効く。宣言があるツールでは、テキストはその値が優先される - DBに到達できない: Claude Codeを動かすマシンから直接データベースに接続する構成のため、VPNやネットワークの許可リストに入っていないと接続に失敗する。ローカル開発機と本番DBが別ネットワークにある場合は事前に疎通を確認する
--configと--dsnを同時に指定してしまう: DBHubはTOML設定と単一DSNのどちらか一方でしか起動しない。両方を渡すと設定エラーになるため、複数DBを扱いたくなった時点でDSN方式からTOML方式に切り替える- 大きなテーブルを
search_objectsで一気に読む: 数百テーブル規模のスキーマは、名前一覧 → 概要 → 詳細と段階的に絞り込む使い方がトークンを節約する。DBHubの/dbhub:exploreスキルはこの手順を前提にしている
よくある質問
プロジェクトスコープと個人スコープ、DB接続はどちらに向きますか
チームで同じ設定を共有したいなら.mcp.jsonのプロジェクトスコープ、自分だけの検証用途なら既定のローカルスコープが向きます。プロジェクトスコープにパスワードを直書きしないよう、環境変数展開を使う点は共通です。
書き込み権限が必要になったらどうすればよいですか
readonlyを外す対象は、必要なツールとテーブルだけに限定します。書き込みが要る操作専用のDBユーザーとMCPツール設定を別に用意すれば、事故の範囲を狭く保てます。
まとめ
MCP接続の設定は数分で終わるので、時間をかけるのはどこで書き込みを止めるかのほうです。まずDBHubプラグインで1台のDBに読み取り専用でつなぎ、複数DBやSSHが要る段階でclaude mcp addに移る順序が無難です。権限ルールは、入れ方で変わるツール名に合わせて書いてください。DB以外の連携先はMCPの記事一覧から探せます。
参照した一次ソース
この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。