MCPが便利そうなので Oracle DB とおしゃべりする MCP サーバーを作ってみた #Python

はじめに

最近、MCP(Model Context Protocol)が注目を集めていますね。そこで、MCPを使って、Cursor や Cline などからシームレスに Oracle データベースにアクセスする MCP サーバーを作ってみました。

こんな感じでテーブルの構造を聞いてみたり

こんな感じで LLM に SQL を書かせて、その場でテストしてみたりすることができます。

image.png

そのそも、MCPとは?

MCP は、「AIモデルが自由に着脱可能な手足や感覚器官の共通インターフェース規格であり、AIモデルの外界との相互作用を大きく促進する可能性を秘めている」という雰囲気のAIモデルをパワーアップしてくれるプロトコルです。これを作ったのはClaude の Anthropic 社ですので “Modular Open Nervous-system for Embodied Transformer” = MONET が良かったのでは?

それはさておき、MCP は、LLMがさまざまなツールやリソースにアクセスするための仕組みです。これにより、LLMはファイルシステム、データベース、APIなどの外部リソースと容易に連携できるようになります。CursorやClaude DesktopなどのMCPホスト(クライアント)は、この仕組みを活用してLLMの能力を拡張して、開発環境としての開発者の体験を向上させることができます。

MCP のコンポーネント

MCP は以下のような3つのコンポーネントで構成されるクライアント・サーバーアーキテクチャを採用しています。

  • ホスト:ユーザーが直接対話するアプリケーション(Claude Desktop、CursorなどのIDE、カスタムエージェント)で、AIモデルが必要に応じてクライアントを通して、サーバーを利用します
  • クライアント:ホストアプリケーション内に存在し、特定のMCPサーバーへの接続を管理します
  • サーバー:標準APIを通じてツール、リソース、プロンプトを公開する外部プログラムで、プロキシーのような役割を担います

作ったもの

今回、作成したのは、MCPサーバーです。 コードは、以下の Github リポジトリで公開してます。

この「MCP Server for Oracle Database」は、LLMがOracle Databaseに対してSQLクエリを実行できるようにするMCPサーバーの実験的な実装です。ローカル環境で動作し、CursorやClaude DesktopなどのMCPホスト(クライアント)から利用できます。

Cursor などでコード開発をしているときにデータベースの構造を確認したくなったり、SQLをテストしてみたいときにCursorなどのチャットウィンドウを離れることなく Oracle データベースと連携することができます。

主な機能

  • Oracle DatabaseへのSQLクエリ実行(SELECT文のみ)
  • テーブル構造の取得
  • 若干のセキュリティ対策(クエリ長制限、危険なキーワードチェックなど)
  • 結果のフォーマット機能(いらないかも)
  • MCP のプロンプト機能を使って、LLMに対して tool の使い方をガイドし成功率を挙げている

セットアップ方法

必要条件

  • Python 3.11以上
  • Oracle Databaseへのアクセス権限
  • 必要な環境変数の設定(.envファイル)
  • uv(高速なPythonパッケージマネージャー)

インストール手順

  1. リポジトリをクローン

    git clone https://github.com/kutsushitaneko/mcp-server-for-oracle-database
    cd mcp-server-for-oracle-database
    
  2. 仮想環境を作成してアクティベイト

  3. 依存パッケージをインストール

    uv pip install -r requirements.txt
    
  4. 環境変数の設定
    .envファイルを作成し、以下の情報を設定します。

    ORACLE_USER=your_username
    ORACLE_PASSWORD=your_password
    ORACLE_DSN=your_dsn
    

MCPクライアントへの登録

Claude Desktop や Cursor などの MCPクライアントの設定ファイルに以下を追加します。

{
  "mcpServers": {
    "ORACLE": {
      "command": "仮想環境の Python 実行ファイルへの絶対パス(...\mcp-server-for-autonomous-database\.venv\Scripts\python.exe)",
      "args": [
        "MCPサーバーの絶対パス(....\mcp-server-for-oracle-database\oracledb_mcp_server.py)"
      ]
    }
  }
}

※構成ファイルを変更した後は、MCPクライアントの再起動が必要です。Claude Desktopの場合、バックグラウンドで動いているプロセスも一度停止してから再起動してください。

提供されるツール

execute_oracle

SQLクエリ(SELECT文のみ)を実行し、結果をフォーマットして返します。

パラメータ

  • query: SQLクエリ(SELECT文のみ)
  • params: バインド変数
  • max_length: 応答の最大文字数
  • max_rows: 取得する最大行数

oracle_query_assistant

(2025/4/14 23:20 Updated)

execute_oracle(Oracle Databaseへのクエリ実行)をガイドするプロンプトを返します。

パラメータ

  • query_type: SQL のタイプ(現在は、”select”のみ)

