MCPサーバーの作り方:Pythonで自作する手順をステップごとに解説
MCPサーバーの作り方。Python SDK 2.0 でツールを書き、Inspector で試し、Claude Code と Claude Desktop につなぎます。
この記事の他の言語版:العربيةDeutschEnglishEspañolFrançaisItalianoPolski简体中文
この記事の内容
MCPサーバーの作り方は、Python ならファイル1つと公式の MCP Python SDK で足ります。型とドックストリングのついた普通の関数を書き、デコレーター @mcp.tool() を付けると、SDK がそれを Claude、ChatGPT、Cursor から呼び出せるツールに変えてくれます。ドキュメントのサンプルにあるサーバーは、全体で十数行です。
この記事ではサーバーをゼロから書き、MCP Inspector でテストして、Claude Code と Claude Desktop につなぎます。コマンドとコードは公式チュートリアル「Build an MCP server」、SDK の README、Claude Code のドキュメントからのものです。
必要なものは何か
MCP とは何か、つまりホスト、クライアント、サーバー、ツールについてはもう知っている前提で進めます(まだなら MCPとは から始めてください)。用意するものは次のとおりです。
- Python 3.11 以上(現行 SDK の README が求めるバージョン)
- パッケージマネージャー uv(公式チュートリアルが使っているもの)
- Node.js 22.19.0 以上(MCP Inspector でサーバーをテストする場合)
- 全体を確認するための MCP ホスト。たとえば Claude Code や Claude Desktop
最初に大事な注意が1つあります。SDK のバージョン 2.0 で、メインのクラス名が変わりました。v2 の変更点の説明によると、以前の from mcp.server.fastmcp import FastMCP は、今は from mcp.server import MCPServer です。ネット上の記事の多くはまだ古い書き方のままですが、公式チュートリアルは SDK 2.0.0 以上を必要とします。
ステップ1:プロジェクトを準備するには
まず uv をインストールします(macOS と Linux)。
curl -LsSf https://astral.sh/uv/install.sh | sh
Windows では PowerShell でこう実行します。
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
インストールが終わったら、uv コマンドが使えるようにターミナルを再起動します。続いてプロジェクトを作り、SDK をインストールします。
uv init my-server
cd my-server
uv venv
source .venv/bin/activate
uv add "mcp[cli]"
touch server.py
[cli] を付けると mcp コマンド(mcp dev、mcp run、mcp install)も入ります。テストで使うコマンドです。(Windows では .venv\Scripts\activate で環境を有効にします)
ステップ2:最初のツールを持つMCPサーバーの作り方
server.py に SDK の README のサンプルを書き、公式チュートリアルと同じように、末尾にサーバーの起動処理を足します。
from mcp.server import MCPServer
mcp = MCPServer("Demo")
@mcp.tool()
def add(a: int, b: int) -> int:
"""Add two numbers."""
return a + b
@mcp.resource("greeting://{name}")
def greeting(name: str) -> str:
"""Greet someone by name."""
return f"Hello, {name}!"
if __name__ == "__main__":
mcp.run(transport="stdio")
これで MCP サーバーとして完成しています。ツールが1つ(add)と、アドレスのテンプレートを持つリソースが1つ(greeting://{name})です。面白いことに、JSON Schema は一切書きません。README によると、シグネチャの a: int, b: int がそのままスキーマになり、ドックストリングはモデルが読むツールの説明になります。リクエストのパース、バリデーション、プロトコルの処理は SDK が引き受けます。
だからドックストリングは丁寧に書きましょう。モデルは名前と説明を見てツールを選ぶので、「Add two numbers.」は最低限です。実際のツールでは、公式の天気予報のサンプルのように引数も説明します。
@mcp.tool()
async def get_forecast(latitude: float, longitude: float) -> str:
"""Get weather forecast for a location.
Args:
latitude: Latitude of the location
longitude: Longitude of the location
"""
(このサンプルは米国の気象機関 NWS の API を使っているので、動くのは米国内の地点だけです)
ステップ3:なぜ print() を使ってはいけないのか
最初のサーバーでいちばん多い失敗がこれです。ローカルサーバーはホストと標準入出力(stdio)でやりとりし、メッセージの形式は JSON-RPC です。ドキュメントははっきり警告しています。stdout に書き込むと JSON-RPC メッセージが壊れ、サーバーが止まります。そして print() の出力先は、デフォルトでその stdout です。
代わりに、stderr に書き出す logging モジュールを使います。
import logging
logger = logging.getLogger(__name__)
logger.info("Processing request") # stderr に出力される
HTTP サーバーではこの問題は起きません。stdout のログが HTTP レスポンスに混ざらないからです。
ステップ4:MCP Inspector でサーバーをテストするには
MCP Inspector は、サーバーをテストするための公式ツールです。SDK からはコマンド1つで起動できます。
uv run mcp dev server.py
ブラウザが開き、Inspector が表示されます。README によると、add を引数 a=1、b=2 で呼び出すと 3 が返ります。同じ画面でツールとリソースの一覧、それに生の JSON-RPC メッセージも見られるので、うまく動かないときの手がかりになります。
Inspector にはターミナル版(--tui)とスクリプト向けのモード(--cli)もあります。後者はたとえばツールの一覧を出力して終了するので、CI に向いています。
npx @modelcontextprotocol/inspector --cli uv run server.py --method tools/list
(Node.js のバージョンは node --version で確認してください。Inspector には 22.19.0 以上が必要です)
ステップ5:サーバーを Claude Code につなぐには
ローカルサーバーは stdio タイプのサーバーとして追加します。-- より後ろはすべて、Claude Code が実行するコマンドです。
claude mcp add --transport stdio demo -- uv --directory /FULL/PATH/my-server run server.py
パスは絶対パスでなければなりません(プロジェクトのディレクトリで pwd を実行すれば確認できます)。接続の状態は claude mcp get demo で、Claude Code のセッション中なら /mcp で見られます。これで、たとえば「add ツールで 1234 と 5678 を足して」と頼み、呼び出しを承認できます。
Claude Code のドキュメントから、すぐに役立つことを2つ挙げておきます。
- サーバーの起動待ち時間は環境変数
MCP_TIMEOUTで変えられます。たとえばMCP_TIMEOUT=10000 claudeなら、サーバーに10秒の猶予を与えます - Claude Code はツールの結果が 10,000 トークンを超えると警告を出し、デフォルトでは 25,000 トークンで切り詰めます(上限は環境変数
MAX_MCP_OUTPUT_TOKENSで変更可能)。ツールがデータベースを丸ごと返すような作りは避けましょう
ステップ6:サーバーを Claude Desktop に追加するには
Claude Desktop では、ローカルサーバーを設定ファイル claude_desktop_config.json に書き足します。場所は macOS なら ~/Library/Application Support/Claude/、Linux なら ~/.config/Claude/、Windows なら %AppData%\Claude\ です(ファイルがなければ作ります)。書く内容はこうです。
{
"mcpServers": {
"demo": {
"command": "uv",
"args": [
"--directory",
"/FULL/PATH/my-server",
"run",
"server.py"
]
}
}
}
そのあとアプリを完全に終了し(macOS では Cmd+Q。ウィンドウを閉じるだけでは足りません)、もう一度起動します。サーバーは、プラスのアイコンの下にある「Connectors」メニューに出てくるはずです。出てこない場合、ドキュメントは JSON の構文とパスが絶対パスになっているかを確認し、command に uv のフルパス(which uv で分かります)を書くよう勧めています。ログは ~/Library/Logs/Claude(macOS)または ~/.config/Claude/logs/(Linux)の mcp.log と mcp-server-NAME.log にあります。
ステップ7:MCP サーバーを HTTP で動かすには
stdio サーバーは自分のパソコンの中でしか動きません。リモートサーバーとして公開するには、Streamable HTTP で起動します。SDK の README によると、本番環境にデプロイするのはこのトランスポートです。
uv run mcp run server.py --transport streamable-http
サーバーは http://localhost:8000/mcp で待ち受けるようになり、Claude Code にはほかのリモートサーバーと同じ方法で追加します。
claude mcp add --transport http demo-http http://localhost:8000/mcp
このサーバーをブラウザ版の Claude アプリでいわゆる「custom connector」として使うには、インターネットから到達できる必要があります。Claude は Anthropic のクラウドから接続してくるからです。そうなるとログインの仕組みも欲しくなります。MCP のドキュメントには、OAuth 2.1 によるサーバーの認可が説明されています。
気をつけるべきこと
1つ目は、ツールに何を許すかです。MCP サーバーは、モデルが自分のパソコン上で実際に行動する力を与えます。ツールはできるだけ狭く作りましょう。「任意のコマンドを実行する」より「このディレクトリのファイルを読む」のほうが安全です。
2つ目は、外から入ってくるデータです。ツールがインターネットやメールからコンテンツを取ってくるなら、プロンプトインジェクション、つまりモデルに向けた隠れた指示が一緒に入り込むことがあります。これについては AIエージェントのセキュリティ でもっと詳しく書きました。
3つ目は、シークレットです。API キーはコードに書かず、環境変数(Claude Code なら --env)で渡しましょう。ドキュメントによると、Inspector はトークンを OS のキーチェーンに保存しますが、キーチェーンがない環境(たとえばコンテナ)では暗号化されていないファイル ~/.mcp-inspector/secrets.json に保存します。
こうして作ったサーバーは、自作のエージェントにもつなげます。そのやり方は PythonでのAIエージェントの作り方 で紹介しています。
FAQ
いちばん簡単なMCPサーバーの作り方は?
SDK の README にある最小のサーバーは十数行です。MCPServer オブジェクト、@mcp.tool() デコレーターを付けた関数が1つ、そして mcp.run()。残りの、引数のスキーマとプロトコルの処理は SDK がやってくれます。
FastMCP とは何ですか?
MCP Python SDK のメインのサーバークラスの旧名です。バージョン 2.0 で MCPServer に変わり、インポートは from mcp.server import MCPServer になりました。
MCP サーバーは Python 以外の言語でも書けますか?
はい。公式チュートリアルには TypeScript、Java、Kotlin、C#、Ruby、Rust、Go などの版があります。
MCP サーバーは Claude でしか動きませんか?
いいえ。MCP はオープンな標準なので、同じサーバーがプロトコルに対応したどのホストでも動きます。たとえば ChatGPT、Visual Studio Code、Cursor です。