Claude Codeをデータベースにつなぐ:MCPでリアルなデータを直接クエリする

MCPでPostgreSQLをClaude Codeに接続し、読み取り専用アカウントと権限設定を行う。ClaudeがスキーマやDBを直接操作でき、手動でスキーマをコピーする手間がなくなる。


データベースを接続すると、Claude Codeの動き方が変わる。テーブル構造をプロンプトにコピーする必要も、フィールド名を教える必要もない。Claudeが直接接続し、自分でスキーマを読み、クエリを書き、結果を分析してくれる。

この記事ではPostgreSQLを例に、設定から実際の使い方まで一通り解説する。

使うMCP Server

公式の @modelcontextprotocol/server-postgres がサポートしているのは:

  • 全テーブルのスキーマ読み取り(フィールド名・型・制約)
  • SQLクエリの実行と結果の返却
  • 複数スキーマへの対応

読み取り専用。このServerはクエリのみを行うよう設計されており、INSERT/UPDATE/DELETEは実行しない。

インストール

npm install -g @modelcontextprotocol/server-postgres

設定

.claude/settings.json(プロジェクト単位)を編集:

{
  "mcpServers": {
    "db": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-postgres",
        "postgresql://readonly_user:password@localhost:5432/myapp_production"
      ]
    }
  }
}

接続文字列の形式:postgresql://USER:PASSWORD@HOST:PORT/DATABASE

パスワードを設定ファイルに書きたくない場合は環境変数を使う:

{
  "mcpServers": {
    "db": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres"],
      "env": {
        "DATABASE_URL": "postgresql://readonly_user:password@localhost:5432/myapp_production"
      }
    }
  }
}

.claude/settings.json をgitにコミットする場合は、平文のパスワードが含まれていないか確認すること。機密情報は .claude/settings.local.json に置き、.gitignore に追加する。

まず読み取り専用アカウントを作る

書き込み権限のあるアカウントをClaudeに渡してはいけない。PostgreSQLで読み取り専用ユーザーを作成する:

-- 読み取り専用ユーザーの作成
CREATE USER claude_readonly WITH PASSWORD 'your_password';

-- 接続権限の付与
GRANT CONNECT ON DATABASE myapp_production TO claude_readonly;

-- スキーマの使用権限を付与
GRANT USAGE ON SCHEMA public TO claude_readonly;

-- 全テーブルへのSELECT権限を付与
GRANT SELECT ON ALL TABLES IN SCHEMA public TO claude_readonly;

-- 将来作成されるテーブルにも同じ権限を適用
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO claude_readonly;

sessionsaudit_logs など見せたくないテーブルがある場合は、そのテーブルへの権限を付与しないか、別スキーマに移動する。

接続の確認

Claude Codeを再起動してから聞いてみる:

データベースにあるテーブルを一覧表示して

Claudeが「データベースへのアクセス権がありません」と言う代わりにテーブル名の一覧を返してきたら、MCP接続は成功している。

実際の使用例

設定が完了すると、Claudeにできることがぐっと広がる。実際のシナリオをいくつか見てみよう。

シナリオ1:データ構造の把握

usersテーブルとordersテーブルはどういう関係ですか?
外部キー制約はありますか?

Claudeは information_schema を直接クエリしてテーブル構造と制約を読み取り、わかりやすく説明してくれる。スキーマを貼り付ける必要はない。

シナリオ2:データ分析

過去30日間に登録したユーザーのうち、
注文を少なくとも1件入れた割合はどれくらい?
登録チャネル別に集計して

ClaudeがSQLを書いて実行し、結果を分析する。クエリが間違っていた場合(フィールド名が違うなど)、エラーを見て自分で修正する。

シナリオ3:問題の調査

ordersテーブルでstatus = 'pending'なのに
created_atが7日以上前のレコードはいくつある?
一番最近のものはいつ?

このような即席の調査は、以前は自分でSQLを書くかデータベースツールで手動確認する必要があった。今は必要なことを言うだけでいい。

シナリオ4:開発サポート

usersテーブルにlast_login_atカラムを追加したい。
マイグレーションSQLを書いて、
既存のインデックスで十分かどうかも確認して

Claudeは現在のテーブル構造を確認してからマイグレーションを書き、インデックスの状況も分析してアドバイスしてくれる。

Claudeが見えるものを制御する

デフォルトでは、権限を付与した全テーブルの完全なスキーマとデータにClaudeはアクセスできる。必要に応じて以下の制限を加えよう。

テーブル単位での制御

特定のテーブルだけに権限を付与する:

-- 全テーブルではなく特定のテーブルのみ許可
GRANT SELECT ON TABLE users, orders, products TO claude_readonly;
-- sessions, payment_tokens, audit_logsなどには権限を付与しない

ビューで機密フィールドをフィルタリング

テーブルに機密フィールド(パスワードハッシュ、APIキー、電話番号)が含まれている場合は、それらを除いたビューを作る:

CREATE VIEW users_safe AS
  SELECT id, email, created_at, plan, status
  FROM users;
  -- password_digest, phone, payment_method_idは除外

GRANT SELECT ON users_safe TO claude_readonly;
-- 元のテーブルへの権限は付与しない

Claudeはビューしかクエリできず、元のフィールドは見えない。

行数の制限

@modelcontextprotocol/server-postgres はデフォルトでクエリ結果に行数制限(通常1000行)を設けており、テーブル全体を引っ張ってくることを防いでいる。この制限は適切なので増やす必要はない。

リモートデータベースへの接続

本番データベースがリモートサーバーにある場合、直接ポートを公開することは通常しない。SSHトンネルを使う:

# localhost:5433をリモートサーバーの5432に転送するトンネルを作成
ssh -L 5433:localhost:5432 [email protected] -N

設定ファイルではローカルポートを指定:

"postgresql://readonly_user:password@localhost:5433/myapp_production"

pgBouncer のような接続プーラーを使う方法もある。

複数のデータベース

プロジェクトで複数のデータベース(メインDB・分析DB・キャッシュDBなど)を使っている場合は、複数のMCP Serverを設定できる:

{
  "mcpServers": {
    "main-db": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://...メインDB..."]
    },
    "analytics-db": {
      "command": "npx",
      "args": ["-y", "@modelcontextprotocol/server-postgres", "postgresql://...分析DB..."]
    }
  }
}

Claudeは両方のDBに接続する。どちらを使うかはその都度伝えればいい。

実際に変わること

データベースを接続した後、最も大きく変わるのは、データ関連の話題に事前説明が不要になることだ。テーブル構造を説明する必要も、フィールドの型を教える必要もない。必要なことを伝えれば、Claudeが自分で調べてくれる。

バグの調査で特に効果を感じる。以前の流れ:自分でDBをクエリ → 結果をコピー → Claudeに貼り付け → 分析してもらう。今の流れ:問題を説明 → Claudeが自分でクエリ → 直接結論が出る。