---
title: "FastMCPとは？PythonでMCPサーバーを作る手順とFastMCP 4.1の使い方【2026年10月】"
url: "https://www.issoh.co.jp/tech/details/6507/"
published: 2025-05-02
updated: 2026-10-17
categories: ["AIエージェント・MCP"]
publisher: "株式会社一創"
---

# FastMCPとは？PythonでMCPサーバーを作る手順とFastMCP 4.1の使い方【2026年10月】

FastMCP（fast mcp）は、**MCP（Model Context Protocol）のサーバーとクライアントをPythonで作るためのフレームワーク**です。Pythonの関数に`@mcp.tool`を付けると、Claude CodeなどのAIエージェントから呼べるツールになります。この記事では、2026年10月17日に**fastmcp 4.1.0／mcp 2.3.0／Python 3.12.13**で実際に動かした結果をもとに、インストール、最小コード、動作確認、Claude Codeへの接続、FastAPI連携、認証、例外の扱いまでを説明します。一次情報は公式リポジトリ[PrefectHQ/fastmcp](https://github.com/PrefectHQ/fastmcp)と公式ドキュメント[gofastmcp.com](https://gofastmcp.com/getting-started/welcome)です。

## まとめ：FastMCPの用途・導入手順・選定条件

- **何をするものか**：MCPサーバー・クライアント・会話内UI（Apps）をPythonで作るフレームワーク。「APIモックを生成するツール」という説明は誤りです。
- **現行版**：最新は4.1.0（PyPI公開 2026-10-08）。3系も3.4.9（2026-10-16）まで保守版が出ています。必要なPythonは3.10以上です。
- **最小実装**：`uv add fastmcp`のあと、`FastMCP("Demo")`→`@mcp.tool`→`mcp.run()`の数行で動きます。型ヒントとdocstringから入力スキーマと説明文が作られます。
- **確認と接続**：`Client(mcp)`でプロセス内から呼んで試し、`fastmcp install claude-code server.py`でClaude Codeに登録します。
- **本番で外せない設定**：HTTP公開では`JWTVerifier`で認証し、`mask_error_details=True`で例外の中身を隠します。既定のままだと素の例外メッセージがクライアントへ届きます。
- **選び方**：既存のFastAPIやOpenAPIをMCP化する、複数サーバーを束ねる、クライアントも書くならFastMCP。サーバー1本を最小構成で出すだけなら公式SDKでも足ります。

## FastMCPとは：MCPサーバー・クライアント・Appsを作るPythonフレームワーク

公式ドキュメントはFastMCPを「MCPのサーバー、クライアント、対話型アプリケーションを作るための標準フレームワーク」と定義しています。開発者は処理を書いた関数を渡すだけで、スキーマ生成・入力検証・トランスポート・認証・プロトコルの版の交渉はFastMCPが受け持ちます。柱は3つあります。関数やデータをツール・リソース・プロンプトとして公開する**Servers**、任意のMCPサーバーへPython・CLIから接続する**Clients**、ツールの結果を会話の中に表やグラフのUIとして出す**Apps**（3.0.0で追加、`pip install "fastmcp[apps]"`）です。

リポジトリは[PrefectHQ/fastmcp](https://github.com/PrefectHQ/fastmcp)（旧jlowin/fastmcp）で、ライセンスはApache-2.0、GitHubのスター表示は2026年10月17日時点で28.1kです。READMEは「全言語のMCPサーバーの70%を何らかの版のFastMCPが動かしている」「1日100万回以上ダウンロードされている」と書いていますが、どちらも出典の示されていない自称値です。MCPそのものの仕組みは[MCP（Model Context Protocol）とは？AIと外部ツールをつなぐ標準規格の仕組みをわかりやすく解説](/tech/details/5736/)で扱っています。

### FastMCPの用途：APIモック生成とMCPツール公開の違い

日本語の解説には、FastMCPを「APIのモックを生成するツール」と紹介するものがあります。公式リポジトリにもドキュメントにも、モック生成を目的とする記述はありません。FastMCPの役割は、LLMやAIエージェントが呼び出す本物のツールを公開することです。FastAPIやOpenAPI仕様からMCPサーバーを作る機能（後述）と、APIの応答を模擬するモック生成は別の機能です。前者は実在するAPIをエージェントから呼べるようにするもので、偽の応答は作りません。

### 2026年10月時点の版：4.1.0と保守が続く3.4系

| パッケージ             | 版               | PyPI公開日（UTC） |
| ----------------- | --------------- | ------------ |
| fastmcp           | 4.1.0（最新）       | 2026-10-08   |
| fastmcp           | 4.0.0（4系の初の正式版） | 2026-08-31   |
| fastmcp           | 3.4.9（3系の保守版）   | 2026-10-16   |
| mcp（公式Python SDK） | 2.3.0           | 2026-10-02   |

4系は内部の土台を公式MCP Python SDKの2系に移し、MCP仕様の2026-07-28版（ステートレス化）と従来の2025-11-25版の両方に応答します。[4.1.0のリリースノート](https://github.com/PrefectHQ/fastmcp/releases/tag/v4.1.0)は保守中心の内容で、HTTPセッションが無期限保持からSDK既定の30分アイドルタイムアウトに変わった点が破壊的変更に入っています。3系からの移行で何が壊れるかは[FastMCP 4とは？sessionless対応と廃止APIから読む3系からの移行判断](/tech/details/15907/)で詳しく扱います。

## FastMCPのインストール手順：pip・uvでの導入と版の確認

FastMCPはPyPIで配布されています。公式はuvを推奨しています。uvを初めて使う場合は、インストール後に`uv init fastmcp-demo`、`cd fastmcp-demo`でプロジェクトを作成してください。以下のuvとpipはどちらかを選び、uvを選んだ場合は、この後のPython・FastMCPコマンドにも`uv run`を付けて実行します。

```
# uv の場合（公式推奨）
uv add fastmcp

# pip の場合
pip install fastmcp

# 本番は版を固定する
pip install "fastmcp==4.1.0"

# 版の確認
fastmcp version
```

`fastmcp version`を実行すると、手元では「FastMCP version: 4.1.0」「MCP version: 2.3.0」「Python version: 3.12.13」とプラットフォームが表示されました。`pip install fastmcp`で入るのは`fastmcp`と、実装本体の`fastmcp-slim`の2つで、依存として`mcp`（公式SDK）と`httpx2`も入ります。3.2以前から上げて`ModuleNotFoundError`が出たときは、`pip install --force-reinstall fastmcp`で入れ直します。4系はpydantic 2.12以上とStarlette 1.0.1以上を要求するので、古い版を固定しているプロジェクトでは依存の解決で止まります。[公式の移行ガイド](https://gofastmcp.com/getting-started/upgrading/from-fastmcp-3)によると、Starlette 1系を受け入れる最初のFastAPIは0.133.0なので、同じ環境でFastAPIを使っている場合は先にFastAPIを0.133.0以上へ上げます。

## MCPサーバーの作り方：@mcp.toolで関数を公開する最小コード

サーバーは、関数を書いてデコレータを付けるだけで作れます。次のコードを`server.py`として保存しました。ツール・リソース・プロンプトを1つずつ持つ構成です。

```
from fastmcp import FastMCP

mcp = FastMCP("Demo")

@mcp.tool
def add(a: int, b: int) -> int:
    """2つの数値を加算する"""
    return a + b

@mcp.resource("config://version")
def version() -> str:
    return "1.0.0"

@mcp.prompt
def review(code: str) -> str:
    """コードレビューを依頼する定型プロンプト"""
    return f"次のコードをレビューしてください:\n{code}"

if __name__ == "__main__":
    mcp.run()
```

`python server.py`または`fastmcp run server.py`で起動します。`run()`を引数なしで呼ぶとstdio（標準入出力）で待ち受けるので、ポートは開きません。

### 型ヒントとdocstringから生成されるスキーマ

このサーバーにクライアントから`tools/list`を送ると、`add`の入力スキーマは`{"type": "object", "additionalProperties": false, "properties": {"a": {"type": "integer"}, "b": {"type": "integer"}}, "required": ["a", "b"]}`、説明文はdocstringの「2つの数値を加算する」になりました。JSON Schemaを手で書く必要はありません。

見落としやすいのは出力側です。戻り値が`int`のように辞書でない型だと、出力スキーマは`{"result": ...}`で包まれ、`fastmcp list`の表示も`add(a: int, b: int) -> dict`になります。Pythonの`Client`で受け取る`.data`は元の`5`に戻るので、包みを意識するのは他言語のクライアントから構造化出力を読むときです。文字列`"x"`を`a`に渡すと、サーバーはpydanticの検証で弾き、クライアント側には`ToolError`として「Input should be a valid integer」が返りました。

### ツール・リソース・プロンプトの使い分け

| デコレータ           | 公開するもの     | 呼ぶ主体       | 用途の例            |
| --------------- | ---------- | ---------- | --------------- |
| `@mcp.tool`     | 実行できる関数    | LLMが判断して呼ぶ | 計算・検索・外部API呼び出し |
| `@mcp.resource` | 読み取り専用のデータ | ホストのアプリ    | 設定値・ファイル内容      |
| `@mcp.prompt`   | 指示のテンプレート  | 利用者が選ぶ     | 定型のレビュー依頼       |

最初は`@mcp.tool`だけで十分です。LLMに実行させたい処理はツールにし、ホストに読ませたいデータが出てきたらリソースを足します。リソースはクライアントによって扱いが違い、ツールほど確実には使われません。

## 作ったサーバーの動作確認：Client・CLI・pytestで試す

Claude Codeなどにつなぐ前に、Pythonから呼んで動くことを確かめます。手段は3つあり、目的で選びます。

### Clientで呼ぶ：in-memory接続とプロトコル版

```
import asyncio
from fastmcp import Client
from server import mcp

async def main():
    async with Client(mcp) as client:
        tools = await client.list_tools()
        print([t.name for t in tools])           # ['add']
        result = await client.call_tool("add", {"a": 2, "b": 3})
        print(result.data)                       # 5
        print(client.protocol_version)           # 2026-07-28

asyncio.run(main())
```

サーバーのインスタンスを`Client`へ直接渡すと、ネットワークもサブプロセスも使わずに同じプロセス内でつながります。交渉されたプロトコル版は`2026-07-28`で、`Client(mcp, mode="legacy")`にすると`2025-11-25`でつながりました。4系で変わった点が2つあります。`Client("server.py")`のように文字列でスクリプトを渡すと「FastMCP 5で削除予定」の警告が出るため、`Client(Path("server.py"))`と書きます。ツール定義の`inputSchema`属性も非推奨になり、`input_schema`で読むよう警告されます。

### CLIで呼ぶ：fastmcp list・call・inspect

```
fastmcp list server.py               # ツール一覧と引数の型
fastmcp call server.py add a=2 b=3   # {"result": 5}
fastmcp inspect server.py            # ツール・プロンプト・リソースの数と版
```

コードを書かずに確かめるならCLIが速い方法です。`fastmcp call`は`a=2 b=3`の形でも`'{"a":2,"b":3}'`のJSONでも引数を渡せました。注意点として、`fastmcp list`と`call`は内部でもう一度`fastmcp run`を起動します。そのため、仮想環境を有効にせず`.venv/bin/fastmcp list server.py`のようにフルパスで実行すると、「Client failed to connect: \[Errno 2\] No such file or directory: ‘fastmcp’」で失敗しました。`source .venv/bin/activate`か`uv run`経由で実行すれば通ります。

### pytestによるツール呼び出しと一覧取得のテスト

```
# test_server.py として server.py と同じディレクトリに保存
# pytest と pytest-asyncio をインストールしてから実行:
# uv run pytest -o asyncio_mode=auto test_server.py
import pytest
from fastmcp import Client
from server import mcp

@pytest.fixture
async def client():
    async with Client(mcp) as c:
        yield c

async def test_add(client):
    result = await client.call_tool("add", {"a": 2, "b": 3})
    assert result.data == 5

async def test_tool_listed(client):
    tools = await client.list_tools()
    assert [t.name for t in tools] == ["add"]
```

[公式のテストガイド](https://gofastmcp.com/servers/testing)どおり`pytest-asyncio`を入れ、`asyncio_mode = "auto"`にすると、上の2本は「2 passed in 2.21s」で通りました。in-memory接続なのでポートの競合もなく、CIにそのまま載せられます。

## Claude Code・Claude Desktop・Cursorへの接続手順

手元で動いたサーバーをエージェントに使わせるには、ホスト側に登録します。FastMCPには登録用の`fastmcp install`があり、4.1.0では`claude-code`・`claude-desktop`・`cursor`・`gemini-cli`・`goose`・`mcp-json`・`stdio`を選べます。

```
# Claude Code に登録（内部で claude mcp add を使う）
fastmcp install claude-code server.py --env API_KEY=xxx

# 手動で登録する場合（公式ドキュメントの例と同じ形）
claude mcp add my-server -- uv run --with fastmcp fastmcp run server.py

# HTTP で公開しているサーバーを登録する
claude mcp add --transport http my-server http://127.0.0.1:8000/mcp

# Claude Desktop・Cursor
fastmcp install claude-desktop server.py
fastmcp install cursor server.py
```

`fastmcp install mcp-json server.py`は、MCPサーバーの起動設定JSONを出力します。貼り付け先と設定形式は、利用するホストの仕様に合わせてください。手元では`"command": "uv"`、`"args": ["run", "--with", "fastmcp", "fastmcp", "run", "（server.pyの絶対パス）"]`が出ました。uvが依存を用意してから起動する形なので、ホスト側の環境にFastMCPを入れておく必要はありません。HTTPの登録例はClaude Code 2.1.299の`claude mcp add --help`に載っている書式です。Claude Desktopの導入と設定ファイルの場所は[Claude Desktopとは？できること・料金・インストール・MCP連携を解説【2026年】](/tech/details/7910/)で扱っています。

## FastAPI・OpenAPIからMCPサーバーを自動生成する手順

既存のREST APIをMCP化できる点は、公式SDKに無いFastMCPの機能です。稼働中のFastAPIアプリやOpenAPI仕様から、エンドポイントをツールとして公開できます。以下のFastAPI例には、追加で`uv add fastapi uvicorn`または`pip install fastapi uvicorn`を実行してください。

### FastAPIアプリをMCP化する：FastMCP.from\_fastapi()

```
from fastapi import FastAPI
from fastmcp import FastMCP

app = FastAPI()

@app.get("/items/{item_id}")
def get_item(item_id: int):
    return {"id": item_id}

@app.post("/items")
def create_item(name: str):
    return {"name": name}

mcp = FastMCP.from_fastapi(app=app)

if __name__ == "__main__":
    mcp.run()
```

4.1.0で変換すると、ツール名は`get_item_items`と`create_item_items_post`になり、POSTのエンドポイントも既定でツールとして公開されました。つまり、更新系のAPIもLLMが呼べる状態になります。読み取りだけを渡したいなら、`route_maps`で除外するか、MCP用に読み取り専用のエンドポイントだけを持つアプリを分けます。ツール名はoperationIdの付け方で変わるので、公開前に`fastmcp list`で確かめてください。FastAPIの基礎は[FastAPIとは｜最短で動かす手順とasync/defの使い分け【2026年版】](/tech/details/3859/)、構成の設計は[FastAPIのベストプラクティス｜ディレクトリ構成・SQLAlchemy 2.1の設計・テストを実測で解説](/tech/details/4347/)で扱っています。

### 既存FastAPIにMCPを同居させる：http\_app()とlifespan

```
from fastapi import FastAPI
from fastmcp import FastMCP

mcp = FastMCP("Orders")

@mcp.tool
def order_status(order_id: int) -> str:
    """注文IDから配送状況を返す"""
    return "shipped"

mcp_app = mcp.http_app(path="/")
app = FastAPI(lifespan=mcp_app.lifespan)
app.mount("/mcp", mcp_app)
# 起動: uvicorn main:app --port 8000
```

FastAPIはそのまま残し、同じプロセスの`/mcp`にMCPサーバーを載せる構成です。uvicornで起動し、`Client("http://127.0.0.1:8000/mcp/")`から`order_status`を呼ぶと「shipped」が返り、プロトコル版は`2026-07-28`でした。`lifespan`をFastAPIへ渡し忘れると、MCP側のセッション管理が初期化されません。既存のlifespanがある場合は`fastmcp.utilities.lifespan`の`combine_lifespans`で束ねます。`app.mount("/mcp", ...)`のときに`http_app(path="/")`にしておくと、パスが`/mcp/mcp`と二重になりません。

### OpenAPI仕様からMCP化する：from\_openapi()とhttpx2

```
import json
import httpx2
from fastmcp import FastMCP

with open("openapi.json", encoding="utf-8") as f:
    spec = json.load(f)

client = httpx2.AsyncClient(base_url="https://api.example.com")
mcp = FastMCP.from_openapi(openapi_spec=spec, client=client, name="My API Server")
```

FastAPI以外のフレームワークで作ったAPIでも、OpenAPI仕様があれば変換できます。4系ではHTTPクライアントが`httpx`から`httpx2`に変わりました。4.1.0ではOpenAPIのパスパラメータに単独の`.`や`..`のセグメントを含む値を拒否する修正も入っています。OpenAPI仕様の出し方は[FastAPIのSwagger UI（/docs）の使い方｜表示・設定・本番で隠す手順【2026年版】](/tech/details/2246/)が参考になります。

## 認証の設定：JWTVerifierでHTTP公開のサーバーを保護する

認証はHTTPで公開するときに必要になります。stdioで手元のホストから起動する場合は使いません。JWTを検証する`JWTVerifier`に、発行者の公開鍵の取得先（JWKS）、issuer、audienceを渡します。

```
from fastmcp import FastMCP
from fastmcp.server.auth.providers.jwt import JWTVerifier

verifier = JWTVerifier(
    jwks_uri="https://auth.example.com/.well-known/jwks.json",
    issuer="https://auth.example.com",
    audience="mcp-production-api",
    required_scopes=["read"],
)
mcp = FastMCP(name="Protected API", auth=verifier)

if __name__ == "__main__":
    mcp.run(transport="http", host="127.0.0.1", port=8000)
```

手元では`RSAKeyPair.generate()`でテスト用の鍵とトークンを作り、`public_key`で同じ設定を組んで試しました。結果は次のとおりです。

| 送ったもの             | 応答                                           |
| ----------------- | -------------------------------------------- |
| トークンなし            | 401（`WWW-Authenticate: Bearer scope="read"`） |
| audienceが違うトークン   | 401（`error="invalid_token"`）                 |
| scopeにreadが無いトークン | 401（`error="invalid_token"`）                 |
| 正しいトークン           | ツールの結果が返る                                    |

スコープ不足も403ではなく401の`invalid_token`で返るため、ログだけでは「トークンが壊れている」のか「権限が足りない」のか区別できません。調べるときはトークンの`aud`と`scope`を先に確かめます。クライアントからは`Client("http://127.0.0.1:8000/mcp", auth="トークン文字列")`と渡せば、FastMCPが`Authorization: Bearer`ヘッダーを付けます。ヘッダーの仕様は[Bearer Token（ベアラートークン）とは？読み方・Authorization: Bearerの書き方とJWTとの違い](/tech/details/4150/)で説明しています。

固定のトークンで試す`StaticTokenVerifier`もありますが、トークンを平文で持つため公式は開発・テスト専用としています。外部のIDプロバイダーとOAuth 2.1でつなぐ場合は`OAuthProxy`を使い、ここではクライアント登録の新方式であるCIMDが既定で有効です。CIMDの仕組みは[CIMD（Client ID Metadata Documents）とは？MCPでDCRに代わるOAuthクライアント登録の仕組みと実装【2026年10月】](/tech/details/10011/)で扱っています。

## 例外の扱い：ToolErrorの使い分けとmask\_error\_detailsによる情報の非表示

ツールの中で例外が起きたとき、FastMCPの既定の挙動は、メッセージをそのままクライアントへ返すことです。検証用に`raise ValueError("secret db password=xyz")`だけを実行するツール`boom`を作って呼ぶと、クライアントには「Error calling tool ‘boom’: secret db password=xyz」が届きました。接続文字列や内部のパスを含む例外がLLMの文脈に入り、会話ログにも残ります。

```
from fastmcp import FastMCP
from fastmcp.exceptions import ToolError

mcp = FastMCP("Orders", mask_error_details=True)

@mcp.tool
def find_order(order_id: int) -> str:
    """注文を検索する"""
    if order_id <= 0:
        raise ToolError("注文IDが見つかりません")  # この文言は利用者へ届く
    raise ValueError("db timeout at 10.0.0.5")      # この文言は隠される
```

同じ`boom`を`mask_error_details=True`のサーバーで呼ぶと、返るのは「Error calling tool ‘boom’」だけになり、中身は届きませんでした。`ToolError`で投げたメッセージは、設定に関係なくそのまま届きます。本番では`mask_error_details=True`にし、LLMに伝えたい理由（「注文IDが見つかりません」など）だけを`ToolError`で返すのが安全です。

## 依存の注入とContext：Depends()とCurrentContext()の書き方

FastAPIと同じ考え方の`Depends()`で、設定値やDB接続をツールへ渡せます。リクエスト単位の機能を持つ`Context`は`CurrentContext()`で受け取ります。

```
from fastmcp import Context, FastMCP
from fastmcp.dependencies import CurrentContext, Depends

mcp = FastMCP("Deps")

def get_config() -> dict:
    return {"region": "ap-northeast-1"}

@mcp.tool
async def show_region(
    config: dict = Depends(get_config),
    ctx: Context = CurrentContext(),
) -> str:
    """設定からリージョン名を返す"""
    return config["region"]
```

このツールの入力スキーマは`properties`が空になり、注入する引数はLLMから見えませんでした。呼び出しの結果は「ap-northeast-1」です。4系で使えなくなったものもあります。クライアント側のLLMに生成を頼む`ctx.sample()`と`ctx.list_roots()`は削除され、`ctx.elicit()`は2026-07-28版の接続では使えません。`ctx.info()`によるログ送信は動きますが、「The logging capability is deprecated as of 2026-07-28 (SEP-2577)」の非推奨警告が出ました。

## トランスポートと公開先：stdio・Streamable HTTP・Horizonの選び方

| 方式              | 起動の書き方                      | 向く場面                   |
| --------------- | --------------------------- | ---------------------- |
| stdio（既定）       | `mcp.run()`                 | 手元のClaude Code・Desktop |
| Streamable HTTP | `mcp.run(transport="http")` | 複数人・リモートからの利用          |
| in-memory       | `Client(mcp)`               | テスト・開発                 |

判断は単純で、自分のPCのホストから使うだけならstdio、ほかの人やサーバーから呼ばせるならStreamable HTTPです。HTTPの既定のエンドポイントは`/mcp`で、CLIなら`fastmcp run server.py --transport http --port 8000`で起動できます。SSEは古いクライアント向けに残っているだけなので、新しく選ぶ理由はありません。仕様の違いは[Streamable HTTPとは？MCPのトランスポートとSSEの違い、2026-07-28仕様の変更点](/tech/details/6580/)で扱っています。

公開先にはFastMCPの開発元PrefectのPrefect Horizonもあり、[公式のデプロイガイド](https://gofastmcp.com/deployment/prefect-horizon)によれば、GitHubのリポジトリを選ぶだけでURLが発行され、個人プロジェクトは無料です。起動時のバナーにも「Deploy free」という文言とHorizonのURLが表示されます。自社のクラウドで動かすならDockerなどでHTTPサーバーとして立て、前段で認証を掛けます。Python以外の基盤で公開する例は[CloudflareでMCPサーバーを構築・公開する方法｜Workersリモートデプロイと認証・ポータル](/tech/details/6032/)にあります。

## プロキシとサーバー合成：create\_proxy()とmount()による複数サーバーの統合

```
from fastmcp import FastMCP
from fastmcp.server import create_proxy

weather = FastMCP("Weather")

@weather.tool
def get_forecast(city: str) -> str:
    """都市名から天気予報を返す"""
    return f"{city}: 晴れ"

main = FastMCP("Gateway")
main.mount(weather, namespace="weather")                         # weather_get_forecast
main.mount(create_proxy("http://127.0.0.1:8000/mcp/"), namespace="orders")
```

`mount()`は別のサーバーを名前空間付きで取り込み、ツール名は`weather_get_forecast`になりました。`create_proxy()`はFastMCP製でないサーバーやリモートのサーバーも取り込めます。前章のFastAPI同居サーバーをプロキシして`namespace="orders"`で載せると、`orders_order_status`として呼べました。リモートのHTTPサーバーをstdioで再公開できるので、HTTPに対応していないホストからリモートのツールを使う橋渡しにもなります。3系の書き方は4系で通りません。`mount(prefix=...)`は「unexpected keyword argument ‘prefix’」の`TypeError`になり、`as_proxy()`と`import_server()`は削除されています。

## FastMCPと公式MCP Python SDK・TypeScript版の違いと選び方

### 公式SDK同梱のFastMCP 1.0と独立版の関係

FastMCP 1.0は2024年に公式MCP Python SDKへ取り込まれ、SDKの1系では`from mcp.server.fastmcp import FastMCP`で使えました。SDKの2系（2026-07-28公開の2.0.0以降）では、この高レベルAPIが`MCPServer`に改名され、旧importは`ModuleNotFoundError`になります。公式SDK側の書き換えは[MCP Python SDK v2 移行：FastMCPからMCPServerへの書き換え手順と据え置き判断](/tech/details/18273/)で扱っています。一方、`pip install fastmcp`で入る独立版は2.0以降も開発が続く別の系統で、FastAPI・OpenAPIからの生成、プロキシ、サーバー合成、クライアント、Appsを持ちます。サーバー1本を最小構成で出すだけなら公式SDKで足ります。その手順は[MCPサーバーの作り方とAIエージェントへの接続手順｜Python SDK 2.3でツール定義・認可を実装](/tech/details/15365/)にまとめています。既存APIのMCP化や複数サーバーの統合まで進めるなら、独立版を選びます。

### TypeScript版 punkpeye/fastmcp との違い

FastMCPという名前のTypeScript実装[punkpeye/fastmcp](https://github.com/punkpeye/fastmcp)もあり、npmの最新は2026年10月14日（UTC）公開のv4.22.10、GitHubのスター表示は3.3kです。名前は同じですが別の開発者による別リポジトリで、APIに互換性はありません。選定ではランタイムに加えて対応するMCP仕様を確認します。punkpeye/fastmcpは2025-11-25以前の仕様に対応し、2026-07-28仕様には未対応です。READMEは2026-07-28仕様向けの別フレームワークとしてViteMCPを案内しています。Node.jsで新仕様に対応させたいなら、2026-07-28仕様を実装した公式TypeScript SDKの2系（`@modelcontextprotocol/server`）も候補です。GoならMCPの公式Go SDKが出発点になり、[MCP Go SDKの使い方｜v1.8.0でサーバーを作る手順とmcp-goとの違い](/tech/details/8272/)で扱っています。

### FastMCPを採用すべきでない場面

自社アプリの中で関数を呼ぶだけで、外部のAIエージェントに機能を渡す必要がないなら、MCP自体が要りません。普通のライブラリ呼び出しで足ります。プロトコルの挙動を細部まで自分で制御したい場合も、抽象化の厚いFastMCPより公式SDKが向きます。もう1つは更新の速さです。4.0.0から4.1.0までの約5週間にパッチ版が11本出ており、版を固定せずに運用すると挙動が変わります。`fastmcp==4.1.0`のように固定し、上げる前にpytestを回す運用が組めないチームには勧めません。社内システムを生成AIから安全に呼べるようにしたいものの設計・認証・運用まで手が回らない場合は、一創の[AIエージェント開発](/service/ai/agent/)でMCPサーバーを含む構成をご相談いただけます。

## よくある質問：FastMCPの使い方と最新版

### FastMCPとは何ですか？

MCPのサーバーとクライアントをPythonで作るためのフレームワークです。関数に`@mcp.tool`を付けるとAIエージェントから呼べるツールになり、スキーマ生成・入力検証・トランスポート・認証はFastMCPが受け持ちます。リポジトリはPrefectHQ/fastmcpで、APIモックを生成するツールではありません。

### FastMCPと公式MCP Python SDKは何が違いますか？

公式SDKに取り込まれたのはFastMCP 1.0で、SDK 2系では`MCPServer`に改名されています。`pip install fastmcp`で入るのは独立して開発が続く系統で、FastAPI・OpenAPIからの自動生成、プロキシ、サーバー合成、クライアント、Appsを持ちます。最小構成のサーバーなら公式SDK、既存APIのMCP化や複数サーバーの統合ならFastMCPが向きます。

### 既存のFastAPIアプリをMCP化できますか？

できます。`FastMCP.from_fastapi(app=app)`に渡すと、各エンドポイントがツールになります。ただしPOSTなど更新系も既定でツールになるため、LLMに呼ばせたくないものは`route_maps`で除外してください。FastAPIを残して同じプロセスに載せるなら、`mcp.http_app()`をマウントし、`lifespan`をFastAPIへ渡します。

### FastMCPでBearer Token認証はどう設定しますか？

サーバーは`JWTVerifier`にJWKSのURI・issuer・audienceを渡し、`FastMCP(auth=verifier)`に設定します。クライアントは`Client(url, auth="トークン")`で送ると`Authorization: Bearer`が付きます。4.1.0ではトークンなし・audience違い・スコープ不足のいずれも401で返りました。認証はHTTPで公開するときだけ効き、stdioでは使いません。

### FastMCPの最新バージョンとPythonの要件は？

2026年10月17日時点の最新は4.1.0（2026-10-08公開）で、3系も3.4.9（2026-10-16）まで保守版が出ています。Pythonは3.10以上が必要です。3系から上げるときは`ctx.sample()`・`as_proxy()`・`mount(prefix=...)`を使っていないかを先に検索してください。本番では`fastmcp==4.1.0`のように版を固定します。

## 関連記事

- [MCP（Model Context Protocol）とは？AIと外部ツールをつなぐ標準規格の仕組みをわかりやすく解説](/tech/details/5736/)
- [FastMCP 4とは？sessionless対応と廃止APIから読む3系からの移行判断](/tech/details/15907/)
- [MCPサーバーの作り方とAIエージェントへの接続手順｜Python SDK 2.3でツール定義・認可を実装](/tech/details/15365/)
- [MCP仕様2026-07-28版とは：ステートレス化の変更点と2025-11-25版からの移行手順](/tech/details/18245/)
- [Streamable HTTPとは？MCPのトランスポートとSSEの違い、2026-07-28仕様の変更点](/tech/details/6580/)

---

出典: [FastMCPとは？PythonでMCPサーバーを作る手順とFastMCP 4.1の使い方【2026年10月】](<https://www.issoh.co.jp/tech/details/6507/>)（株式会社一創）
