45395 - シコウサクゴ -

業務データベースを自然言語で検索するMCPサーバーを作った

2026-04-11
AI駆動開発
AI駆動開発
Claude Code
MCP
PostgreSQL
自然言語
データベース
Last updated:2026-04-12
8 Minutes
1525 Words

非エンジニアのメンバーから「このデータ出して」と依頼が来るたびにSQLを書く。この繰り返しを解消するために、PostgreSQLに対して自然言語でクエリを投げられるMCPサーバーを構築しました。

課題:SQLを書けない人がデータにアクセスできない

業務データベースには案件の進捗、担当者の活動履歴、完了実績など日常的に参照が必要なデータがあります。しかしアクセスはSQLを書けるメンバーに集中します。よくある依頼パターンはこのようなものです。

  • 「特定エリアの進捗状況を一覧で見たい」
  • 「今週完了した案件を教えて」
  • 「2週間以上動きのない案件を洗い出したい」
  • 「ある担当者が処理した案件名と金額の一覧がほしい」

いずれも単純なSELECT文で済みますが、テーブル構造を知らないと書けません。

解決策:MCPサーバーでAIとDBをつなぐ

MCP(Model Context Protocol)は、AIアシスタントが外部ツールやデータソースと接続するためのプロトコルです。MCPサーバーを介することで、AIが自然言語をSQLに変換し、データベースから結果を取得して回答します。

アーキテクチャ

1
ユーザー(自然言語で質問)
2
3
Claude CLI
4
↓ MCP Protocol
5
MCPサーバー(SQL生成 + 実行)
6
↓ Read-Only接続
7
PostgreSQL(業務データベース)

ポイントは3つあります。

  1. Claude CLIがユーザーインターフェース — 自然言語の入力をそのまま受け取ります
  2. MCPサーバーがブリッジ — スキーマ情報の提供とSQLの実行を担います
  3. PostgreSQLへの接続はRead-Only — 誤ったUPDATE/DELETEが発行されるリスクを排除します

仕様駆動開発で進めた

このMCPサーバーの開発は、以下のステージで段階的に進めました。

  1. ブレスト — ユースケースの洗い出し、どんな自然言語クエリが来るかの想定
  2. 要件定義 — 接続先DB、対応するクエリパターン、セキュリティ要件の明確化
  3. 設計 — MCPサーバーのツール定義、スキーマ情報の公開方法、エラーハンドリング
  4. テスト設計 — 自然言語→SQL変換の正確性、Read-Only制約の検証
  5. タスク分解 → 実装

各ステージでユーザー確認を入れることで、「作ったけど使えない」を防ぎました。特に要件定義で「実際に聞きたい質問」を列挙してもらったのが効果的でした。

自然言語クエリの実例

実際にテストした自然言語クエリと、それがどう処理されたかの例を挙げます。

自然言語の質問処理内容
「エリアAの進捗を教えてください」特定エリアでフィルタし、案件のステータスを一覧取得
「今週完了した案件を教えてください」日付範囲 + ステータス条件でフィルタ
「動きのない案件を教えて(2週間以上活動なし)」最終更新日が14日以上前のレコードを抽出
「担当者Xが処理した案件名と金額を教えてください」担当者名でJOINし、案件名と金額カラムを取得

MCPサーバーがスキーマ情報(テーブル名、カラム名、型、リレーション)を公開し、ClaudeがそれをもとにSQL文を生成・実行する仕組みです。

Read-Only接続にした理由と実装

Read-Onlyに制限した理由は明確です。

  • 自然言語からのSQL生成は、意図しないUPDATEやDELETEを生成するリスクがゼロではありません
  • 業務データベースに対する書き込み操作は、既存の業務フローを経由すべきです
  • AIが「データを修正しておきました」と善意で書き換える事故を構造的に防ぎます

PostgreSQL側でRead-Only専用ユーザーを作成し、MCPサーバーはそのユーザーで接続します。

1
CREATE USER mcp_readonly WITH PASSWORD '****';
2
GRANT CONNECT ON DATABASE business_db TO mcp_readonly;
3
GRANT USAGE ON SCHEMA public TO mcp_readonly;
4
GRANT SELECT ON ALL TABLES IN SCHEMA public TO mcp_readonly;
5
ALTER DEFAULT PRIVILEGES IN SCHEMA public
6
GRANT SELECT ON TABLES TO mcp_readonly;

MCPサーバー側でもSELECT文のみ許可するバリデーションを入れていますが、DB側の権限制約が最後の砦です。防御は多層にしておくのが基本です。

限界とエッジケース

万能ではありません。把握している限界を挙げます。

  • 曖昧な質問への対応: 「最近の案件」がいつからを指すのか、コンテキストによって解釈が変わります。MCPサーバー側でデフォルト期間を定義するか、Claudeに確認を促させる必要があります
  • 複雑なJOIN: 3テーブル以上のJOINが必要なクエリでは、スキーマ情報だけでは正しいリレーションを推測できないことがあります
  • 集計クエリの精度: 「平均」「合計」などの集計は、GROUP BYの粒度が質問文から一意に決まらないケースがあります
  • 日本語カラム名: スキーマが日本語カラム名の場合、自然言語との対応付けは比較的スムーズですが、英語カラム名の場合はスキーマのコメント情報が重要になります

今後の展開

現在はローカル環境で動作しています。今後の計画は以下の通りです。

  • クラウドデプロイ: Google Cloud上にMCPサーバーを配置し、リモートアクセスを可能にする [要確認: 具体的なGCPサービス構成]
  • ユーザー認証: 誰がどのクエリを実行したかのログ記録と、アクセス制御の追加
  • Claude CLI → Claude API移行: 現在のCLI依存を脱し、APIベースにすることでWebインターフェースやSlack連携が可能になります

まとめ

MCPサーバーをPostgreSQLとClaude CLIの間に置くことで、自然言語でのデータベース検索が実現できました。非エンジニアが「今週完了した案件を教えて」と聞くだけでデータが返ってくる体験は、地味ですが業務効率への影響が大きいです。

Read-Only接続と仕様駆動開発の2点は、この種のAI連携ツールを作る上で再利用できる設計パターンだと考えています。

Article title:業務データベースを自然言語で検索するMCPサーバーを作った
Article author:45395
Release time:2026-04-11

記事へのご質問・ご感想をお聞かせください

フィードバックを送る