Model Context Protocol(MCP)は、LLMアプリケーションと外部データソースやツールを接続するためのオープンな規格です。本記事では、Pythonを用いてMCPサーバーを最小構成で構築する方法と、実際の業務環境で運用・拡張する際に必要となる設計ポイントを解説します。
※MCPの仕様や関連ライブラリは更新される可能性があります。実装時には必ず最新の公式ドキュメントをご確認ください。
この記事で分かること
-
mcpSDKを使用したPythonによるMCPサーバーの最小実装 - ツール(Tools)およびリソース(Resources)の定義方法
- 実務でのエラーハンドリング、セキュリティ、ログ設計の注意点
- 本番運用に向けた設計チェックリスト
前提条件
- Python 3.10 以上がインストールされていること
- FastMCP(
mcpライブラリに含まれる高レベルAPI)を使用した記述を理解すること
MCPサーバーの最小構成実装
まず、必要なパッケージをインストールします。
pip install mcp
以下は、標準入力/出力(stdio)経由でクライアントと通信する最小限のMCPサーバーの実装例です。
# server.py
from mcp.server.fastmcp import FastMCP
# MCPサーバーのインスタンス化
mcp = FastMCP("MinimalServer")
# ツール(LLMが呼び出せる関数)の定義
@mcp.tool()
def add_numbers(a: int, b: int) -> int:
"""2つの数値を加算します。"""
return a + b
# リソース(LLMが参照できるデータ)の定義
@mcp.resource("config://version")
def get_version() -> str:
"""現在のバージョン情報を返します。"""
return "1.0.0"
if __name__ == "__main__":
# stdioトランスポートでサーバーを実行
mcp.run(transport="stdio")
動作確認コマンド
mcp CLI(開発用ツール)を利用して動作を確認できます。
# サーバーの起動確認(開発モード)
npx @modelcontextprotocol/inspector python server.py
実務運用で必要となる設計ポイント
最小構成のコードから実務利用へスケールさせる場合、以下の設計考慮が必要となります。
1. 入力バリデーションと型安全性の確保
LLMからの引数は想定外の型やフォーマットで渡される可能性があります。Pydanticなどを併用し、ツール関数内での事前チェックを厳格に行うことが推奨されます。
from pydantic import BaseModel, Field
class UserQuery(BaseModel):
user_id: int = Field(..., description="ユーザーID")
limit: int = Field(default=10, ge=1, le=100, description="取得件数上限")
@mcp.tool()
def fetch_user_data(query: UserQuery) -> dict:
"""指定されたユーザーの情報を取得します(独自実装例)。"""
# 処理ロジック
return {"status": "success", "user_id": query.user_id}
2. エラーハンドリングとログ分離
stdio トランスポートを使用する場合、sys.stdout はMCPプロトコルのJSON-RPCメッセージ通信に使用されます。そのため、通常の print() 文などで標準出力にログを出力すると通信が破損します。
-
ログ出力: 必ず標準エラー出力(
sys.stderr)またはファイル出力にリダイレクトするロガー(loggingモジュール等)を使用してください。 - エラーの返却: ツール内部の例外は適切にキャッチし、LLMが次の行動を判断しやすいエラーメッセージとして返却します。
import logging
import sys
# 標準エラー出力にログを出力する設定
logging.basicConfig(
stream=sys.stderr,
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
@mcp.tool()
def safe_divide(a: float, b: float) -> str:
"""安全な除算を行います。"""
if b == 0:
logging.warning("ゼロ除算が試行されました。")
return "エラー: ゼロで割ることはできません。"
return str(a / b)
3. 機密情報と認証情報の取り扱い
- APIキーやデータベース接続文字列などの認証情報は、コード内にハードコーディングせず環境変数から取得します。
- 個人情報(PII)や機密データをログやレスポンスに含めないようマスク処理を挟みます。
導入前チェックリスト
本番環境やチーム開発でMCPサーバーをデプロイする前に、以下の項目を確認してください。
| チェック項目 | 説明 | 確認 |
|---|---|---|
| ログ出力先の分離 |
stdout への直接出力を行わず、stderr やファイルへ出力しているか |
[ ] |
| 入力値検証 | ツールの引数に適切な型定義・範囲制限が適用されているか | [ ] |
| 機密情報の管理 | 環境変数経由で認証情報を取り扱っているか | [ ] |
| トラブルシューティング | MCP Inspector等で独立したテストを実施したか | [ ] |
| バージョン固定 |
mcp ライブラリのバージョンを指定・固定しているか |
[ ] |
注意点とよくある失敗
-
標準出力の汚染: デバッグ目的で入れた
print()によりJSON parsing errorが発生し、クライアントと通信不能になるケースが頻発します。 - プロンプトコンテキストの過大化: リソースで返却するテキストデータが大きすぎると、LLMのコンテキストウィンドウを圧迫します。必要なデータのみをスライスして返却する設計を行ってください。
まとめ
Pythonの mcp SDK(FastMCP)を活用することで、最小構成のMCPサーバーは短いコードで構築可能です。しかし実務運用においては、通信プロトコルの特性を踏まえたログ管理や厳格な型検証が不可欠です。本記事のチェックリストを活用し、安全でメンテナンス性の高いMCPサーバーを構築してください。