※ SELECT 文の例やバインド変数の使い方、パラメータのデータ型を詳しく説明したプロンプトへ返します。
LLM はこの情報を元に execute_oracle() をより正確に起動できるようになります。

describe_table

テーブルの構造を表示します。sqlplusのdescribeを模しています。

パラメータ

  • table_name: テーブル名

使用例

※ここに挙げるのはあくまでも例です。LLMが文脈に応じて適切にトリガーを引いてくれます(と期待)。

テーブルの構造を表示

xxxx テーブルの構造をしらべて

または

screenshot_sample-01.jpg

テーブルのデータを取得

xxxx テーブルのデータを取得して

screenshot_sample-02.jpg

screenshot_sample-03.jpg

screenshot_sample-04.jpg

SQLの実行

この SQL を試してみて

コード解説(2025/4/14 23:20 Updated)

MCP 固有のコードだけ簡単にご紹介します。

MCPサーバーの初期化

from mcp.server.fastmcp import FastMCP
mcp = FastMCP("ORACLE")

FastMCPクラスをインポートして「ORACLE」というID/名前でMCPサーバーのインスタンスを作成しています。

ツール定義

@mcp.tool(
    name = "execute_oracle",
    description = """
    Oracle Databaseに対してSQLクエリを実行し、結果をフォーマットして返す。
        Args:
            query: 実行するSQLクエリ(必須)
            params: バインド変数に使用するパラメータ(辞書型 例:{"parameter1": 5})
            max_length: 応答の最大文字数(integer型、デフォルト: 1000)
            max_rows: 取得する最大行数(integer型、デフォルト: 10)
        ヒント:
            文字数制限にかかったときは、max_lengthを大きくしてください。
    """)
def execute_oracle(query: str, params: dict = None, max_length: int = 1000, max_rows: int = 10) -> str:
    # 以下は処理の実装

@mcp.toolデコレータは、MCPサーバーにツールとして公開する関数を定義しています。この例では「execute_oracle」という名前のツールが定義されており、引数とその説明が提供されています。

プロンプト定義

MCP では、MCP サーバーから MCP クライアントへプロンプトを返すことができます。MCPクライアントは、受け取ったプロンプトを LLM のコンテキストへ挿入します。これを利用して、MCPサーバーから、自身のツールやリソースの使い方を LLM へガイドしてあげることが可能です。この機能を使って execute_oracle 関数のパラメータ設定やバインド変数の使い方をガイドしているのが下記のコードです。

コードの書き方としては、単位プロンプトのテンプレートや説明のテキストを返す関数を作って、デコレータ で修飾するだけです。MCPにおいては、@mcp.prompt()デコレータは、通常のPython関数をMCPのプロンプト機能として登録・定義するために使われています。このデコレータによって、Pythonの関数はMCPフレームワークに統合され、AIモデルとの対話に使用できるようになります。

@mcp.prompt()
def oracle_query_assistant(query_type: str = "select") -> str:
    """
    # 以下は execute_oracle の使い方の説明

このプロンプトがない状態では、Cursor(モデルの選定はAuto)も Claude Desktop もSQLの応答文の最大長を指定する max_lenght のデータ型やバインド変数の使い方を繰り返し試行錯誤してしまいますが、この機能を実装してからは Claude Desktop はほぼ試行錯誤することなく目的の動作をできるようになりました。Cursor は、まだ試行錯誤しますが、諦めて他の手段へ移る頻度が減りました。

サーバー起動

if __name__ == "__main__":
    # stdioで通信
    mcp.run(transport="stdio")

これがMCPサーバーを実際に起動する部分です。標準入出力(stdio)を使用して通信するように設定されています。これにより、このPythonスクリプトを実行すると、標準入出力を通じてMCPプロトコルでクライアントと通信するサーバーとして動作します。

セキュリティについて

本プロジェクトでは、最小限のセキュリティ対策を施しています。

  • SELECT文以外は受け付けません
  • クエリ長の制限(デフォルト: 1MB)
  • 危険なキーワードのチェック
  • 入力値のサニタイズ
  • 読み取り専用クエリの検証

⚠️ 注意: 外部からアクセスできないローカルな環境でのみ使用してください。

おわりに

2,3 時間でざっと作ったものなのでまだまだ荒いところが沢山ありますが、この段階でも便利さを感じています。
MCP恐るべしですね。

※本記事で紹介したプロジェクトは実験的なものであり、本番環境での使用は推奨していません。
※サーバーなのでデータベースコネクションはもっと賢く管理したいところですが現在のコードは MCP クライアントからリクエストが来るためにコネクションを確立して、応答完了ごとに閉じています。改善したいですね。



フラッグシティパートナーズ海外不動産投資セミナー 【DMM FX】入金

Source link