Model Context Protocol(MCP)は、AIアシスタントが外部ツールやデータソースと連携する方法に革命をもたらします。MCPは、AIアプリケーションのためのユニバーサルなUSB-Cポートのようなものと考えてください。Claude Codeを、想像できるほぼすべてのデータソース、API、ツールに接続するための標準化された方法を提供します。この包括的なガイドでは、独自のMCPサーバーをゼロから構築する方法を順を追って説明し、Claude Codeが組み込み機能を超えてその能力を拡張するカスタム機能にアクセスできるようにします。
データベース、API、ファイルシステムを統合したい場合でも、まったく新しいカスタムツールを作成したい場合でも、MCPは無限の拡張性の基盤を提供します。このチュートリアルの終わりまでに、動作するMCPサーバーを手に入れ、あらゆるユースケースに合わせてそれを拡張する方法を理解できるでしょう。
最高の生産性で開発チームが連携するための統合されたオールインワンプラットフォームをお探しですか?
Apidogは、あなたのすべての要求に応え、Postmanをはるかに手頃な価格で置き換えます!
We’re thrilled to share that MCP support is coming soon to Apidog! 🚀
— Apidog (@ApidogHQ) March 19, 2025
Apidog MCP Server lets you feed API docs directly to Agentic AI, supercharging your vibe coding experience! Whether you're using Cursor, Cline, or Windsurf - it'll make your dev process faster and smoother.… pic.twitter.com/ew8U38mU0K
MCPサーバーとは何か、なぜ話題になっているのか
MCPの何が違うのか
MCP(Model Context Protocol)は、Anthropicが開発したオープンプロトコルで、AIモデルが標準化されたインターフェースを通じて外部サーバーと通信できるようにします。特定のエンドポイントをハードコーディングする従来のAPI統合とは異なり、MCPはAIアシスタントが外部ツールを動的に発見、理解、利用するための構造化された方法を提供します。
MCPの素晴らしさは、その発見可能性にあります。Claude CodeがあなたのMCPサーバーに接続すると、利用可能なツール、その使い方、受け入れるパラメータを自動的に学習します。これは、Claude Code自体を更新することなく新しい機能を追加できることを意味します。
MCPアーキテクチャの詳細
このプロトコルは、明確に定義された役割を持つクライアントサーバーアーキテクチャに従います。
- MCPホスト: Claude Code、Claude Desktop、その他のMCPサービスを利用するAIアシスタントなどのアプリケーション
- MCPクライアント: サーバーと1対1の接続を維持し、通信を処理するプロトコルクライアント
- MCPサーバー: 標準化されたプロトコルを通じて特定の機能を提供する軽量プログラム
- トランスポート層: 通信方法(ローカルサーバーの場合はstdio、リモートサーバーの場合はSSE)
通信フローの説明
Claude Codeが外部ツールを使用する必要がある場合、次のことが起こります。
- 発見フェーズ: Claude Codeが利用可能なツールについてあなたのサーバーに問い合わせます
- スキーマ検証: あなたのサーバーはツール定義と入力スキーマで応答します
- ツール選択: Claude Codeはユーザーのリクエストに基づいて適切なツールを選択します
- 実行フェーズ: Claude Codeは検証済みのパラメータでツール呼び出しを送信します
- 結果処理: あなたのサーバーはリクエストを処理し、構造化された結果を返します
このフローにより、タイプセーフティ、適切なエラー処理、およびすべてのMCP統合における一貫した動作が保証されます。
前提条件と環境設定
システム要件分析
MCPサーバーを構築する前に、開発環境を理解し、適切なツールを選択する必要があります。MCPサーバーは複数の言語で構築できますが、PythonとTypeScriptが最も一般的にサポートされており、豊富なツールが提供されています。
Python開発の場合:
- Python 3.8以降 - 最新のasync/awaitサポートと型アノテーションに必要
- pipパッケージマネージャー - 依存関係管理用
- 仮想環境ツール -
venv
またはconda
を使用して依存関係を分離
TypeScript/JavaScript開発の場合:
- Node.js v20以降 - 最新のECMAScript機能と安定性に必要
- npmまたはyarn - パッケージ管理用
- TypeScriptコンパイラ - より良いタイプセーフティのためにTypeScriptを使用する場合
コア依存関係:
- Claude Code CLI: MCPサーバー管理の主要なインターフェース
- JSON-RPC 2.0の知識: 基盤となる通信プロトコルの理解
- 基本的なサーバーアーキテクチャの概念: リクエスト/レスポンスサイクルとエラー処理
ステップバイステップの環境準備
1. Claude Code CLIのインストール
Claude Code CLIは、MCPサーバーを管理するための主要なツールです。どのディレクトリからでもアクセスできるようにグローバルにインストールします。
# Claude Codeをグローバルにインストール
npm install -g @anthropic-ai/claude-code
グローバルインストールが重要な理由: グローバルインストールにより、claude
コマンドがシステム全体で利用可能になり、異なるディレクトリからMCPサーバーを登録する際のパス関連の問題を防ぎます。
2. インストールの確認
Claude Codeが正しくインストールされ、アクセス可能であることを確認します。
# インストールを確認し、バージョンをチェック
claude --version
# 利用可能なコマンドをチェック
claude --help
3. 最初の重要な権限設定
このステップは絶対に不可欠であり、見落とされがちです。
# 権限バイパス付きの初期設定を実行
claude --dangerously-skip-permissions
このコマンドがすること:
- Claude Codeの構成ディレクトリを初期化します
- MCP通信のセキュリティ権限を確立します
- 必要な認証トークンを作成します
- MCPレジストリデータベースをセットアップします
なぜ必要か: このステップがないと、MCPサーバーはClaude Codeとの安全な接続を確立できず、認証失敗や接続タイムアウトが発生します。
セキュリティ上の考慮事項: --dangerously-skip-permissions
フラグは開発環境では安全ですが、通常のセキュリティプロンプトをバイパスします。本番環境では、各権限要求を慎重に確認してください。
重要な構成: MCPスコープの理解
構成スコープが重要な理由
MCPサーバーを構築する際の最も一般的な落とし穴の1つは、不適切な構成スコープ管理です。スコープを理解することは、MCPサーバーがClaude Codeでいつ、どこで利用可能になるかを決定するため、非常に重要です。多くの開発者は、スコープの誤構成に起因する「サーバーが見つかりません」というエラーのデバッグに何時間も費やしています。
Claude Codeは、セキュリティを維持しながら柔軟性を提供するように設計された階層的な構成システムを使用しています。各スコープは特定の目的を果たし、異なるユースケースがあります。
構成スコープ階層の説明
1. プロジェクトスコープ (.mcp.json
) - 最高優先度
場所: プロジェクトルートディレクトリの.mcp.json
ファイル内
目的: その特定のプロジェクトで作業しているときにのみ利用可能であるべきプロジェクト固有のMCPサーバー
ユースケース: プロジェクト固有のデータベース接続、プロジェクト固有のリンター、またはカスタムビルドツール
プロジェクトスコープが適切な場合:
- グローバルであるべきではないプロジェクト固有のツールがある場合
- チームで作業しており、バージョン管理を通じてMCP構成を共有したい場合
- 異なるプロジェクトで同じツールの異なるバージョンが必要な場合
2. ユーザースコープ (-scope user
) - グローバル構成
場所: ユーザーのホームディレクトリ構成
目的: すべてのプロジェクトおよびディレクトリでグローバルに利用可能なMCPサーバー
ユースケース: 天気API、計算機ツール、システムユーティリティなどの汎用ツール
ユーザースコープが通常推奨される理由:
- システム上のどのディレクトリからでも動作します
- プロジェクトディレクトリの変更後も維持されます
- どこでも使用したいユーティリティサーバーに最適です
3. ローカルスコープ (デフォルト) - ディレクトリ固有
場所: 現在の作業ディレクトリのコンテキスト
目的: 短期的な、一時的なMCPサーバーのセットアップ
制限事項: その特定のディレクトリからClaude Codeを実行している場合にのみ動作します
一般的な構成ミス
❌ 間違ったアプローチ (ローカルスコープ - 機能が制限される):
claude mcp add my-server python3 /path/to/server.py
問題点: このサーバーは、登録した正確なディレクトリにいる場合にのみ動作します。
✅ 正しいアプローチ (ユーザースコープ - グローバルアクセス):
claude mcp add --scope user my-server python3 ~/.claude-mcp-servers/my-first-server/server.py
利点: このサーバーは、システム上のどのディレクトリからでも動作します。
戦略的なディレクトリ計画
推奨されるディレクトリ構造
長期的な保守性のために、整理されたディレクトリ構造を作成します。
# 永続的な保存場所を作成
mkdir -p ~/.claude-mcp-servers/
# 機能別に整理
mkdir -p ~/.claude-mcp-servers/apis/
mkdir -p ~/.claude-mcp-servers/utilities/
mkdir -p ~/.claude-mcp-servers/development/
整理された構造の利点
保守性: 後でサーバーを見つけて更新するのが簡単
セキュリティ: 異なる種類のツールの明確な分離
バックアップ: 1つのディレクトリをバックアップするだけで、すべてのMCPサーバーを簡単にバックアップ
共有: チームメンバーとサーバー構成を簡単に共有
スコープのトラブルシューティングガイド
スコープの問題の診断
MCPサーバーが表示されない場合は、次の診断シーケンスに従います。
- 現在のスコープ構成を確認:
claude mcp list
- 競合するプロジェクトスコープを持つディレクトリにいないことを確認:
ls .mcp.json
- 異なるディレクトリからテスト:
cd ~ && claude mcp list
cd /tmp && claude mcp list
スコープの問題の修正
問題: サーバーが1つのディレクトリでのみ動作する
解決策: ローカル構成を削除し、ユーザースコープで再追加
# 問題のあるローカル構成を削除
claude mcp remove my-server
# グローバルユーザースコープで再追加
claude mcp add --scope user my-server python3 ~/.claude-mcp-servers/my-first-server/server.py
最初のMCPサーバーの構築
開発プロセスの理解
MCPサーバーを構築するには、MCPプロトコルとユースケースの特定の要件の両方を理解する必要があります。基本を理解するために基本的な「Hello World」サーバーから始め、その基盤の上に構築を進めます。
開発プロセスは以下のフェーズに従います。
- サーバー構造のセットアップ: 基本的なファイル構造とエントリポイントの作成
- プロトコル実装: 必須のMCPメソッドの実装
- ツール定義: サーバーが提供するツールの定義
- 登録とテスト: Claude Codeへのサーバー追加と機能検証
- 機能強化と本番化: 実際の機能とエラー処理の追加
ステップ1: プロジェクトの基盤と構造
開発環境の作成
まず、MCPサーバーのための適切な開発環境を確立します。
# MCPサーバーディレクトリに移動
cd ~/.claude-mcp-servers/
# 新しいサーバープロジェクトを作成
mkdir my-first-server
cd my-first-server
# プロジェクト構造を初期化
touch server.py
touch requirements.txt
touch .env
この構造が重要な理由
整理された開発: 各サーバーを独自のディレクトリに保持することで、競合を防ぎ、メンテナンスが容易になります。
依存関係の分離: 各サーバーは、他のサーバーに影響を与えることなく、独自の要件を持つことができます。
構成管理: 環境ファイルを使用すると、値をハードコーディングすることなく安全な構成が可能になります。
MCPサーバーの要件の理解
すべてのMCPサーバーは、3つのコアJSON-RPCメソッドを実装する必要があります。
initialize
: 接続を確立し、サーバーの機能を宣言しますtools/list
: 利用可能なツールとそのスキーマを返しますtools/call
: 提供されたパラメータで特定のツールを実行します
ステップ2: コアサーバーフレームワークの実装
基本的なMCPサーバーテンプレートを含むserver.py
ファイルを作成します。
#!/usr/bin/env python3
"""
Claude Code統合のためのカスタムMCPサーバー
"""
import json
import sys
import os
from typing import Dict, Any, Optional
# 適切なMCP通信のためにバッファリングなしの出力を保証
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 1)
def send_response(response: Dict[str, Any]):
"""Claude CodeにJSON-RPCレスポンスを送信"""
print(json.dumps(response), flush=True)
def handle_initialize(request_id: Any) -> Dict[str, Any]:
"""MCP初期化ハンドシェイクを処理"""
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {
"tools": {}
},
"serverInfo": {
"name": "my-custom-server",
"version": "1.0.0"
}
}
}
def handle_tools_list(request_id: Any) -> Dict[str, Any]:
"""Claude Codeのために利用可能なツールをリストアップ"""
tools = [
{
"name": "hello_world",
"description": "簡単なデモンストレーションツール",
"inputSchema": {
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "挨拶する名前"
}
},
"required": ["name"]
}
}
]
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"tools": tools
}
}
def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
"""Claude Codeからのツール呼び出しを実行"""
tool_name = params.get("name")
arguments = params.get("arguments", {})
try:
if tool_name == "hello_world":
name = arguments.get("name", "World")
result = f"Hello, {name}! Your MCP server is working perfectly."
else:
raise ValueError(f"Unknown tool: {tool_name}")
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"content": [
{
"type": "text",
"text": result
}
]
}
}
except Exception as e:
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32603,
"message": str(e)
}
}
def main():
"""JSON-RPC通信を処理するメインサーバーループ"""
while True:
try:
line = sys.stdin.readline()
if not line:
break
request = json.loads(line.strip())
method = request.get("method")
request_id = request.get("id")
params = request.get("params", {})
if method == "initialize":
response = handle_initialize(request_id)
elif method == "tools/list":
response = handle_tools_list(request_id)
elif method == "tools/call":
response = handle_tool_call(request_id, params)
else:
response = {
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32601,
"message": f"Method not found: {method}"
}
}
send_response(response)
except json.JSONDecodeError:
continue
except EOFError:
break
except Exception as e:
if 'request_id' in locals():
send_response({
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32603,
"message": f"Internal error: {str(e)}"
}
})
if __name__ == "__main__":
main()
コードアーキテクチャの説明
入出力設定: 最初の数行は、MCP通信に不可欠なバッファリングなしのI/Oを構成します。バッファリングされた出力は、プロトコルを壊すメッセージ配信の遅延を引き起こす可能性があります。
JSON-RPC処理: メインループはstdinからJSON-RPCリクエストを読み取り、stdoutにレスポンスを書き込みます。これはローカルサーバー通信のためのMCP仕様に従います。
エラー処理戦略: コードは複数の層のエラー処理を実装しています。
- JSON解析エラー(不正な形式のリクエスト)
- メソッドが見つからないエラー(サポートされていない操作)
- ツール実行エラー(ランタイムの失敗)
プロトコル準拠: 各レスポンスには、適切な相関のための必須フィールドjsonrpc: "2.0"
とリクエストIDが含まれています。
ステップ3: サーバーの準備とテスト
サーバーを実行可能にする
# サーバーを実行可能にする
chmod +x server.py
実行権限が重要な理由: MCPサーバーはClaude Codeによってサブプロセスとして起動されます。実行権限がないと、起動は不可解な権限エラーで失敗します。
手動プロトコルテスト
Claude Codeに登録する前に、サーバーのプロトコル実装をテストします。
# 初期化ハンドシェイクをテスト
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py
期待される応答構造: プロトコルバージョンと機能を含むJSON応答が表示されるはずです。エラーメッセージが表示されるか、出力がない場合は、Pythonのインストールとスクリプトの構文を確認してください。
検証ステップ
続行する前に、これらの検証チェックを実行します。
- 構文チェック:
python3 -m py_compile server.py
- インポートテスト:
python3 -c "import json, sys, os"
- 実行テスト: 手動プロトコルテストが機能することを確認
ステップ4: Claude Codeへの登録
サーバーの追加
適切なスコープと絶対パスを使用してサーバーを登録します。
# グローバルユーザースコープで登録し、ユニバーサルアクセスを可能にする
claude mcp add --scope user my-first-server python3 ~/.claude-mcp-servers/my-first-server/server.py
重要な詳細:
- 「ファイルが見つかりません」エラーを避けるために絶対パスを使用
- 識別しやすいように説明的なサーバー名を選択
- 開発サーバーには常に
-scope user
を使用
検証とトラブルシューティング
# 登録を確認
claude mcp list
# 接続の問題をチェック
claude mcp get my-first-server
一般的な登録の問題:
- サーバーがリストにない: ファイルパスと権限を確認
- 接続失敗: Pythonのインストールとスクリプトの構文を確認
- スコープの問題: 競合する
.mcp.json
を持つディレクトリにいないことを確認
高度な例: 天気API統合
「Hello World」を超える
MCPサーバーの基本的な構造を理解したので、現実世界の統合パターンを示すより実用的なサーバーを構築しましょう。この天気APIサーバーでは、以下を学びます。
- 適切なエラー処理を伴う外部API統合
- 安全な構成のための環境変数管理
- 入力検証とパラメータ処理
- 最適なClaude Code統合のための応答フォーマット
- 本番対応のエラー処理パターン
API統合の計画
コードを書く前に、これらの統合側面を考慮します。
API選択: シンプルさと無料枠があるOpenWeatherMap APIを使用します。
データフロー: ユーザーリクエスト → パラメータ検証 → API呼び出し → 応答フォーマット → Claude応答
エラーシナリオ: ネットワーク障害、無効なAPIキー、不正な形式の応答、レート制限
セキュリティ: 環境変数に保存されたAPIキー、入力サニタイズ
実装戦略
このサーバーを段階的に構築し、各部分を完全なエラー処理で実装しましょう。
#!/usr/bin/env python3
import json
import sys
import os
import requests
from typing import Dict, Any
# 設定 - セキュリティのために環境変数を使用
WEATHER_API_KEY = os.environ.get("OPENWEATHER_API_KEY", "your-api-key-here")
def get_weather(city: str) -> str:
"""指定された都市の現在の天気データを取得"""
try:
url = "<http://api.openweathermap.org/data/2.5/weather>"
params = {
"q": city,
"appid": WEATHER_API_KEY,
"units": "metric"
}
response = requests.get(url, params=params, timeout=10)
data = response.json()
if response.status_code == 200:
temp = data["main"]["temp"]
desc = data["weather"][0]["description"]
humidity = data["main"]["humidity"]
return f"{city}の天気: {temp}°C、{desc.title()}、湿度: {humidity}%"
else:
return f"天気取得エラー: {data.get('message', '不明なエラー')}"
except requests.RequestException as e:
return f"ネットワークエラー: {str(e)}"
except Exception as e:
return f"天気データ処理エラー: {str(e)}"
def handle_tools_list(request_id: Any) -> Dict[str, Any]:
"""天気機能を備えた強化されたツールリスト"""
tools = [
{
"name": "get_weather",
"description": "世界中の任意の都市の現在の気象条件を取得",
"inputSchema": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "都市名(例: 'London', 'Tokyo', 'New York')"
}
},
"required": ["city"]
}
}
]
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"tools": tools
}
}
def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
"""天気機能を備えた強化されたツール実行"""
tool_name = params.get("name")
arguments = params.get("arguments", {})
try:
if tool_name == "get_weather":
city = arguments.get("city")
if not city:
raise ValueError("都市名が必要です")
result = get_weather(city)
else:
raise ValueError(f"不明なツール: {tool_name}")
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"content": [
{
"type": "text",
"text": result
}
]
}
}
except Exception as e:
return {
"jsonrpc": "2.0",
"id": request_id,
"error": {
"code": -32603,
"message": str(e)
}
}
# 基本的な例と同じmain()関数およびその他のハンドラを含む
高度な機能の説明
環境変数によるセキュリティ: APIキーは環境変数からロードされ、ハードコードされることはありません。これにより、バージョン管理での偶発的な露出を防ぎます。
堅牢なエラー処理: get_weather()
関数は複数のエラーシナリオを処理します。
- ネットワークタイムアウトと接続失敗
- 無効なAPI応答とレート制限
- 不正な形式のJSONデータ
- 欠落または無効なAPIキー
強化されたツールスキーマ: 天気ツールのスキーマには詳細な説明と例が含まれており、Claude Codeがツールを効果的に使用する方法を理解するのに役立ちます。
ステップ5: プロフェッショナルな依存関係と構成管理
適切な要件ファイルの作成
requests>=2.28.0
python-dotenv>=1.0.0
バージョン固定戦略: 最小バージョン要件(>=
)を使用することで、セキュリティアップデートを許可しながら互換性を確保します。本番サーバーの場合は、厳密なバージョン固定を検討してください。
安全な環境構成
構成管理のために.env
ファイルを作成します。
# 天気API構成
OPENWEATHER_API_KEY=your_actual_api_key_here
# サーバー構成
MCP_LOG_LEVEL=INFO
MCP_DEBUG=false
# オプション: レート制限
MCP_MAX_REQUESTS_PER_MINUTE=60
セキュリティのベストプラクティス:
.env
ファイルをバージョン管理にコミットしない- 強力でユニークなAPIキーを使用する
- 悪用を防ぐためにレート制限を実装する
- 本番環境でのAPIキーローテーションを検討する
依存関係のインストールと分離
# 分離のための仮想環境を作成
python3 -m venv mcp-env
source mcp-env/bin/activate # Windowsの場合: mcp-env\\\\Scripts\\\\activate
# 依存関係をインストール
pip install -r requirements.txt
# インストールを確認
python3 -c "import requests; print('Dependencies installed successfully')"
仮想環境が重要な理由: 分離により、異なるMCPサーバーとシステムPythonインストールの間の依存関係の競合を防ぎます。
MCPサーバーのテストとデバッグ
包括的なテスト戦略
MCPサーバーのテストには、プロトコル準拠と機能の正確性の両方を扱うため、多層的なアプローチが必要です。体系的なテスト戦略は、問題が本番環境に到達するのを防ぎ、デバッグをはるかに容易にします。
MCPサーバーのためのテストピラミッド
- ユニットテスト: 個々の関数のテスト
- プロトコルテスト: JSON-RPC準拠の検証
- 統合テスト: Claude Codeとのインタラクションテスト
- エンドツーエンドテスト: 全ワークフローの検証
レイヤー1: 手動プロトコルテスト
コアMCPメソッドのテスト
統合の前に、サーバーがMCPプロトコルを正しく実装していることを確認します。
# 初期化ハンドシェイクをテスト
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}' | python3 server.py
期待される応答構造:
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": {"tools": {}},
"serverInfo": {"name": "your-server", "version": "1.0.0"}
}
}
ツール発見のテスト
# ツールリストエンドポイントをテスト
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | python3 server.py
検証チェックリスト:
- 応答に
tools
配列が含まれている - 各ツールに
name
、description
、inputSchema
がある - スキーマがJSON Schema仕様に従っている
- スキーマ内の必須フィールドがマークされている
ツール実行のテスト
# 実際のツール機能をテスト
echo '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"hello_world","arguments":{"name":"Test"}}}' | python3 server.py
確認すべきこと:
- ツールがエラーなく実行される
- 応答に
content
配列が含まれている - コンテンツに適切な
type
とデータフィールドがある - エラー応答に適切なエラーコードが含まれている
レイヤー2: 自動テストフレームワーク
テストスクリプトの作成
自動テストのためにtest_server.py
ファイルを作成します。
#!/usr/bin/env python3
import json
import subprocess
import sys
def test_mcp_method(method, params=None):
"""特定のMCPメソッドをテスト"""
request = {
"jsonrpc": "2.0",
"id": 1,
"method": method,
"params": params or {}
}
try:
result = subprocess.run(
[sys.executable, "server.py"],
input=json.dumps(request),
capture_output=True,
text=True,
timeout=10
)
return json.loads(result.stdout.strip())
except Exception as e:
return {"error": str(e)}
# テストスイート
tests = [
("initialize", None),
("tools/list", None),
("tools/call", {"name": "hello_world", "arguments": {"name": "Test"}})
]
for method, params in tests:
response = test_mcp_method(method, params)
print(f"Testing {method}: {'✓ PASS' if 'result' in response else '✗ FAIL'}")
レイヤー3: Claude Codeとの統合テスト
サーバー登録と検証
# サーバーを登録
claude mcp add --scope user test-server python3 /full/path/to/server.py
# 登録を確認
claude mcp list | grep test-server
# サーバーのヘルスチェック
claude mcp get test-server
ライブ統合テスト
# テストモードでClaude Codeを起動
claude
# Claude Codeでツール発見をテスト
/mcp
# ツール実行をテスト
mcp__test-server__hello_world name:"Integration Test"
ツール命名パターン: Claude Codeは、命名衝突を避けるためにツールにmcp__<サーバー名>__<ツール名>
というプレフィックスを付けます。
高度なデバッグ技術
デバッグロギングの有効化
サーバーに包括的なロギングを追加します。
import logging
import sys
# stderrにロギングを構成 (JSON-RPCと干渉しない)
logging.basicConfig(
level=logging.DEBUG,
stream=sys.stderr,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
def handle_tool_call(request_id, params):
logger.debug(f"Received tool call: {params}")
# ... ツールのロジック
logger.debug(f"Tool execution completed successfully")
MCPサーバーログ分析
Claude Codeは各MCPサーバーのログを保持しています。
# 最新のログを表示 (macOS)
tail -f ~/Library/Logs/Claude/mcp-server-*.log
# 最新のログを表示 (Linux)
tail -f ~/.config/claude/logs/mcp-server-*.log
# エラーを検索
grep -i error ~/Library/Logs/Claude/mcp-server-*.log
一般的なデバッグパターン
問題: サーバーは起動するがツールが表示されない
診断: tools/list
応答形式を確認
解決策: JSONスキーマ準拠を検証
問題: ツール呼び出しがサイレントに失敗する
診断: tools/call
のエラー処理を確認
解決策: 包括的な例外処理を追加
問題: サーバー接続が切断される
診断: バッファリングなしI/Oと適切な例外処理を確認
解決策: sys.stdout
構成とメインループのエラー処理を検証
パフォーマンスと信頼性のテスト
サーバーのロードテスト
# 複数の高速リクエストをテスト
for i in {1..10}; do
echo '{"jsonrpc":"2.0","id":'$i',"method":"tools/list","params":{}}' | python3 server.py &
done
wait
メモリとリソースの監視
# サーバーのリソース使用状況を監視
python3 -m memory_profiler server.py
# 拡張操作中のメモリリークをチェック
python3 -m tracemalloc server.py
一般的な問題のトラブルシューティング
プロトコルレベルの問題
- 無効なJSON応答:
json.loads()
を使用して出力を検証 - 必須フィールドの欠落: MCP仕様準拠を確認
- 不正なエラーコード: 標準のJSON-RPCエラーコードを使用
統合の問題
- サーバーが表示されない: ファイル権限とPythonパスを検証
- ツールにアクセスできない: スコープ構成と登録を確認
- 認証失敗: 適切なMCP初期化を保証
ベストプラクティスとセキュリティ上の考慮事項
本番対応のエラー処理
堅牢な検証の実装
MCPサーバーのエラー処理は、障害がClaude Codeとの通信チェーン全体を破壊する可能性があるため、包括的である必要があります。複数のレベルで検証を実装します。
def validate_arguments(arguments: Dict[str, Any], required: List[str]):
"""必須の引数が存在することを確認"""
missing = [field for field in required if field not in arguments]
if missing:
raise ValueError(f"Missing required fields: {', '.join(missing)}")
def handle_tool_call(request_id: Any, params: Dict[str, Any]) -> Dict[str, Any]:
"""適切な検証を伴うツール実行"""
try:
tool_name = params.get("name")
arguments = params.get("arguments", {})
# 処理前に検証
if tool_name == "get_weather":
validate_arguments(arguments, ["city"])
# ここでツールのロジックを処理
except ValueError as ve:
return create_error_response(request_id, -32602, str(ve))
except Exception as e:
return create_error_response(request_id, -32603, f"Internal error: {str(e)}")
エラー応答基準
JSON-RPC 2.0のエラーコード規則に従います。
- 32700: 解析エラー (無効なJSON)
- 32600: 無効なリクエスト (不正な形式のリクエストオブジェクト)
- 32601: メソッドが見つからない (サポートされていないMCPメソッド)
- 32602: 無効なパラメータ (ツールに対する間違ったパラメータ)
- 32603: 内部エラー (サーバー側の実行失敗)
包括的なセキュリティフレームワーク
1. シークレット管理
機密情報をハードコードしないでください。構成には階層的なアプローチを使用します。
import os
from pathlib import Path
def load_config():
"""フォールバック階層で構成をロード"""
# 1. 環境変数 (最高優先度)
api_key = os.environ.get("API_KEY")
# 2. ローカルの.envファイル
if not api_key:
env_path = Path(".env")
if env_path.exists():
# .envファイルからロード
pass
# 3. システムキーリング (本番)
if not api_key:
try:
import keyring
api_key = keyring.get_password("mcp-server", "api_key")
except ImportError:
pass
if not api_key:
raise ValueError("API key not found in any configuration source")
return {"api_key": api_key}
2. 入力サニタイズと検証
インジェクション攻撃を防ぐために厳密な入力検証を実装します。
import re
from typing import Any, Dict
def sanitize_string_input(value: str, max_length: int = 100) -> str:
"""文字列入力をサニタイズ"""
if not isinstance(value, str):
raise ValueError("Expected string input")
# 潜在的に危険な文字を削除
sanitized = re.sub(r'[<>"\\\\']', '', value)
# DoSを防ぐために長さを制限
if len(sanitized) > max_length:
raise ValueError(f"Input too long (max {max_length} characters)")
return sanitized.strip()
def validate_city_name(city: str) -> str:
"""都市名入力を検証"""
sanitized = sanitize_string_input(city, 50)
# 文字、スペース、一般的な句読点のみを許可
if not re.match(r'^[a-zA-Z\\\\s\\\\-\\\\.]+$', sanitized):
raise ValueError("Invalid city name format")
return sanitized
3. レート制限とリソース保護
悪用を防ぐためにレート制限を実装します。
import time
from collections import defaultdict
from threading import Lock
class RateLimiter:
def __init__(self, max_requests: int = 60, window_seconds: int = 60):
self.max_requests = max_requests
self.window_seconds = window_seconds
self.requests = defaultdict(list)
self.lock = Lock()
def allow_request(self, client_id: str = "default") -> bool:
"""レート制限の下でリクエストが許可されるかチェック"""
now = time.time()
with self.lock:
# 古いリクエストをクリーンアップ
self.requests[client_id] = [
req_time for req_time in self.requests[client_id]
if now - req_time < self.window_seconds
]
# 制限をチェック
if len(self.requests[client_id]) >= self.max_requests:
return False
# このリクエストを記録
self.requests[client_id].append(now)
return True
# グローバルレート制限インスタンス
rate_limiter = RateLimiter()
高度なロギングと監視
構造化ロギングの実装
デバッグと監視を改善するために構造化ロギングを使用します。
import logging
import json
import sys
from datetime import datetime
class MCPFormatter(logging.Formatter):
"""MCPサーバーログ用のカスタムフォーマッター"""
def format(self, record):
log_entry = {
"timestamp": datetime.utcnow().isoformat(),
"level": record.levelname,
"message": record.getMessage(),
"module": record.module,
"function": record.funcName,
}
# 利用可能な場合は追加のコンテキストを追加
if hasattr(record, 'tool_name'):
log_entry["tool_name"] = record.tool_name
if hasattr(record, 'request_id'):
log_entry["request_id"] = record.request_id
return json.dumps(log_entry)
# 構造化ロギングを構成
logger = logging.getLogger(__name__)
handler = logging.StreamHandler(sys.stderr)
handler.setFormatter(MCPFormatter())
logger.addHandler(handler)
logger.setLevel(logging.INFO)
パフォーマンス監視
サーバーのパフォーマンスメトリックを追跡します。
import time
import statistics
from collections import deque
class PerformanceMonitor:
def __init__(self, max_samples: int = 1000):
self.response_times = deque(maxlen=max_samples)
self.error_count = 0
self.request_count = 0
def record_request(self, duration: float, success: bool):
"""リクエストメトリックを記録"""
self.request_count += 1
self.response_times.append(duration)
if not success:
self.error_count += 1
def get_stats(self) -> Dict[str, Any]:
"""現在のパフォーマンス統計を取得"""
if not self.response_times:
return {"no_data": True}
return {
"total_requests": self.request_count,
"error_rate": self.error_count / self.request_count,
"avg_response_time": statistics.mean(self.response_times),
"p95_response_time": statistics.quantiles(self.response_times, n=20)[18],
"p99_response_time": statistics.quantiles(self.response_times, n=100)[98]
}
# グローバルパフォーマンスモニター
perf_monitor = PerformanceMonitor()
デプロイメントとメンテナンス戦略
バージョン管理
MCPサーバーの適切なバージョン管理を実装します。
__version__ = "1.2.3"
__mcp_version__ = "2024-11-05"
def get_server_info():
"""MCP初期化のためのサーバー情報を返す"""
return {
"name": "my-production-server",
"version": __version__,
"mcp_protocol_version": __mcp_version__,
"capabilities": ["tools", "resources"], # サポートする機能を宣言
}
ヘルスチェックの実装
監視のためのヘルスチェック機能を追加します。
def handle_health_check(request_id: Any) -> Dict[str, Any]:
"""監視のためのヘルスチェックエンドポイント"""
try:
# コア機能のテスト
test_db_connection() # ヘルスチェックの例
test_external_apis() # ヘルスチェックの例
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"status": "healthy",
"timestamp": datetime.utcnow().isoformat(),
"version": __version__,
"uptime_seconds": time.time() - start_time,
"performance": perf_monitor.get_stats()
}
}
except Exception as e:
return {
"jsonrpc": "2.0",
"id": request_id,
"result": {
"status": "unhealthy",
"error": str(e),
"timestamp": datetime.utcnow().isoformat()
}
}
グレースフルシャットダウン処理
サーバーシャットダウン時の適切なクリーンアップを実装します。
import signal
import sys
class MCPServer:
def __init__(self):
self.running = True
self.active_requests = set()
# シグナルハンドラを登録
signal.signal(signal.SIGINT, self.shutdown_handler)
signal.signal(signal.SIGTERM, self.shutdown_handler)
def shutdown_handler(self, signum, frame):
"""グレースフルシャットダウンを処理"""
logger.info(f"Received signal {signum}, initiating graceful shutdown")
self.running = False
# アクティブなリクエストが完了するまで待機
timeout = 30 # 秒
start_time = time.time()
while self.active_requests and (time.time() - start_time) < timeout:
time.sleep(0.1)
logger.info("Shutdown complete")
sys.exit(0)
現実世界のユースケースと高度なアプリケーション
エンタープライズ統合パターン
MCPサーバーは、Claude Codeが既存のビジネスシステムと統合する必要があるエンタープライズ環境で優れています。以下は実証済みの統合パターンです。
データベース統合サーバー
- 顧客データ検索: CRMシステムから顧客情報を照会
- 在庫管理: リアルタイムの在庫レベルチェックと更新
- 分析ダッシュボード: ビジネスインテリジェンスシステムからレポートを生成
- 監査証跡の作成: コンプライアンスのためにAI支援の決定をログに記録
開発ワークフロー自動化
- CI/CDパイプライン統合: ビルド、デプロイ、テストをトリガー
- コード品質分析: SonarQube、ESLint、またはカスタムリンターと統合
- ドキュメント生成: コードアノテーションからAPIドキュメントを自動生成
- 課題追跡: Jira/GitHubの課題を作成、更新、照会
システム監視と運用
- インフラストラクチャ監視: Prometheus、Grafana、またはカスタムメトリックを照会
- ログ分析: アプリケーションログを検索および分析
- パフォーマンス最適化: ボトルネックを特定し、改善策を提案
- セキュリティスキャン: 脆弱性スキャナーおよびセキュリティツールと統合
高度なアーキテクチャパターン
マルチサーバーオーケストレーション
複雑なワークフローの場合、互いに連携するMCPサーバーを設計します。
# サーバー連携パターン
def coordinate_workflow(workflow_id: str, steps: List[Dict]) -> Dict:
"""サーバー間で多段階ワークフローを連携"""
results = {}
for step in steps:
server_name = step["server"]
tool_name = step["tool"]
params = step["params"]
# Claude Codeを通じて他のMCPサーバーを呼び出し
result = call_mcp_tool(server_name, tool_name, params)
results[step["id"]] = result
# ステップ間の依存関係を処理
if step.get("depends_on"):
inject_dependencies(params, results, step["depends_on"])
return {"workflow_id": workflow_id, "results": results}
キャッシングとパフォーマンス最適化
頻繁に要求されるデータのためにインテリジェントなキャッシングを実装します。
import hashlib
import pickle
from datetime import datetime, timedelta
class IntelligentCache:
def __init__(self, default_ttl: int = 3600):
self.cache = {}
self.default_ttl = default_ttl
def get_cache_key(self, tool_name: str, params: Dict) -> str:
"""一貫性のあるキャッシュキーを生成"""
key_data = f"{tool_name}:{json.dumps(params, sort_keys=True)}"
return hashlib.md5(key_data.encode()).hexdigest()
def get(self, tool_name: str, params: Dict) -> Optional[Any]:
"""有効な場合はキャッシュされた結果を取得"""
key = self.get_cache_key(tool_name, params)
if key in self.cache:
data, expiry = self.cache[key]
if datetime.now() < expiry:
return data
else:
del self.cache[key]
return None
def set(self, tool_name: str, params: Dict, result: Any, ttl: Optional[int] = None):
"""TTL付きで結果をキャッシュ"""
key = self.get_cache_key(tool_name, params)
expiry = datetime.now() + timedelta(seconds=ttl or self.default_ttl)
self.cache[key] = (result, expiry)
本番デプロイメント戦略
コンテナ化されたデプロイメント
一貫性のあるデプロイメントのために、MCPサーバーをDockerコンテナとしてパッケージ化します。
FROM python:3.11-slim
WORKDIR /app
# システム依存関係をインストール
RUN apt-get update && apt-get install -y \\\\
curl \\\\
&& rm -rf /var/lib/apt/lists/*
# Python依存関係をコピーしてインストール
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# アプリケーションコードをコピー
COPY server.py .
COPY config/ ./config/
# 非rootユーザーを作成
RUN useradd -m -s /bin/bash mcpuser
USER mcpuser
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \\\\
CMD python3 -c "import requests; requests.get('<http://localhost:8080/health>')"
CMD ["python3", "server.py"]
Kubernetesデプロイメント
スケーラビリティと信頼性のために、MCPサーバーをKubernetesにデプロイします。
apiVersion: apps/v1
kind: Deployment
metadata:
name: mcp-weather-server
spec:
replicas: 3
selector:
matchLabels:
app: mcp-weather-server
template:
metadata:
labels:
app: mcp-weather-server
spec:
containers:
- name: mcp-server
image: your-registry/mcp-weather-server:latest
ports:
- containerPort: 8080
env:
- name: OPENWEATHER_API_KEY
valueFrom:
secretKeyRef:
name: mcp-secrets
key: openweather-api-key
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
スケーリングとパフォーマンスの考慮事項
水平スケーリングパターン
MCPサーバーを水平スケーリングをサポートするように設計します。
- ステートレス設計: サーバーをステートレスに保ち、容易なレプリケーションを可能にする
- ロードバランシング: 複数のサーバーインスタンスにリクエストを分散
- データベースプーリング: データベースバックエンドのサーバーに接続プーリングを使用
- キャッシング戦略: 共有キャッシングのためにRedisまたはMemcachedを実装
パフォーマンス最適化技術
import asyncio
import aiohttp
from concurrent.futures import ThreadPoolExecutor
class HighPerformanceMCPServer:
def __init__(self):
self.executor = ThreadPoolExecutor(max_workers=10)
self.session = None
async def async_tool_call(self, tool_name: str, params: Dict) -> Dict:
"""ツール呼び出しを非同期で処理"""
if not self.session:
self.session = aiohttp.ClientSession()
# I/Oバウンドタスクに非同期操作を使用
if tool_name == "web_search":
return await self.async_web_search(params)
elif tool_name == "database_query":
return await self.async_database_query(params)
else:
# CPUバウンドタスクにスレッドプールを使用
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
self.executor,
self.sync_tool_call,
tool_name,
params
)
結論と次のステップ
MCP開発をマスターする
Claude CodeのためのMCPサーバー構築は、AIアプリケーション開発におけるパラダイムシフトを表しています。ハードコードされた接続を必要とする従来のAPI統合とは異なり、MCPはAIアシスタントを真に拡張可能にする動的で発見可能なインターフェースを提供します。
この包括的なガイドを通じて、あなたは以下を学びました。
基礎スキル:
- MCPプロトコルの基礎とアーキテクチャパターン
- 信頼性の高いデプロイメントのための重要な構成スコープ管理
- 基本から高度な段階的なサーバー実装
本番対応:
- 包括的なエラー処理と検証戦略
- シークレット管理と入力サニタイズを含むセキュリティフレームワーク
- パフォーマンス監視と最適化技術
高度な機能:
- マルチサーバーオーケストレーションとワークフロー連携
- キャッシング戦略と水平スケーリングパターン
- エンタープライズ統合とデプロイメント手法
戦略的な開発アプローチ
フェーズ1: 基盤構築 (1-2週目)
プロトコルを理解するために、シンプルで単一目的のサーバーから始めます。
- ファイルシステムユーティリティ (ファイルのリスト、読み取り、書き込み)
- 基本的なAPI統合 (天気、ニュース、計算機)
- システム情報ツール (ディスク容量、プロセス監視)
フェーズ2: 統合拡張 (3-4週目)
既存のシステムと統合するより複雑なサーバーを構築します。
- アプリケーションのためのデータベースクエリインターフェース
- 開発ツール統合 (git, CI/CD, テストフレームワーク)
- 通信ツール (メール、Slack、通知システム)
フェーズ3: エンタープライズデプロイメント (2ヶ月目以降)
完全な運用サポート付きで本番対応サーバーをデプロイします。
- ヘルスチェック付きのコンテナ化されたデプロイメント
- 監視とアラート統合
- セキュリティ強化とコンプライアンス機能
- マルチチーム連携とサーバー共有
長期的な成功戦略
コミュニティへの参加
- オープンソースへの貢献: サーバーをMCPコミュニティと共有
- 他者から学ぶ: 既存のサーバー実装を研究し、ベストプラクティスを学ぶ
- 最新情報を維持: MCPプロトコルの進化と新機能をフォロー
継続的な改善
- パフォーマンス監視: サーバーメトリックを追跡し、ボトルネックを最適化
- フィードバック収集: ユーザーフィードバックを収集し、機能を改善
- セキュリティアップデート: 依存関係とセキュリティプラクティスを定期的に更新
イノベーションの機会
- AIモデル統合: Claude Codeを専門AIモデルに接続
- 業界固有のツール: ドメインの専門知識のためのサーバーを構築
- ワークフロー自動化: 複雑なビジネスプロセスを自動化するサーバーを作成
MCP開発の未来
Model Context Protocolは、AI統合アプリケーションの新しいエコシステムの基盤を表しています。MCPサーバーを構築する際、あなたはClaude Codeのためのツールを作成しているだけでなく、MCP互換のAIアシスタントの拡大するエコシステム全体で機能する再利用可能なコンポーネントを構築しています。
MCP開発への投資は、以下を通じて利益をもたらします。
- プロトコル標準化: ツールが異なるAIプラットフォーム間で機能
- コミュニティ活用: 共有ライブラリとベストプラクティスから利益を得る
- 将来の互換性: 新しいAIアシスタントがすぐにあなたのサーバーを使用できる
成功のための重要なリマインダー
MCP開発の旅に乗り出すにあたり、これらの不可欠な原則を覚えておいてください。
- 構成スコープの習得: プロジェクトレベルの制限が特に必要な場合を除き、開発サーバーには常に
-scope user
を使用 - セキュリティ第一: シークレットをハードコードせず、常に入力を検証し、レート制限を実装
- エラー処理の完全性: すべての障害モードを予測し、適切に処理
- テストの徹底: プロトコル準拠、機能、統合をテスト
- ドキュメントの品質: チーム連携とメンテナンスのためにサーバーをドキュメント化
ヘルプとリソースの入手
課題に遭遇した場合:
- 公式MCPドキュメント: 最新のプロトコル仕様を参照
- コミュニティフォーラム: 他のMCP開発者と交流してトラブルシューティング
- GitHubリポジトリ: オープンソースのMCPサーバー実装を研究
- Claude Codeログ: サーバーログを使用して接続と実行の問題をデバッグ
今日から構築を開始し、迅速にイテレーションを行い、Model Context Protocolを通じてAI機能を拡張する開発者の成長するコミュニティに参加してください。あなたのカスタムMCPサーバーは、私たちが想像し始めたばかりのAI支援ワークフローのための新しい可能性を解き放ちます。
覚えておいてください: すべての複雑な統合は、シンプルな「Hello World」サーバーから始まりました。基本から始め、基礎をマスターし、作業方法を変革するAI統合ツールを徐々に構築してください。
最高の生産性で開発チームが連携するための統合されたオールインワンプラットフォームをお探しですか?
Apidogは、あなたのすべての要求に応え、Postmanをはるかに手頃な価格で置き換えます!