MCPとは何か
MCP(Model Context Protocol)はAnthropicが2024年末に公開したオープンプロトコルで、AIアシスタントと外部ツール・データソースを標準化された方法で接続するための仕様です。
Claude Codeにはデフォルトでファイル読み書き・Bashコマンド実行などのツールが用意されていますが、MCPサーバーを追加することで独自のツールを組み込めます。たとえば社内APIへのアクセス・Notionのページ取得・Slackへのメッセージ送信といった機能を、自然言語でClaude Codeに指示するだけで実行できるようになります。
MCPサーバーの仕組み
MCPはクライアント(Claude Code)とサーバー(独自実装)間の通信プロトコルです。
通信はstdio(標準入出力)またはSSEで行われます。Claude CodeがMCPサーバーを子プロセスとして起動し、JSONRPCメッセージでやり取りします。
MCPサーバーが提供できるものは3種類です。
- Tools:Claudeが実行できる関数(ファイル取得・API呼び出しなど)
- Resources:Claudeが参照できるデータ(ドキュメント・DB内容など)
- Prompts:定型プロンプトのテンプレート
今回は最も使われるToolsの実装に絞って説明します。
TypeScriptでのMCPサーバー実装
公式SDKを使って天気情報を返すシンプルなMCPサーバーを作ります。
mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk
npm install -D typescript @types/node ts-node
// src/index.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const server = new McpServer({
name: "weather-mcp",
version: "1.0.0",
});
// ツールの定義
server.tool(
"get_weather",
"指定した都市の現在の天気を返す",
{
city: z.string().describe("都市名(例:東京、大阪)"),
},
async ({ city }) => {
// 実際にはWeather APIを呼ぶ
const weatherData = {
city,
temperature: 18,
condition: "晴れ",
humidity: 60,
};
return {
content: [
{
type: "text",
text: JSON.stringify(weatherData, null, 2),
},
],
};
}
);
async function main() {
const transport = new StdioServerTransport();
await server.connect(transport);
console.error("Weather MCP server started");
}
main().catch(console.error);
// tsconfig.json
{
"compilerOptions": {
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "./dist",
"rootDir": "./src"
}
}
PythonでのMCPサーバー実装
pip install mcp
# server.py
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent
import json
app = Server("weather-mcp")
@app.list_tools()
async def list_tools() -> list[Tool]:
return [
Tool(
name="get_weather",
description="指定した都市の現在の天気を返す",
inputSchema={
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "都市名"
}
},
"required": ["city"]
}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[TextContent]:
if name == "get_weather":
city = arguments["city"]
# 実際にはAPIを呼ぶ
data = {"city": city, "temperature": 18, "condition": "晴れ"}
return [TextContent(type="text", text=json.dumps(data, ensure_ascii=False))]
raise ValueError(f"Unknown tool: {name}")
if __name__ == "__main__":
import asyncio
asyncio.run(stdio_server(app))
Claude Codeへの登録
MCPサーバーをClaude Codeで使えるようにするには、設定ファイルに登録します。
~/.claude/settings.json または プロジェクトの .claude/settings.json を編集します。
{
"mcpServers": {
"weather": {
"command": "node",
"args": ["/absolute/path/to/my-mcp-server/dist/index.js"],
"env": {
"WEATHER_API_KEY": "your-api-key"
}
}
}
}
Pythonの場合:
{
"mcpServers": {
"weather": {
"command": "python",
"args": ["/absolute/path/to/server.py"]
}
}
}
動作確認
Claude Codeを再起動すると、登録したMCPサーバーが自動的に読み込まれます。
claude
起動後に以下のように話しかけると、定義したツールが呼び出されます。
東京の今日の天気を調べてください
Claude Codeが get_weather ツールを選択して呼び出し、返ってきた結果を自然言語で回答します。
ツールが認識されているか確認するには /mcp コマンドを使います。
デバッグのコツ
MCPサーバーのデバッグはstderrへのログ出力が基本です(stdoutはJSONRPC通信に使われるため)。
TypeScriptなら console.error("debug:", data) 、Pythonなら import sys; print("debug:", data, file=sys.stderr) でデバッグ情報を出力できます。
claude --mcp-debug フラグで起動するとMCP通信の詳細ログが確認できます。
まとめ
MCPサーバーの自作はTypeScript・Pythonどちらでも公式SDKを使って比較的シンプルに実装できます。settings.json に登録するだけでClaude Codeがツールとして認識し、自然言語で呼び出せるようになります。社内APIや独自データソースへのアクセスをMCPサーバーとして実装することで、Claude Codeを自分のワークフローに統合できます。