プログラマー必見！FastAPI-MCPでAI時代のAPI開発を加速する方法（初心者向けコード付き）

## はじめに

みなさん、こんにちは！最近、API開発の現場で「これマジですごい！」と思わず叫んでしまったツールを見つけたんですよ。それが「[**FastAPI-MCP**](https://github.com/tadata-org/fastapi_mcp)」です！

FastAPI使ってる人なら絶対に知るべきツールです。だって、あなたのAPIをAIモデル（GPTやClaudeなど）に簡単に操作させることができるんですから！私みたいな初心者でも数分で設定できちゃいました。

## FastAPI-MCPって何がすごいの？

まず、FastAPI-MCPの核となる機能を紹介します：

- **認証機能が標準装備**：FastAPIの依存性注入（Depends()）をそのまま使えるから、セキュリティ面も安心！
- **FastAPIとの相性抜群**：単なるOpenAPI変換ツールじゃなく、FastAPIのASGIインターフェースを直接使うから超効率的！
- **設定ほぼゼロ**：FastAPIアプリを指定するだけでMCPツールが自動生成されるんです。マジで簡単！
- **スキーマ情報をそのまま保持**：リクエストとレスポンスのモデル構造がそのまま維持されるから、データ構造の正確性が保証されます。
- **APIドキュメントも維持**：Swaggerドキュメントとの一貫性も保たれるので、開発者体験も最高です！
- **柔軟な配置オプション**：MCPサーバーを同じFastAPIアプリにマウントすることも、別々に配置することも可能です。
- **ASGI転送の高速性**：FastAPIのASGIインターフェースを直接使用するため、余計なHTTPコールのオーバーヘッドがありません

![fastmcp-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/1b584417-1ddc-42f0-a0a4-e4799a8a8a0c.png)

## なぜFastAPI-MCPを選ぶべきなの？

正直に言いますと、私も最初はAPIをMCPツールに手動で変換しようとして、こんな問題にぶつかりました：

- インターフェース適応コードを何度も書き直す必要があって、作業量が膨大でミスも多発...
- 認証と権限制御が複雑で、セキュリティ確保が難しい...
- APIドキュメントとデータモデルの同期維持が大変で、メンテナンスコストが高い...
- 従来のHTTP転送だと遅延が増加して、パフォーマンスが制限される...

でも、FastAPI-MCPはFastAPIと深く統合されているので、これらの問題を全部解決してくれるんです！普通のFastAPIアプリを書くのと同じくらい簡単にMCPツールが生成できて、しかも高性能とセキュリティも確保されています。

## 実際に使ってみよう！

それでは、ローカル環境でFastAPI MCPを構築してテストする方法を一緒に見ていきましょう！

### ステップ1：Python 3.10+（3.12推奨）環境を準備する

まずは基本中の基本、Pythonの環境を用意しましょう！

もしPythonをまだインストールしていなければ、[Python公式サイト](https://www.python.org/downloads/)から最新版をダウンロードしてインストールしてください。

インストール後、コマンドラインで確認してみましょう：

```
python --version
# または
python3 --version
```

### ステップ2：必要なパッケージをインストールする

次に、FastAPI、Uvicorn、そしてFastAPI MCPをインストールします：

```
pip install fastapi uvicorn fastapi-mcp
```

### ステップ3：シンプルなFastAPIアプリを作成する

トラブルを避けるため、まずは超シンプルなFastAPIアプリを作ってみましょう。`main.py`というファイルを作成して、以下の内容を書き込みます：

```python
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP

app = FastAPI(title="シンプルAPI")

@app.get("/hello", operation_id="say_hello")
async def hello():
    """シンプルな挨拶エンドポイント"""
    return {"message": "Hello World"}

# MCPサーバーを作成
mcp = FastApiMCP(app, name="シンプルMCPサービス")
mcp.mount()

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

このサンプルは本当にシンプルで、`/hello`エンドポイントだけを持ち、簡単な挨拶メッセージを返します。

![fastmcp-11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/2e6ab7c6-fd67-4f3a-99fb-32af17c5258b.png)

### ステップ4：アプリを実行してテストする

さあ、アプリを実行してテストしてみましょう：


:::note info
APIテストツールをお探しなら、[Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya&utm_content=fastapimcp)もチェックしてみてください！FastAPI-MCPと組み合わせれば、APIの開発からテスト、AI連携まで一気通貫で効率化できます。[Apidog](http://www.apidog.com/jp/?utm_source=opr&utm_medium=a2takuya&utm_content=fastapimcp)の直感的なインターフェースと強力な機能で、API開発の生産性が劇的に向上します。
:::


```
python main.py
```

または：

```
uvicorn main:app --reload
```

サーバーは`http://127.0.0.1:8000`で起動します。

![fastmcp-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/4aa41d27-7e45-473f-ada4-08d3850cbbd9.png)

### ステップ5：MCPエンドポイントを探索する

ブラウザを開いて、MCPエンドポイントにアクセスしてみましょう：`http://127.0.0.1:8000/mcp`

注意：通常のAPIとは異なり、MCPエンドポイントはServer-Sent Events (SSE)プロトコルを使用しているため、ブラウザでは次のような出力が表示されます：

```
event: endpoint
data: /mcp/messages/?session_id=02b22de319bb43e596ec91ed5d480411
```

![fastmcp-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/96c1308e-8b73-4194-bfa1-99a8adc37d1a.png)

これは、MCPサーバーが起動し、AIクライアントからのリクエストを受け付ける準備ができたことを示しています。

## AIクライアントでFastAPI MCPに接続する

次に、MCPをサポートするAIクライアントをサーバーに接続する必要があります。Cursorを例に説明します：

### 方法1：SSE（Server-Sent Events）接続を使用する

Claude Desktop、Cursor、Windsurfなどの主要なMCPクライアントはSSE接続をサポートしており、以下の設定形式を使用します：

```json
{
  "mcpServers": {
    "fastapi-mcp": {
      "url": "http://localhost:8000/mcp"
    }
  }
}
```

各クライアントで、対応する設定セクションを見つけてこの設定を追加するだけです。例えば、Cursorでは、右上の設定アイコンをクリックし、「MCP -> Add new global MCP server」に移動して、開いた`mcp.json`ファイルに上記のJSON設定を入力します。
![fastmcp-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/10567f73-b64b-4b97-a994-0866ebe65ed7.png)

FastAPI MCPサービスが起動していれば、Cursorで自動的に有効になります！

### 方法2：mcp-remoteをブリッジとして使用する

認証が必要な場合や、MCPクライアントがSSEをサポートしていない場合は、`mcp-remote`をブリッジとして使用できます：

```json
{
  "mcpServers": {
    "fastapi-mcp": {
      "command": "npx",
      "args": [
        "mcp-remote",
        "http://localhost:8000/mcp",
        "8080"  // オプションのポート番号
      ]
    }
  }
}
```

## AIクライアントでFastAPI MCPを使用する

CursorなどのAI IDEでFastAPI MCPに接続したら、対話を開始できます。例えば、Cursorのエージェントモードで「`/hello` APIを呼び出して」と質問すると、AIはインターフェースの出力結果を返します！

![fastmcp-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3877124/ea75793f-4219-44ac-a5b1-459fc8489d15.png)

## 上級テクニック

基本的な使い方をマスターしたら、FastAPI MCPをより柔軟に使うためのいくつかの上級テクニックを見ていきましょう。

### カスタムエンドポイント公開

実際のアプリケーションでは、すべてのAPIエンドポイントをAIモデルに公開したくない場合があります。FastAPI MCPは、どのエンドポイントを公開するかを制御するための複数の方法を提供しています：

```python
# 特定の操作IDのみを公開
mcp = FastApiMCP(
    app,
    include_operations=["say_hello", "get_user_info"]
)

# 特定の操作IDを除外
mcp = FastApiMCP(
    app,
    exclude_operations=["delete_user", "update_settings"]
)

# 特定のタグを持つエンドポイントのみを公開
mcp = FastApiMCP(
    app,
    include_tags=["public", "read_only"]
)

# 特定のタグを持つエンドポイントを除外
mcp = FastApiMCP(
    app,
    exclude_tags=["admin", "sensitive"]
)
```

この柔軟性により、AIモデルが利用できる機能を正確に制御でき、セキュリティが向上します。

### 認証保護の追加

本番環境では、MCPエンドポイントを保護して、認証されたクライアントのみがアクセスできるようにしたい場合があります：

```python
from fastapi import FastAPI, Depends, Security, HTTPException
from fastapi.security import APIKeyHeader

app = FastAPI()
api_key_header = APIKeyHeader(name="X-API-Key")

# API鍵を検証する関数を定義
async def verify_api_key(api_key: str = Security(api_key_header)):
    if api_key != "your-secret-key":  # 実際のアプリケーションでは環境変数や安全なストレージを使用すべき
        raise HTTPException(status_code=403, detail="Invalid API key")
    return api_key

# 認証依存関係を追加してMCPサーバーを作成
mcp = FastApiMCP(app, mcp_dependencies=[Depends(verify_api_key)])
mcp.mount()
```

これで、MCPサービスへのすべてのリクエストには、ヘッダーに有効なAPI鍵が含まれている必要があります。

### カスタムレスポンス処理

AIモデルに返すレスポンスに追加情報を含めたり、フォーマット変換を行いたい場合があります：

```python
from fastapi import FastAPI, Response, Request
from fastapi_mcp import FastApiMCP
from typing import Callable, Dict, Any
from datetime import datetime

app = FastAPI()

# カスタムレスポンスプロセッサを定義
async def response_processor(
    request: Request,
    response: Response,
    response_data: Dict[str, Any]
) -> Dict[str, Any]:
    # メタデータの追加やレスポンスの修正
    response_data["processed_by"] = "custom_processor"
    response_data["timestamp"] = datetime.now().isoformat()
    return response_data

# レスポンスプロセッサを追加してMCPサーバーを作成
mcp = FastApiMCP(
    app,
    response_processor=response_processor
)
mcp.mount()
```

### 分離デプロイ

一部のシナリオでは、MCPサーバーをメインAPIサービスとは別にデプロイしたい場合があります：

```python
# api_app.py - メインAPIアプリケーション
from fastapi import FastAPI
api_app = FastAPI()

@api_app.get("/data")
def get_data():
    return {"data": "some value"}

# mcp_app.py - 独立したMCPサーバーアプリケーション
from fastapi import FastAPI
from fastapi_mcp import FastApiMCP
from api_app import api_app  # メインAPIアプリケーションをインポート

mcp_app = FastAPI()
mcp = FastApiMCP(api_app)
mcp.mount(mcp_app)  # api_appではなくmcp_appにマウント

# 2つのアプリケーションを別々に実行できます：
# uvicorn api_app:api_app --port 8001
# uvicorn mcp_app:mcp_app --port 8000
```

この方法により、MCPサービスを独立してスケーリングしたり、異なるAPIアプリケーションに統一されたMCPアクセスポイントを提供したりできます。

## 注意事項

FastAPI MCPを使用する際には、プロトコルのセキュリティに関する考慮事項があります：

1. 公開するエンドポイントを制限する：安全な読み取り専用のエンドポイントのみを公開し、システムに変更を加える可能性のあるエンドポイント（DELETE、PUT操作など）の公開を避けます。
2. 適切な認証を追加する：認証されたユーザーのみがAIを通じてAPIにアクセスできるようにします。
3. リクエスト検証：FastAPIのPydanticモデルを使用して、リクエストパラメータを厳密に検証します。
4. レスポンスフィルタリング：特にAIモデルがこれらの情報をユーザーに表示する可能性がある場合、レスポンス内の機密情報をフィルタリングすることを検討します。

## まとめ

FastAPI MCPの使用は本当に簡単です！Python環境さえあれば、数分でAPIをAIが呼び出せるツールに変えることができます。全体のプロセスは次のようにまとめられます：

1. Python 3.10+（3.12推奨）をインストール
2. 必要なパッケージをインストール
3. FastAPIアプリケーションを作成
4. MCPサポートを追加
5. AI IDEでFastAPI MCPを実行してテスト

FastAPI-MCPは、FastAPI APIをMCPツールに迅速に変換したい開発者に最適な、効率的で使いやすく、機能豊富なツールです。わずか数行のコードで統合が完了し、認証、ドキュメント保持、柔軟なデプロイをサポートしており、FastAPIエコシステムでMCPに接続するための理想的な選択肢です。

FastAPI-MCPを使えば、AIとAPIの連携が驚くほど簡単になります。みなさんも是非試してみてください！質問やコメントがあれば、ぜひ共有してくださいね。一緒にAI時代の開発を楽しみましょう！

## 参考
[1] https://github.com/tadata-org/fastapi_mcp
[2] https://modelcontextprotocol.io/introduction