こんにちは! グループ経営ソリューション事業部の米久保です。
みなさん、MCP(Model Context Protocol)を活用してAIエージェントを強化していますか?
この記事では、Postgres MCP Pro というMCPサーバーを使うとデータベースアクセスの開発効率が向上したよ、という話をします。
Postgres MCP Proとは
Postgres MCP Pro は、米国のスタートアップ企業 Crystal DBA 社が開発するオープンソース(ライセンスはMIT)のMCPサーバーです。提供する主要機能は以下のとおりです。
- データベースヘルス:コネクション使用率やバッファキャッシュなどデータベースの健全性を分析する
- インデックスチューニング:ワークロードに最適なインデックスを提案する
- クエリプラン:クエリプランを確認し、パフォーマンスを最適化する
- スキーマインテリジェンス:データベーススキーマの理解に基づいたSQL生成を支援する
- 安全なSQLの実行:読み取り専用モード、安全なSQL解析などアクセス制御を提供する
Claude Code や GitHub Copilot などのコーディングAIエージェントに Postgres MCP Pro が提供するツールを利用させることで、PostgreSQL データベースサーバーを用いるアプリケーションの開発や運用を効率化することが可能です。
構成
アプリケーション開発業務において Postgres MCP Pro を活用することを目的とし、以下の構成で検証を行いました。
- IDE には IntelliJ IDEA を使用し、 GitHub Copilot のプラグインをインストールする
- 開発用のDB(PostgreSQL)、 Postgres MCP Pro をそれぞれ Docker コンテナとしてローカルPC上に起動する
- GitHub Copilot の LLM を利用する(モデルは Claude Sonnet 4)
実際の検証は筆者が担当するプロダクトのコードを利用しましたが、本稿の執筆にあたってはサンプルのDBとコードで同様の検証を行った結果をもとにしています。
Dockerコンテナの作成
docker-compose.yml を以下に示します。サンプルデータには、PostgreSQL Sample Database を利用し、初期化スクリプトで投入するようにしています。Postgres MCP Pro は PostgreSQL サーバーに依存するため、ヘルスチェック後に立ち上げます。コンテナ上の開発DBは最悪壊れてもダメージはないので、 --access-mode=unrestricted を指定し Postgres MCP Pro は無制限モードで立ち上げています。
services: postgres: container_name: postgres-dvdrental image: postgres:17 environment: - POSTGRES_USER=postgres - POSTGRES_PASSWORD=- POSTGRES_DB=postgres ports: - "5432:5432" volumes: - postgres_data:/var/lib/postgresql/data - ./db/dvdrental.tar:/docker-entrypoint-initdb.d/dvdrental.tar:ro - ./db/init-dvdrental.sh:/docker-entrypoint-initdb.d/init-dvdrental.sh:ro healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 10s timeout: 5s retries: 5 networks: - sample_network postgres-mcp-pro: image: crystaldba/postgres-mcp container_name: postgres-mcp-pro restart: unless-stopped environment: - DATABASE_URI=postgresql://postgres: @postgres:5432/dvdrental ports: - "8000:8000" command: ["--access-mode=unrestricted", "--transport=sse"] depends_on: postgres: condition: service_healthy networks: - sample_network volumes: postgres_data: networks: sample_network: driver: bridge
docker-compose up -d でコンテナを起動すれば、準備完了です。
MCPサーバーの利用設定
次に、コーディングAIエージェントがMCPサーバーを利用できるように設定します。設定方法はAIツールにより異なりますが、IntelliJの場合は mcp.json に以下のように記述します。
{ "servers": { "postgresql": { "type": "sse", "url": "http://localhost:8000/sse" } } }
設定を終えたら、動作確認してみましょう。たとえば、「データベースにテーブルは何個存在しますか?」とチャットで尋ねると下図のような応答が得られました。
list_schemas や list_objects というツールを利用して、PostgreSQLのDB情報を取得できていることがわかります。
Domaによるデータアクセス処理の実装
Doma は、Javaでデータアクセス処理を実装するためのオープンソースのフレームワークです。電通総研は、IntelliJのプラグインを開発して寄贈するなど、Domaのオープンソース開発を積極的に支援しています。
電通総研、Javaフレームワーク「Doma(ドマ)」の利用支援ツールを開発
今回は、サンプルDBからデータを取得するリポジトリインターフェースを以下のように定義し、AIエージェントにデータアクセス層のコードとSQLをすべて実装させてみました。Postgres MCP Proの利用により成果物の精度が向上することを確認するのが目的です。
package com.example.rentaldemo; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; public interface CustomerActorAnalysisRepository { 指定顧客の期間内レンタル作品から最頻出俳優を特定. @param customerId @param startDate @param endDate @return OptionalfindTopActorsByCustomerRentals( Integer customerId, LocalDateTime startDate, LocalDateTime endDate ); 指定俳優の出演作品のうち顧客が未レンタルの作品を取得. @param customerId @param actorId @param limit @return List findUnwatchedFilmsByActor( Integer customerId, Integer actorId, Integer limit ); }
カスタム指示(copilot-instructions.md)には、以下のようにデータアクセス処理の実装ルールを定めておきます。
# データアクセス処理の実装 + DOMAを使ってDAOを実装すること + DBからフェッチしたデータはEntityオブジェクトにマッピングしてDAOから返却する + RepositoryはEntityをDTOに変換して返却する + DOMAの警告やエラーが発生している場合は適切に修正すること + 2-way SQLが、実際にDBで動作することを確認すること
AIエージェントとのチャットのやり取りは長くなるため、冒頭部分のみ示します。

