2025-05-22 / @syui

openai , llm , mcp , chatgpt

mcpとfastapi

引き続きmcpを使ってみたいと思います。まだまだmcpをどのように使っていけばいいのかわかりませんが、今のところ考えている使い方を紹介します。

AIとの会話を記録し、それをAIが使用するというものです。人にとって同じことを各AIに伝えるのは大変なことです。しかし、各AIがその記録を参照できるなら楽ですよね。

そのために使えるのがfastapi, fastapi_mcpです。

mcpでAIが自発的にtoolを使える環境を用意します。

例えば、openaiにはtools ,tool_choiceがありますので、それを使ってみます。

# このコマンドを実行
git clone https://github.com/microsoft/MCP.git
cd MCP
python3 -m venv .venv
source .venv/bin/activate

echo "
# setup.py
from setuptools import setup

setup(
    name='simple-example',
    py_modules=['cli'],
    entry_points={
        'console_scripts': [
            'mcp = cli:main',
        ],
    },
)" > setup.py

pip install -e .
pip install openai fastapi fastapi_mcp requests
# server.py
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP

app = FastAPI()
mcp = FastApiMCP(app, name="simple-example", description="最小限のMCPサーバー例")

@app.get("/hello", operation_id="greet")
async def hello(name: str = "World"):
    return {"message": f"Hello, {name}!"}

mcp.mount()

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)
$ curl "http://localhost:8000/hello?name=Alice"
# 出力: {"message":"Hello, Alice!"}
# ask.py
import os
import openai
import requests
import json

cfg = {
    "model": "gpt-4o-mini",
    "api_key": os.environ["OPENAI_API_KEY"]
}
user_message = "田中さんに挨拶して"

tools = [
    {
        "type": "function",
        "function": {
            "name": "greet",
            "description": "名前を指定して挨拶します",
            "parameters": {
                "type": "object",
                "properties": {
                    "name": {
                        "type": "string",
                        "description": "挨拶する相手の名前"
                    }
                },
                "required": ["name"]
            }
        }
    }
]

client = openai.OpenAI(api_key=cfg["api_key"])

payload = {
    "model": cfg["model"],
    "messages": [
        {"role": "system", "content": "必要に応じてgreetツールを使って挨拶してください。"},
        {"role": "user", "content": user_message}
    ],
    "tools": tools,
    "tool_choice": "auto"
}

# 1. OpenAI APIにリクエスト
response = client.chat.completions.create(**payload)
message = response.choices[0].message

# 2. ツール呼び出しがあればMCPサーバーへリクエスト
if message.tool_calls:
    for tool_call in message.tool_calls:
        if tool_call.function.name == "greet":
            args = json.loads(tool_call.function.arguments)
            # MCPサーバーにGETリクエスト
            mcp_response = requests.get(
                "http://localhost:8000/hello",
                params=args
            )
            tool_output = mcp_response.json()["message"]

            # 3. OpenAI APIにtool_outputsとして返す
            followup = client.chat.completions.create(
                model=cfg["model"],
                messages=[
                    {"role": "system", "content": "必要に応じてgreetツールを使って挨拶してください。"},
                    {"role": "user", "content": user_message},
                    {
                        "role": "assistant",
                        "content": None,
                        "tool_calls": [tool_call.model_dump()],
                    },
                    {
                        "role": "tool",
                        "tool_call_id": tool_call.id,
                        "name": "greet",
                        "content": tool_output,
                    }
                ]
            )
            print(followup.choices[0].message.content)
    print("ツールが使われました。内容:", message.tool_calls)
    for tool_call in message.tool_calls:
        print(f"tool name: {tool_call.function.name}, arguments: {tool_call.function.arguments}")
else:
    # 通常のAI応答
    print(message.content)
$ python server.py                                               
---
$ export OPENAI_API_KEY=sk-xxx
$ source .venv/bin/activate

$ python ask.py
田中さん、こんにちは!
ツールが使われました。

これは何をやっているのかというと、「mcp serverを立てて、AIがそれを使用して返事をした」というものです。

fastmcpfastapi_mcpの違い

$ pip show mcp
Home-page: https://modelcontextprotocol.io
Author: Anthropic, PBC.

$ pip show fastmcp
Home-page: https://gofastmcp.com
Author: Jeremiah Lowin

$ pip show fastapi_mcp
Home-page: https://github.com/tadata-org/fastapi_mcp
Author:
  • fastmpc: mcpサーバーを最小構成で高速に構築するためのパッケージ

  • fastapi_mcp: apiをmcpに対応しAIにも使えるようにするパッケージ

例えば、キャラクターデータをapiで公開し、それを表示するwebを作成する場合などは、fastapi_mcpを使用するのがいいですね。