RAG アプリケーションを MCP に対応させる

# この記事の内容
python ベースの RAG アプリケーションを MCP サーバー化して、MCP クライアント (Claude for Desktop) から呼び出すまでの作業手順を記載しています。

# MCP について
Model Context Protocol（MCP）は、Anthropicが2024年に提案したLLMと外部ツール/データの連携を統一するためのオープンプロトコルです。
Anthropic のアナウンス

https://www.anthropic.com/news/model-context-protocol

簡単な説明ですが、
- あらゆるLLMがあらゆる外部データソース・機能に統一的手法でアクセスできる
- 異なるLLMと異なるツールの“組み合わせ地獄（M×N問題）”を解消し、開発者・モデル提供者・ツール提供者の連携基盤を提供する
- イメージとしては「AIにおけるUSB-Cポート」。どのLLMにも、どのツールにも、同じ“コネクタ”で接続可能である
- 2025年3月に OpenAI も MCP 準拠を表明し、AI エージェントにおけるツール接続規格の国際標準になりつつある

ということで、今後の Agent アプリケーションは MCP への準拠が必須になってくるのではないかと思います。

# RAG アプリケーションについて
現状は以下のような構成になっています。
ユーザーからの質問を受け付けた python プロセスは IBM Cloud 上の Open Search を使用して、関連文書を検索、同じく IBM Cloud 上の watsonx.ai LLM を使用して回答を生成しユーザーへ返しています。

![スクリーンショット 2025-04-20 17.44.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564348/e39df609-8c96-470e-ad8f-9fa6aec77ef6.png)

# MCP 対応後の構成
今回作成する RAG アプリケーションを MCP サーバー化した構成は以下のとおりです。
Claude for Desktop は MCP サーバーのプロセスを自身の子プロセスとして起動して stdio を通じて通信を行います。

![スクリーンショット 2025-04-20 17.51.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564348/307e8eab-28c3-45c6-a5e0-7bc4e1d59d50.png)

# RAG アプリケーションの MCP サーバー化
こちらの手順を参考にしています。
uv による python 環境の準備などの手順は省略します。

https://modelcontextprotocol.io/quickstart/server

## python コード snippet
### SDK のインポート
```python
from mcp.server.fastmcp import FastMCP
```

### initialize FastMCP server
"rag_application" はサーバー名で適切な名前を入れます。
python の SDK は 名前が似ている FastAPI と同じ starlette をベースに実装されているようです。
```python
mcp = FastMCP("rag_application")
```

### tools の定義
今回はユーザーの入力をテキストで受け取り、RAG の機能を用いて回答をテキストで返す tools を１つ作成します。
tools の場合、関数の１行上に @mcp.tool() というアノテーションをつけるようです。
また、関数の直後の行から docstring の形式で tools の説明と引数を記載する必要があります。
元々の RAG アプリケーションが IBM Z OS に関する質問に回答するアプリなので、そのような説明文と引数を記載しています。
また、詳細は省略しますが、answer_generate_batch が、ユーザーの質問文をテキストで受け取り、RAG の仕組みで回答を生成してテキストで返す関数になっています。
```python
@mcp.tool()
def get_rag_answer(user_input: str) -> str:
    """Find and answer questions about IBM Z OS by searching for specialized documents.

    Args:
        user_input: question about IBM Z OS
    """
    return answer_generate_batch(user_input)
```

### entry point
```python
if __name__ == '__main__':
    mcp.run(transport='stdio')
```

# MCP クライアントの設定 (Claude for Desktop)
claude_desktop_config.json を編集します。
Claude for Desktop で "設定" -> "開発者" -> "構成を編集" の手順で開くことができるかと思います。
以下のように "rag_application" の部分に先ほど定義したサーバー名を、"command" には uv の絶対パスを、"args" には先ほど定義した MCP サーバーの python スクリプトへのパスや python ファイル名を記載します。
```json
{
    "mcpServers": {
        "rag_application": {
            "command": "/path/to/uv",
            "args": [
                "--directory",
                "/path/to/server_mcp",
                "run",
                "server_mcp.py"
            ]
        }
    }
}
```

# 動作確認
MCP サーバーが正しく設定されていると以下のようにテキストボックスの下の金槌のマークに数字が表示されます。画像は今回の RAG アプリケーション以外にも MCP サーバーを設定しているので、"3" と表示されています。

![スクリーンショット 2025-04-24 16.33.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564348/d7d40d64-1f85-4e79-9346-05b601e4ae80.png)

金槌マークをクリックすると現在設定されている MCP ツールが説明とともに表示されます。
以下の画像のように、今回設定した rag_application も表示されています。

![スクリーンショット 2025-04-24 16.34.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3564348/fe763555-cf10-421e-aaa3-829de6a71968.png)

IBM Z OS に関する質問を試しにしてみます。
すると処理の途中で MCP サーバー get_rag_answer から詳細な情報を取得し適切な回答を出力してくれることを確認しました。（画像は省略）

# 参考
公式ドキュメント

https://modelcontextprotocol.io/introduction