DBのテーブル構造を把握したうえで、適切なSQLを組み立てようとしていることがわかります。
生成されたDAOのインターフェースは以下です(インターフェースの実装クラスは、Domaが自動生成してくれます)。
package com.example.rentaldemo.dao; import com.example.rentaldemo.entity.CustomerActorAnalysisEntity; import com.example.rentaldemo.entity.UnwatchedFilmEntity; import org.seasar.doma.Dao; import org.seasar.doma.Select; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @Dao public interface CustomerActorAnalysisDao { 指定顧客の期間内レンタル作品から最頻出俳優を特定 @param customerId @param startDate @param endDate @return @Select OptionalfindTopActorByCustomerRentals( Integer customerId, LocalDateTime startDate, LocalDateTime endDate ); 指定俳優の出演作品のうち顧客が未レンタルの作品を取得 @param customerId @param actorId @param limit @return @Select List findUnwatchedFilmsByActor( Integer customerId, Integer actorId, Integer limit ); }
一つ目のメソッド findTopActorByCustomerRentals に対応するSQLテンプレートは以下のように生成されました。
SELECT a.actor_id, a.first_name, a.last_name, COUNT(*) as appearance_count, c.customer_id, CONCAT(c.first_name, ' ', c.last_name) as customer_name FROM rental r JOIN inventory i ON r.inventory_id = i.inventory_id JOIN film f ON i.film_id = f.film_id JOIN film_actor fa ON f.film_id = fa.film_id JOIN actor a ON fa.actor_id = a.actor_id JOIN customer c ON r.customer_id = c.customer_id WHERE r.customer_id = 1 AND r.rental_date >= '2005-01-01 00:00:00' AND r.rental_date <= '2005-12-31 23:59:59' GROUP BY a.actor_id, a.first_name, a.last_name, c.customer_id, c.first_name, c.last_name ORDER BY appearance_count DESC LIMIT 1
Domaでは、Daoのメソッドパラメータと、SQLテンプレート中のバインド変数とが対応づいている必要があります。たとえば、メソッドパラメータ customerId には、SQLテンプレートの /* customerId */ が対応します。
所感
Postgres MCP Proの有用性
今回の検証では、コンテキストにDB設計に関する情報は一切含めていません。にもかかわらず、MCPサーバーを経由してDBのメタ情報を取得して利用することで、AIエージェントがデータモデルを把握してSQLを正しく組み立てられるようになりました。サンプルDBがシンプルなことも一因でしょうが、コンテキストに与える情報を工夫すれば、実際の開発現場で取り扱う大きなデータモデルにおいても精度向上が見込めるでしょう。
また、MCPサーバーによって、生成したSQLを実行してフィードバックを得ることが可能となります。それにより、AIエージェントが実行可能なSQLを生成することを担保することができます。Postgres MCP Pro はパフォーマンスチューニングのツールも提供するため、SQLの性能面においても効果が期待されます。
Domaの生成AI親和性
AIエージェントがMCPサーバー経由でSQLの実行確認ができるのは、Domaの two-way SQL の仕組みのおかげです。先に示したSQLテンプレートでは、バインド変数の埋め込みはSQLコメントを用いて記述されています。このように、テンプレート上の諸々の操作はSQLコメントを利用するため、DomaのSQLテンプレートは基本的にそのままSQLとして実行可能です。
また、Domaはコンパイル時にアノテーション処理を使用してソースコードの検証と生成を行います。前述の「Daoのメソッドパラメータと、SQLテンプレート中のバインド変数が対応づいている」という条件もコンパイル時にチェックされ、満たしていなければエラーが出力されます。AIエージェントは、環境と相互作用し、得られたフィードバックをもとに誤りを訂正しながらゴールへと近づいていくものです。Domaのコンパイル時チェックは、AIエージェントの利用において非常に有益であると感じました。
動作検証環境
今回の検証に利用した環境は以下のとおりです。
- OS
- 開発環境
- 仮想環境
執筆:@tyonekubo
レビュー:@nakamura.toshihiro
(Shodoで執筆されました)
コメント