Model Context Protocol(MCP)をClaude CodeとChatGPT APIで活用する方法|ツール連携の標準化と実装パターン【2026年版】
Model Context Protocol(MCP)とは?ツール連携の標準化が進む2026年
Model Context Protocol(MCP)は、Anthropicが推し進めるLLM(大規模言語モデル)とツール・データソースを接続するための標準仕様です。2026年現在、Claude Code、ChatGPT API、その他のAIコーディングツールの間で、ツール連携設計の「標準」として急速に採用が広がっています。
従来、各LLMがツール連携を実装する際は、独自の仕様を使っていました。そのため開発者は、同じ機能を複数のLLMに対応させようとするたびに、異なるAPI設計を学び直す必要がありました。MCPはこの課題を解決し、一度設計したツール連携インターフェースを複数のLLMプラットフォーム間で再利用できるようにします。
MCPの主要な特徴と利点
標準化による開発効率の向上
MCPの最大の利点は、ツール連携の仕様を統一することで、開発者の学習コストと実装時間を削減することです。
- クロスプラットフォーム対応: Claude Code、ChatGPT API、その他のLLMサービスに同じインターフェースで接続可能
- 再利用性: 一度実装したツール連携ロジックを複数のプロジェクトで流用できる
- 保守性: 業界標準に従うため、チーム内での知識共有とコード管理が容易
パイプランアーキテクチャによるエージェント制御
MCPは「パイプラインレイヤー」という考え方を導入しています。これは、LLMの指示内容に頼るのではなく、データフロー自体に制御ロジックを埋め込むアーキテクチャを指します。
具体的には:
- エージェント境界の明確化: エージェント(自動判断するシステム)と知識ベース(参照用データ)の責任を分離
- パイプラインレイヤーでの制御: LLMの指示文に「〜しないでください」と書くのではなく、パイプラインの設計時点で不正なデータフローを物理的に遮断
- 自己参照の防止: デフォルトでは同じデータソースへの重複参照を避け、意図しない無限ループを防止
これにより、プロンプトの書き方だけに頼った曖昧な制御から、設計段階で保証された堅牢なエージェントシステムへシフトします。
Claude CodeでMCPを実装する基本パターン
Claude CodeのMCP統合方法
Claude Codeは、MCPサーバーに接続することで、外部ツール・API・データベースへのアクセスを標準化できます。
ステップ1: MCPサーバーの仕様を理解する
MCPサーバーは、以下の機能を提供します:
- Tool(ツール): LLMが直接呼び出せる関数型のインターフェース
- Resource(リソース): 参照可能なテキスト・ファイル・データソース
- Prompt(プロンプト): テンプレート化された事前設定プロンプト
ステップ2: 基本的なMCPツール定義
MCPサーバー上でツールを定義する際の一般的なパターンは以下の通りです:
{
"tools": [
{
"name": "execute_code",
"description": "JavaScriptコードを実行して結果を返す",
"inputSchema": {
"type": "object",
"properties": {
"code": {
"type": "string",
"description": "実行するJavaScriptコード"
}
},
"required": ["code"]
}
},
{
"name": "fetch_api",
"description": "HTTPリクエストを送信してレスポンスを取得",
"inputSchema": {
"type": "object",
"properties": {
"url": {
"type": "string",
"description": "リクエスト先のURL"
},
"method": {
"type": "string",
"enum": ["GET", "POST", "PUT", "DELETE"],
"description": "HTTPメソッド"
}
},
"required": ["url"]
}
}
]
}
ステップ3: Claude CodeでMCPサーバーに接続
Claude Codeの設定ファイル(通常は.claudercまたはclaude-config.json)にMCPサーバーのエンドポイントを登録します:
{
"mcp_servers": [
{
"name": "local_tools",
"url": "http://localhost:3000",
"auth": {
"type": "none"
}
},
{
"name": "api_gateway",
"url": "http://api-gateway.internal:5000",
"auth": {
"type": "bearer",
"token": "${MCP_API_TOKEN}"
}
}
]
}
環境変数をセットして接続を確認します:
export MCP_API_TOKEN="your-token-here"
claude-code --config claude-config.json
ChatGPT APIでMCPを活用する実装方法
ChatGPT APIのツール連携との互換性
ChatGPT APIも、MCPの標準仕様に段階的に対応しています。これにより、MCPで定義されたツールをChatGPT API経由でも呼び出せるようになります。
実装パターン: MCPツールをOpenAI関数呼び出しにマッピング
MCPツール定義をOpenAI Assistants APIのツール定義に変換するブリッジを構築します:
import json
import requests
from openai import OpenAI
# MCPサーバーからツール定義を取得
mcp_url = "http://localhost:3000"
mcp_tools_response = requests.get(f"{mcp_url}/tools")
mcp_tools = mcp_tools_response.json()
# MCPツール定義をOpenAI形式に変換
def convert_mcp_to_openai_tool(mcp_tool):
return {
"type": "function",
"function": {
"name": mcp_tool["name"],
"description": mcp_tool["description"],
"parameters": mcp_tool["inputSchema"]
}
}
openai_tools = [convert_mcp_to_openai_tool(tool) for tool in mcp_tools]
# OpenAIクライアントを初期化
client = OpenAI(api_key="your-openai-api-key")
# MCPツールをOpenAI Assistants APIに登録
assistant = client.beta.assistants.create(
name="MCP-Integrated Assistant",
model="gpt-4",
tools=openai_tools
)
# ツール呼び出しを処理
def handle_tool_call(tool_name, tool_input):
# MCPサーバーに要求を転送
response = requests.post(
f"{mcp_url}/tools/{tool_name}/call",
json=tool_input
)
return response.json()
ステップバイステップ: ChatGPT APIでの統合
- MCPサーバーの起動
# ローカルでMCPサーバーを起動(Node.js例)
npm install -g mcp-server-core
mcp-server --port 3000 --config ./mcp-config.json
- OpenAI Assistantsの設定
# MCPツールを使用したアシスタントの作成
tools = [
{
"type": "function",
"function": {
"name": "search_database",
"description": "指定されたクエリでデータベースを検索",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string"},
"limit": {"type": "integer", "default": 10}
},
"required": ["query"]
}
}
}
]
assistant = client.beta.assistants.create(
name="Database Query Assistant",
model="gpt-4",
tools=tools
)
- スレッドでの会話実行とツール呼び出し
# スレッドを作成
thread = client.beta.threads.create()
# ユーザーメッセージを追加
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content="最近のログを検索してください"
)
# アシスタントに実行させ、ツール呼び出しを待つ
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)
# ツール呼び出しをポーリング
import time
while run.status in ["queued", "in_progress"]:
run = client.beta.threads.runs.retrieve(
thread_id=thread.id,
run_id=run.id
)
time.sleep(0.5)
# ツール呼び出しが必要な場合は処理
if run.status == "requires_action":
tool_calls = run.required_action.submit_tool_outputs.tool_calls
tool_outputs = []
for tool_call in tool_calls:
result = handle_tool_call(
tool_call.function.name,
json.loads(tool_call.function.arguments)
)
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(result)
})
# ツール実行結果をアシスタントに返す
run = client.beta.threads.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
MCPアーキテクチャの設計パターン
パイプランレイヤーでのエージェント制御設計
MCPを活用した堅牢なシステム設計では、以下のアーキテクチャパターンが推奨されます。
パターン1: 知識ベースとエージェント分離
┌─────────────────┐
│ LLM(Claude) │
├─────────────────┤
│ エージェント │
│ (判断・計画) │
└────────┬────────┘
│
┌────┴────────────────┬──────────┐
│ │ │
┌───▼────────────┐ ┌────▼──────┐ ┌▼──────────┐
│ 知識ベース │ │ ツール │ │API │
│(読み取り) │ │(実行) │ │(外部連携)
└────────────────┘ └───────────┘ └───────────┘
このアーキテクチャでは:
- LLMエージェント: ユーザー要求を解析し、実行計画を立てる
- 知識ベース: 参照用データ(ドキュメント、FAQ、設定値)。LLMは読み込み専用
- ツール層: 実際にシステム状態を変更(APIの呼び出し、ファイル作成、DB操作)
この分離により、LLMが「知識ベースを誤って上書きする」という問題を構造的に防ぎます。
パターン2: MCPリソースによる自己参照の防止
MCPの「Resource」機能を使い、デフォルトでは同じデータソースへの重複参照を排除します:
{
"resources": [
{
"name": "user_database",
"type": "database",
"uri": "postgresql://db.internal/users",
"access_control": {
"read": "allowed",
"write": "denied",
"self_reference": "prohibited"
}
},
{
"name": "api_cache",
"type": "cache",
"uri": "redis://cache.internal:6379",
"access_control": {
"read": "allowed",
"write": "agent_only",
"self_reference": "with_version_check"
}
}
]
}
self_reference: "prohibited"の設定により、同一のリソースに対する複数アクセスがパイプレイヤーで自動的に統合されます。
実践的な設計チェックリスト
MCPを導入する際、以下の項目を確認してください:
| 項目 | 確認ポイント |
|---|---|
| データフロー分離 | エージェント(判断)と知識ベース(参照)は物理的に分離されているか |
| 自己参照対策 | 同一リソースへの重複アクセスはパイプレイヤーで制御されているか |
| ツール呼び出しの原子性 | ツール実行は中途半端な状態(失敗時のロールバック)を起こさないか |
| エラーハンドリング | ツール呼び出し失敗時の復帰ロジックが明示的に実装されているか |
| 監査ログ | すべてのツール呼び出しと結果がログに記録されているか |
| アクセス制御 | MCPサーバーへの接続は認証・暗号化されているか |
実装例: Claude CodeでのMCP活用ケース
ケース1: 社内APIの標準化された統合
複数の社内マイクロサービス(ユーザー管理、請求、ログ分析)をClaude Codeから統一インターフェースでアクセスする例:
// mcp-server.js: MCPサーバーの実装
const express = require('express');
const app = express();
// ツール: ユーザー検索
const tools = {
search_user: {
name: "search_user",
description: "ユーザーデータベースから指定条件で検索",
inputSchema: {
type: "object",
properties: {
email: { type: "string" },
status: { type: "string", enum: ["active", "inactive", "suspended"] }
},
required: ["email"]
},
handler: async (input) => {
// 社内APIを呼び出し
const response = await fetch('http://user-service.internal/api/search', {
method: 'POST',
headers: { 'Authorization': `Bearer ${process.env.SERVICE_TOKEN}` },
body: JSON.stringify(input)
});
return response.json();
}
},
get_billing_info: {
name: "get_billing_info",
description: "ユーザーの請求情報を取得",
inputSchema: {
type: "object",
properties: {
user_id: { type: "string" }
},
required: ["user_id"]
},
handler: async (input) => {
const response = await fetch(`http://billing-service.internal/api/users/${input.user_id}`, {
headers: { 'Authorization': `Bearer ${process.env.SERVICE_TOKEN}` }
});
return response.json();
}
}
};
// MCPエンドポイント
app.get('/tools', (req, res) => {
res.json(Object.values(tools).map(t => ({
name: t.name,
description: t.description,
inputSchema: t.inputSchema
})));
});
app.post('/tools/:name/call', async (req, res) => {
const tool = tools[req.params.name];
if (!tool) {
return res.status(404).json({ error: 'Tool not found' });
}
try {
const result = await tool.handler(req.body);
res.json(result);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => console.log('MCP Server running on port 3000'));
Claude Codeでこのサーバーを使用:
# Claude設定ファイルに登録
cat >> claude-config.json << 'EOF'
{
"mcp_servers": [
{
"name": "company_services",
"url": "http://localhost:3000",
"auth": { "type": "none" }
}
]
}
EOF
# Claude Codeを起動
claude-code --config claude-config.json
Claude Code内でのプロンプト例:
ユーザー alice@example.com の請求状況を確認してください。
以下の手順で進めてください:
1. search_user ツールで alice@example.com を検索
2. 返ってきたユーザーIDを使用して get_billing_info を呼び出し
3. 結果をまとめてレポートしてください
Claude Codeは以下のステップを自動実行します。
ケース2: ChatGPT APIを使った多段階ワークフロー
データ分析・可視化のワークフローをMCP統合で実現:
from openai import OpenAI
import json
import subprocess
client = OpenAI(api_key="your-api-key")
# ステップ1: MCPサーバーを起動
subprocess.Popen([
"node", "mcp-data-tools.js",
"--port", "3001"
])
# ステップ2: MCPから利用可能なツール取得
import requests
mcp_response = requests.get("http://localhost:3001/tools")
mcp_tools = mcp_response.json()
openai_tools = [
{
"type": "function",
"function": {
"name": tool["name"],
"description": tool["description"],
"parameters": tool["inputSchema"]
}
}
for tool in mcp_tools
]
# ステップ3: OpenAI Assistantを作成
assistant = client.beta.assistants.create(
name="Data Analysis Assistant",
model="gpt-4",
tools=openai_tools
)
# ステップ4: 会話スレッド開始
thread = client.beta.threads.create()
# ステップ5: タスク実行
messages = [
"過去30日間の売上データを取得して、グラフを作成してください"
]
for user_message in messages:
client.beta.threads.messages.create(
thread_id=thread.id,
role="user",
content=user_message
)
# 実行とツール呼び出しループ
run = client.beta.threads.runs.create(
thread_id=thread.id,
assistant_id=assistant.id
)
import time
while True:
run = client.beta.threads.runs.retrieve(
thread_id=thread.id,
run_id=run.id
)
if run.status == "completed":
break
elif run.status == "requires_action":
# ツール呼び出し処理
tool_calls = run.required_action.submit_tool_outputs.tool_calls
tool_outputs = []
for tool_call in tool_calls:
# MCPサーバーにツール呼び出しを委譲
tool_result = requests.post(
f"http://localhost:3001/tools/{tool_call.function.name}/call",
json=json.loads(tool_call.function.arguments)
).json()
tool_outputs.append({
"tool_call_id": tool_call.id,
"output": json.dumps(tool_result)
})
run = client.beta.threads.runs.submit_tool_outputs(
thread_id=thread.id,
run_id=run.id,
tool_outputs=tool_outputs
)
time.sleep(1)
MCPの標準化による今後の展開
2026年のAIコーディング環境での役割
MCPは単なる技術仕様ではなく、業界全体での「ツール連携の民主化」を推し進めています。
- エコシステムの統一: 複数のLLMプラットフォーム間でのツール資産の再利用が容易に
- ベストプラクティスの共有: パイプレイヤーアーキテクチャなど、設計パターンの業界標準化
- 開発効率の向上: 同じツール連携ロジックを複数プロジェクトで流用可能
今から準備すべきこと
MCPを組織に導入する際は、以下の準備が効果的です:
- 既存ツール連携の棚卸し: 現在使用している各種API・ツールをリスト化
- MCP対応の優先順位付け: ビジネスインパクトが大きい順に対応予定を立てる
- チーム教育: パイプレイヤーアーキテクチャの考え方をエンジニアチーム全体で共有
つまずきやすいポイントと解決策
問題1: MCPサーバーの認証設定でエラーが出る
現象: MCPサーバーに接続時に「401 Unauthorized」が返される
原因: 環境変数の設定漏れ、またはトークン形式の誤り
解決方法:
# 環境変数を確認
echo $MCP_API_TOKEN
# 設定が空の場合、以下を実行
export MCP_API_TOKEN="your-actual-token"
# Claude Codeを再起動
ps aux | grep claude-code | grep -v grep | awk '{print $2}' | xargs kill
claude-code --config claude-config.json
問題2: ChatGPT APIでツール呼び出しが実行されない
現象: OpenAI Assistantが「requires_action」ステータスに進まない
原因: toolsパラメータが正しい形式でないか、モデルがツール対応していない
解決方法:
# 正しい形式で定義
tools = [
{
"type": "function", # 絶対必須
"function": {
"name": "tool_name",
"description": "説明文",
"parameters": {
"type": "object",
"properties": {...},
"required": [...]
}
}
}
]
# モデルを gpt-4 以降に指定
assistant = client.beta.assistants.create(
model="gpt-4", # gpt-3.5-turbo は未対応
tools=tools
)
問題3: MCPサーバー上のツール定義と実装が不一致
現象: LLMはツール呼び出しを試みるが、実行時にエラー
原因: inputSchemaと実装の関数シグネチャがズレている
解決方法: スキーマ検証テストを実装
// mcp-server.js
app.post('/tools/:name/call', async (req, res) => {
const tool = tools[req.params.name];
const inputSchema = tool.inputSchema;
// JSONスキーマ検証
const Ajv = require('ajv');
const ajv = new Ajv();
const validate = ajv.compile(inputSchema);
if (!validate(req.body)) {
return res.status(400).json({
error: "Invalid input",
details: validate.errors
});
}
// 以降の処理...
});
まとめ
Model Context Protocolは、Claude Code、ChatGPT API、その他のLLMプラットフォーム間での「ツール連携の標準化」を実現する技術です。2026年時点では、実務レベルでの導入が急速に進んでいます。
MCPを効果的に活用するポイント:
- パイプレイヤーアーキテクチャを理解する: LLMの指示に頼るのではなく、設計時点で制御を組み込む
- エージェントと知識ベースを分離する: 構造的にエラーを防ぐ
- 標準仕様に従う: 複数LLM間での資産再利用を実現
これらを実践することで、スケーラブルで堅牢なAIエージェントシステムを構築できます。
あわせて読みたい
- Claude CodeでMCPサーバー連携【2026年版】設定方法とPythonカスタムサーバー実装
- PythonでMCPサーバーを作る完全ガイド【2026年版・本番運用コード付き】
- Claude Code CLAUDE.md完全ガイド【2026年版】プロジェクト制約の設定・フォーマット・ベストプラクティス