
長年、大規模言語モデル(LLM)を社内データベース、ローカルファイルシステム、開発者ツールに接続するには、LLMプロバイダーごとに専用の関数呼び出しスキーマを作成する必要がありました。モデルを切り替えたり、エージェントフレームワークを更新したりするたびに、ツール定義、認証境界、シリアル化ロジックを再実装しなければなりませんでした。
Anthropicが導入し、Claude Desktop、Cursor、および最新のAI開発環境で広く採用されている**モデルコンテキストプロトコル(MCP)は、この断片化を解決します。MCPは、LLMが標準化されたJSON-RPCインターフェースを介してローカルおよびリモートのツールを検出し、検査し、呼び出すことを可能にする、ユニバーサルでオープンな標準、つまり「AI統合のUSB-C」**です。
このガイドでは、MCPのアーキテクチャを分解し、FastMCPを使用して本番環境レベルのPython MCPサーバーをゼロから構築し、セキュアなツールと動的リソースを実装し、それをClaude Desktopに直接接続します。
Configure stdio & SSE servers with Claude, Cursor & Python export
Configure and validate Model Context Protocol (MCP) servers with stdio and SSE transports. Export ready-to-run configurations for Claude Desktop, Claude Code CLI, Cursor, and TypeScript/Python SDKs.
MCPがどのように機能するかを理解するために、プロトコルにおける3つの主要な参加者を見てみましょう。
stdin/stdout)を介して通信します。これは、ローカル開発マシン向けの標準的でオーバーヘッドのないモードです。uvを使ったPython環境のセットアップ超高速Pythonパッケージマネージャーであるuvを使用して、プロジェクトを初期化し、公式のPython MCP SDKをインストールします。
# Create project directory
mkdir local-dev-mcp && cd local-dev-mcp
# Initialize Python workspace
uv init
uv add mcp pydantic
FastMCPを使ったサーバーの構築Python SDKは、FastAPIをモデルにした高レベルフレームワークであるFastMCPを提供します。これは、パラメータースキーマ、型ヒント、ドキュメント文字列を自動的に有効なJSON-RPCツールスキーマに抽出します。
server.pyを作成します。
# server.py: Production Local Developer MCP Server
import os
from pathlib import Path
from pydantic import BaseModel, Field
from mcp.server.fastmcp import FastMCP
# Initialize the MCP Server with identity and version
mcp = FastMCP("Developer-Workspace-Tools", version="1.0.0")
# Define a safe base directory to prevent directory traversal attacks
SAFE_WORKSPACE = Path(os.getenv("MCP_WORKSPACE_DIR", "./workspace")).resolve()
SAFE_WORKSPACE.mkdir(parents=True, exist_ok=True)
def resolve_safe_path(relative_path: str) -> Path:
"""Guarantees file operations remain strictly inside the authorized workspace."""
resolved = (SAFE_WORKSPACE / relative_path).resolve()
if not str(resolved).startswith(str(SAFE_WORKSPACE)):
raise PermissionError(f"Access denied: '{relative_path}' attempts path traversal.")
return resolved
# ====================================================================
# Primitive 1: Tools (Callable Actions)
# ====================================================================
@mcp.tool()
def save_code_snippet(filename: str, code: str, language: str = "python") -> str:
"""
Saves a code snippet to the authorized local workspace.
Args:
filename: Name of the file including extension (e.g., 'auth_utils.py')
code: Full code content to write
language: Programming language identifier for metadata
"""
target_path = resolve_safe_path(filename)
target_path.parent.mkdir(parents=True, exist_ok=True)
with open(target_path, "w", encoding="utf-8") as f:
f.write(code)
return f"Successfully wrote {len(code)} bytes to {filename} (Language: {language})"
@mcp.tool()
def list_workspace_files() -> list[dict]:
"""Lists all files in the developer workspace with file size and modified timestamps."""
files = []
for p in SAFE_WORKSPACE.rglob("*"):
if p.is_file():
stat = p.stat()
files.append({
"relative_path": str(p.relative_to(SAFE_WORKSPACE)),
"size_bytes": stat.st_size,
"modified_timestamp": stat.st_mtime,
})
return files
# ====================================================================
# Primitive 2: Resources (Context Streams)
# ====================================================================
@mcp.resource("workspace://logs/{log_name}")
def get_system_log(log_name: str) -> str:
"""Reads a designated log file from the workspace for debugging context."""
log_path = resolve_safe_path(f"logs/{log_name}.log")
if not log_path.exists():
return f"Log file '{log_name}' not found."
with open(log_path, "r", encoding="utf-8") as f:
# Return the last 50 lines to conserve context window
lines = f.readlines()
return "".join(lines[-50:])
if __name__ == "__main__":
# Runs the Stdio transport event loop
mcp.run()
Claude Desktopが新しいMCPサーバーを検出して呼び出せるように、JSON設定ファイルを構成します。
~/Library/Application Support/Claude/claude_desktop_config.json~/.config/Claude/claude_desktop_config.json%APPDATA%\Claude\claude_desktop_config.jsonmcpServersの下にサーバー定義を追加します。
{
"mcpServers": {
"developer-workspace": {
"command": "uv",
"args": [
"run",
"--directory",
"/absolute/path/to/local-dev-mcp",
"server.py"
],
"env": {
"MCP_WORKSPACE_DIR": "/absolute/path/to/workspace"
}
}
}
}
Claude Desktopを再起動します。チャット入力ボックスの右下隅に新しい🔌 ハンマー/ツールアイコンが表示されます。これをクリックすると、登録されたツールであるsave_code_snippetとlist_workspace_filesが表示されます。
Claude Desktopに接続する前に、公式のブラウザベースのMCP Inspectorを使用して、MCPサーバーを対話的にテストおよびデバッグできます。
# Launch the interactive MCP debugger
npx @modelcontextprotocol/inspector uv run server.py
インスペクターはローカルのWeb UIを起動し、そこで次のことができます。
pathlib.Path.resolve()を使用して明示的なベースディレクトリに対して解決してください。LLMによって直接渡される相対パス文字列を信頼しないでください。SELECTのみの権限を持つデータベースロールで接続してください。print()ステートメントを使用しないでください。標準出力はJSON-RPCメッセージ専用であるため、任意のテキスト出力はワイヤプロトコルを破損します。標準のPython loggingをsys.stderrに書き込むように設定して使用してください。開発者が、独自の内部データベースをClaude Desktopと統合するためのMCPサーバーを構築しています。彼らは、ローカル開発での最小限のレイテンシと、データベースへの外部アクセスを防ぐ最大限のセキュリティを確保する必要があります。このシナリオで優先すべきMCPトランスポートメカニズムは何ですか?
はい、できます。MCPサーバーは単なる標準コードです。ツール実装内でhttpxやrequestsを使用して、GitHub API、Slack Webhook、Jiraチケット、または内部Kubernetesクラスターを呼び出すことができます。
Claudeは、MCPサーバーによってアドバタイズされる関数シグネチャとドキュメント文字列を検査します。ツールの機能、パラメーターの意味、および呼び出すべきタイミングを説明する記述的なドキュメント文字列を作成することが、信頼性の高いツール呼び出しにとって最も重要な要素です。
AI CLIログの整形、Cron式の作成、JWTの解析、chmod権限の計算をオフラインで実行。

Claudeの無料プランでSonnetモデル、200Kコンテキスト、Projects、Claude Desktop経由のローカルMCPツールを使いこなし、メッセージ制限を予想以上に引き延ばす方法をご紹介します。
続きを読む
Streamable HTTP、DNSリバインディング対策、OAuth 2.1 Bearerトークン、FastAPIを活用した本番環境向けリモートModel Context Protocol (MCP) サーバーの設計・セキュリティ・デプロイ実践。
続きを読む
開発者がChatGPT、Claude、Geminiについて、それぞれの役立つ点、邪魔になる点、タスクに合ったツールを選ぶ方法を正直に語ります。
続きを読む