AIコーディング 2026.04.22
Claude CodeでMCPサーバー連携【2026年版】設定方法とPythonカスタムサーバー実装
MCPの仕組み
Claude Code ←→ MCPサーバー ←→ 外部API/DB/ファイル
MCPサーバーは「Claude用のプラグイン」。
ツールを定義すると、ClaudeがそのツールをAPIコールするように使えます。
設定ファイルの書き方
// ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"exchange-rates": {
"command": "python",
"args": ["/Users/you/mcp-servers/exchange_server.py"],
"env": {
"EXCHANGE_API_KEY": "your-api-key-here"
}
},
"database": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-sqlite", "/path/to/db.sqlite"]
}
}
}
設定後 claude --mcp-servers で認識されているサーバーを確認:
claude --mcp-servers
# → exchange-rates: connected
# → database: connected
Pythonで為替レートMCPサーバーを実装する
# exchange_server.py
# pip install mcp requests
import os
import requests
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp import types
app = Server("exchange-rates")
API_KEY = os.environ.get("EXCHANGE_API_KEY", "")
@app.list_tools()
async def list_tools() -> list[types.Tool]:
"""Claudeに提供するツールの一覧を返す"""
return [
types.Tool(
name="get_exchange_rate",
description="通貨間の為替レートを取得します",
inputSchema={
"type": "object",
"properties": {
"from_currency": {
"type": "string",
"description": "変換元通貨(例: JPY, USD, EUR)"
},
"to_currency": {
"type": "string",
"description": "変換先通貨"
},
"amount": {
"type": "number",
"description": "変換する金額",
"default": 1
}
},
"required": ["from_currency", "to_currency"]
}
),
types.Tool(
name="list_currencies",
description="利用可能な通貨の一覧を返します",
inputSchema={"type": "object", "properties": {}}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
"""ツールを実行してClaudeに結果を返す"""
if name == "get_exchange_rate":
from_curr = arguments["from_currency"].upper()
to_curr = arguments["to_currency"].upper()
amount = arguments.get("amount", 1)
# exchangerate-api.com(無料プランあり)を使用
response = requests.get(
f"https://v6.exchangerate-api.com/v6/{API_KEY}/pair/{from_curr}/{to_curr}/{amount}"
)
data = response.json()
if data.get("result") == "success":
rate = data["conversion_rate"]
converted = data["conversion_result"]
result = f"{amount} {from_curr} = {converted:.4f} {to_curr}(レート: {rate:.6f})"
else:
result = f"エラー: {data.get('error-type', '不明なエラー')}"
return [types.TextContent(type="text", text=result)]
if name == "list_currencies":
currencies = ["JPY", "USD", "EUR", "GBP", "AUD", "CAD", "CHF", "CNY", "KRW"]
return [types.TextContent(type="text", text=", ".join(currencies))]
return [types.TextContent(type="text", text=f"不明なツール: {name}")]
async def main():
async with stdio_server() as (read_stream, write_stream):
await app.run(read_stream, write_stream, app.create_initialization_options())
if __name__ == "__main__":
import asyncio
asyncio.run(main())
Claude Codeから使う
# Claude Codeを起動
claude
# MCPツールが使えるようになる
> 100円は今何ドル?
# → Claudeがget_exchange_rateツールを呼び出して最新レートを取得して回答
> 「今日の為替レートを取得してCSVに保存するスクリプトを書いて」と指示すると
# → ClaudeがMCPツールでレートを取得し、CSVを生成するコードを書いてくれる
データベース連携のMCPサーバー
# database_server.py
# SQLiteデータベースに自然言語でクエリを実行する
import sqlite3
from mcp.server import Server
from mcp import types
from mcp.server.stdio import stdio_server
app = Server("database")
DB_PATH = "sales.db"
@app.list_tools()
async def list_tools() -> list[types.Tool]:
return [
types.Tool(
name="query_db",
description="SQLiteデータベースにSQLクエリを実行します",
inputSchema={
"type": "object",
"properties": {
"sql": {"type": "string", "description": "実行するSQLクエリ(SELECT推奨)"},
},
"required": ["sql"]
}
),
types.Tool(
name="list_tables",
description="データベースのテーブル一覧を返します",
inputSchema={"type": "object", "properties": {}}
)
]
@app.call_tool()
async def call_tool(name: str, arguments: dict) -> list[types.TextContent]:
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
try:
if name == "query_db":
sql = arguments["sql"]
# SELECT以外は拒否(セキュリティ対策)
if not sql.strip().upper().startswith("SELECT"):
return [types.TextContent(type="text", text="エラー: SELECTクエリのみ許可されています")]
cursor.execute(sql)
rows = cursor.fetchall()
if not rows:
return [types.TextContent(type="text", text="結果なし")]
# テーブル形式で返す
headers = rows[0].keys()
result = " | ".join(headers) + "\n"
result += "-" * 40 + "\n"
for row in rows[:20]: # 最大20行
result += " | ".join(str(v) for v in row) + "\n"
return [types.TextContent(type="text", text=result)]
if name == "list_tables":
cursor.execute("SELECT name FROM sqlite_master WHERE type='table'")
tables = [row[0] for row in cursor.fetchall()]
return [types.TextContent(type="text", text=", ".join(tables))]
finally:
conn.close()
return [types.TextContent(type="text", text="不明なツール")]
あわせて読みたい
- Claude Codeセットアップ完全ガイド【macOS/Windows/WSL】
- Claude CodeでJira調査を自動化する。MCPサーバーでツール連携を実現
- Claude Code できること完全リスト【2026年版】