MCPが変えるAI開発
2024年11月、Anthropicが発表したMCP(Model Context Protocol)は、AIソフトウェア開発の風景を変えました。2026年現在、MCPはAI-ツール統合の標準的なアプローチになっています。
MCPとは何か?USB比喩で理解する
MCPを理解するなら、USBの比喩が分かりやすいです:
物理世界の例:
- USB標準の前:デバイスごとに専用ケーブル
- USB標準の後:1つのUSBケーブルで全デバイス対応
AIの世界のMCP:
- MCP前:Claude用、ChatGPT用、Gemini用に異なるAPI設計
- MCP後:1つのMCPサーバーで全てのAIに対応可能
MCPは言語モデルと外部ツール・データソースを接続するための標準化インターフェースです。
MCPの3コンポーネント・アーキテクチャ
┌─────────────────────────────────────────┐
│ Host(ホスト) │
│ Claude / ChatGPT / Claude Code など │
└──────────────┬──────────────────────────────┘
│ (MCP通信)
┌──────────────▼──────────────────────────────┐
│ Client(クライアント) │
│ MCPクライアントライブラリ │
│ リクエスト送信・レスポンス処理 │
└──────────────┬──────────────────────────────┘
│ (標準化された通信)
┌──────────────▼──────────────────────────────┐
│ Server(サーバー) │
│ └─ ツール実装 (Tool Definition) │
│ └─ リソース実装 (Resource Definition) │
│ └─ プロンプト実装 (Prompt Definition) │
└─────────────────────────────────────────┘
MCP の3つの主要機能
1. Tools:AIが実行できるアクション
# MCP Tool Example: Webから情報を取得
@mcp.tool()
def fetch_weather(city: str, date: str = "today") -> dict:
"""
指定された都市の天気情報を取得します。
Args:
city: 都市名(例:東京)
date: 日付(デフォルト:今日)
Returns:
天気情報の辞書
"""
# 実装
return {
"city": city,
"date": date,
"temperature": 22,
"condition": "晴れ",
"humidity": 65
}
# Claude が自動的に以下を実行可能:
# user: 「東京の今日の天気を教えて」
# → Claude が自動的に fetch_weather("東京", "today") を呼び出し
# → Claude が結果を解釈して回答
2. Resources:AIがアクセスできるデータ
# MCP Resource Example: 社内ナレッジベースへのアクセス
@mcp.resource()
def get_company_policies() -> str:
"""
企業ポリシードキュメント全体をリソースとして提供
"""
return """
===== 企業ポリシー 2026 =====
1. 報告体制
- バグは即座に報告
- セキュリティ問題は24時間以内
2. 開発スタンダード
- テストカバレッジ80%以上
- コードレビュー必須
3. デプロイプロセス
- ステージング環境で検証
- 本番デプロイは金曜除外
"""
@mcp.resource(uri_template="/knowledge-base/{category}/{article_id}")
def get_knowledge_article(category: str, article_id: str) -> str:
"""
カテゴリ別に知識ベース記事を取得(パラメータ付きリソース)
"""
# データベースから記事を取得
return db.query(f"SELECT content FROM articles WHERE category = {category}")
# Claude が以下を実行可能:
# user: 「デプロイの注意点を教えて」
# → Claude が自動的に get_company_policies() リソースにアクセス
# → ドキュメント内の「デプロイプロセス」セクションを参照して回答
3. Prompts:AIへの指示テンプレート
# MCP Prompt Example: 定型化された指示
@mcp.prompt(name="code_review")
def code_review_prompt(code: str, language: str = "python") -> str:
"""
コードレビュー用の標準化されたプロンプト
Args:
code: レビュー対象のコード
language: プログラミング言語
"""
return f"""
You are an expert {language} code reviewer.
Review the following code for:
1. Security vulnerabilities
2. Performance issues
3. Code style compliance
4. Type safety
5. Test coverage
Code to review:
```{language}
{code}
```
Provide specific, actionable feedback.
"""
@mcp.prompt(name="bug_analysis")
def bug_analysis_prompt(error_message: str, stack_trace: str, context: str) -> str:
"""
バグ分析用の標準化されたプロンプト
"""
return f"""
分析対象エラー:
{error_message}
スタックトレース:
{stack_trace}
コンテキスト:
{context}
以下を分析してください:
1. エラーの根本原因
2. なぜこのエラーが発生したのか
3. 解決方法(実装例付き)
4. 今後の予防策
"""
# Claude が以下を実行可能:
# user: 「このエラーを分析して」+ エラーメッセージ
# → Claude が自動的に bug_analysis_prompt を適用
# → 標準化された分析フォーマットで回答
実装:Python でMCPサーバーを構築
FastMCP:最簡単な実装方法
2026年の推奨方法はFastMCPです。Flask/FastAPI なしに、シンプルなデコレータで実装できます。
import os
import subprocess
from fastmcp import FastMCP
# MCPサーバーの初期化
app = FastMCP("my-git-server")
# Tool 1: Git コマンドの実行
@app.tool()
def run_git_command(command: str, repo_path: str = ".") -> str:
"""
指定されたGitコマンドを実行し、結果を返します
Args:
command: 実行するGitコマンド(例:'log --oneline -5')
repo_path: リポジトリパス
"""
try:
result = subprocess.run(
f"git -C {repo_path} {command}",
shell=True,
capture_output=True,
text=True,
timeout=10
)
if result.returncode != 0:
return f"エラー: {result.stderr}"
return result.stdout
except subprocess.TimeoutExpired:
return "エラー: コマンド実行がタイムアウト"
except Exception as e:
return f"エラー: {str(e)}"
# Tool 2: ファイル差分の取得
@app.tool()
def get_git_diff(file_path: str, repo_path: str = ".") -> str:
"""
指定されたファイルの変更差分を表示します
"""
return run_git_command(f"diff {file_path}", repo_path)
# Tool 3: 最新のコミット情報を取得
@app.tool()
def get_latest_commit(repo_path: str = ".", num_commits: int = 5) -> str:
"""
最新のコミット情報を取得します
Args:
repo_path: リポジトリパス
num_commits: 取得するコミット数
"""
command = f"log --oneline -n {num_commits}"
return run_git_command(command, repo_path)
# Resource: リポジトリの統計情報
@app.resource()
def repo_stats(repo_path: str = ".") -> str:
"""
リポジトリの統計情報を表示します
"""
stats_info = f"""
Repository Statistics
====================
総コミット数:
{run_git_command('rev-list --count HEAD', repo_path)}
総ファイル数:
{run_git_command('ls-files | wc -l', repo_path)}
最新のブランチ:
{run_git_command('branch -a', repo_path)}
"""
return stats_info
# Prompt: コミットメッセージの作成支援
@app.prompt(name="commit_message_helper")
def commit_message_prompt(changes_summary: str) -> str:
"""
コミットメッセージ作成の支援
"""
return f"""
以下の変更内容から、良質なコミットメッセージを作成してください。
変更内容:
{changes_summary}
コミットメッセージの要件:
1. 1行目は50字以内の要約(命令形)
2. 2行目は空行
3. 3行目以降は詳細説明(72字行折り返し)
4. 日本語で記述
例:
機能: ユーザー認証機能の追加
OAuth 2.0を使用したGoogleアカウント連携を実装した。
ユーザーはGoogleアカウントで直接ログイン可能になった。
"""
if __name__ == "__main__":
# MCPサーバーをスタート
app.run()
TypeScriptでの実装
import Anthropic from "@anthropic-ai/sdk";
// MCP Client の初期化
const client = new Anthropic({
mcp: {
servers: {
filesystem: {
command: "node",
args: ["./mcp-servers/filesystem.js"]
},
github: {
command: "node",
args: ["./mcp-servers/github.js"]
},
database: {
command: "node",
args: ["./mcp-servers/database.js"]
}
}
}
});
// MCPサーバーの定義例(GitHub連携)
const githubMCPServer = `
const express = require('express');
const { MCPServer } = require('mcp');
const { Octokit } = require('octokit');
const app = MCPServer.create("github-mcp");
const octokit = new Octokit({
auth: process.env.GITHUB_TOKEN
});
// Tool: プルリクエスト一覧を取得
app.tool('get_pull_requests', {
description: 'リポジトリのプルリクエスト一覧を取得',
inputSchema: {
type: 'object',
properties: {
owner: { type: 'string', description: 'リポジトリオーナー' },
repo: { type: 'string', description: 'リポジトリ名' },
state: { type: 'string', enum: ['open', 'closed', 'all'], default: 'open' }
},
required: ['owner', 'repo']
}
}, async (params) => {
const prs = await octokit.rest.pulls.list({
owner: params.owner,
repo: params.repo,
state: params.state
});
return {
pull_requests: prs.data.map(pr => ({
number: pr.number,
title: pr.title,
author: pr.user.login,
created_at: pr.created_at,
url: pr.html_url
}))
};
});
// Tool: イシューを作成
app.tool('create_issue', {
description: 'リポジトリにイシューを作成',
inputSchema: {
type: 'object',
properties: {
owner: { type: 'string' },
repo: { type: 'string' },
title: { type: 'string' },
body: { type: 'string' },
labels: { type: 'array', items: { type: 'string' } }
},
required: ['owner', 'repo', 'title']
}
}, async (params) => {
const issue = await octokit.rest.issues.create({
owner: params.owner,
repo: params.repo,
title: params.title,
body: params.body,
labels: params.labels
});
return {
issue_number: issue.data.number,
url: issue.data.html_url
};
});
app.start();
`;
Claude Desktop での MCP 設定
2026年現在、Claude Desktop は MCP を完全ネイティブサポートしています。
設定手順
// ~/.claude_desktop_config.json
{
"mcpServers": {
"filesystem": {
"command": "uvx",
"args": ["mcp-server-filesystem"]
},
"postgresql": {
"command": "node",
"args": ["/path/to/postgresql-mcp-server.js"],
"env": {
"DATABASE_URL": "postgresql://user:pass@localhost/mydb"
}
},
"slack": {
"command": "node",
"args": ["/path/to/slack-mcp-server.js"],
"env": {
"SLACK_BOT_TOKEN": "xoxb-..."
}
},
"notion": {
"command": "uvx",
"args": ["mcp-server-notion"],
"env": {
"NOTION_API_KEY": "secret_..."
}
}
}
}
再起動後、Claude は自動的にこれらのMCPサーバーに接続します。
実践的ユースケース:複雑な統合例
ユースケース:CI/CDパイプラインの自動デバッグ
# MCP サーバー:CI/CDとGitHubと監視ツールを統合
from fastmcp import FastMCP
import requests
import json
app = FastMCP("ci-cd-debug-server")
# Tool 1: GitHub Actions のログを取得
@app.tool()
def get_github_action_logs(
owner: str,
repo: str,
run_id: int,
job_name: str = None
) -> str:
"""
GitHub Actions の実行ログを取得します
"""
headers = {
"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}",
"Accept": "application/vnd.github.v3+json"
}
# ジョブ一覧を取得
jobs_url = f"https://api.github.com/repos/{owner}/{repo}/actions/runs/{run_id}/jobs"
jobs_response = requests.get(jobs_url, headers=headers)
if job_name:
# 特定のジョブのみ取得
jobs = [j for j in jobs_response.json()["jobs"] if j["name"] == job_name]
else:
jobs = jobs_response.json()["jobs"]
logs = []
for job in jobs:
log_url = job["logs_url"]
log_response = requests.get(log_url, headers=headers)
logs.append({
"job_name": job["name"],
"status": job["status"],
"conclusion": job["conclusion"],
"logs": log_response.text[:5000] # 最初の5000文字
})
return json.dumps(logs, indent=2, ensure_ascii=False)
# Tool 2: ログからエラーを自動抽出
@app.tool()
def extract_errors_from_logs(logs_text: str) -> list:
"""
ログテキストから重要なエラーを抽出します
"""
error_patterns = [
"ERROR", "FATAL", "Exception", "Failed", "失敗",
"Traceback", "FAILED", "STDERR"
]
errors = []
lines = logs_text.split("\n")
for i, line in enumerate(lines):
if any(pattern in line for pattern in error_patterns):
# コンテキスト(前後5行)を含めて抽出
start = max(0, i - 2)
end = min(len(lines), i + 3)
context = "\n".join(lines[start:end])
errors.append({
"line_number": i,
"error_line": line,
"context": context
})
return errors[:10] # 最大10個まで
# Tool 3: 過去のビルド履歴を検索
@app.tool()
def search_build_history(
owner: str,
repo: str,
keyword: str,
limit: int = 5
) -> str:
"""
過去のビルド履歴からキーワードを含むものを検索
"""
headers = {
"Authorization": f"Bearer {os.getenv('GITHUB_TOKEN')}",
"Accept": "application/vnd.github.v3+json"
}
url = f"https://api.github.com/repos/{owner}/{repo}/actions/runs"
params = {"per_page": 50}
response = requests.get(url, headers=headers, params=params)
runs = response.json()["workflow_runs"]
matching_runs = []
for run in runs[:limit]:
if keyword.lower() in run["name"].lower():
matching_runs.append({
"id": run["id"],
"name": run["name"],
"conclusion": run["conclusion"],
"created_at": run["created_at"],
"run_number": run["run_number"]
})
return json.dumps(matching_runs, indent=2, ensure_ascii=False)
# Resource: 社内のトラブルシューティングガイド
@app.resource()
def troubleshooting_guide() -> str:
"""
よくあるCI/CDエラーとその解決方法
"""
return """
===== CI/CDトラブルシューティングガイド =====
1. Out of Memory エラー
症状: FATAL: out of memory
原因: テストが多すぎる、またはメモリリーク
解決: テストを分割実行、またはNode容量を増加
2. タイムアウトエラー
症状: Command timed out
原因: 処理が遅い、またはハング
解決: タイムアウト時間を増やす、または処理を最適化
3. ネットワークエラー
症状: Connection refused
原因: 外部サービスが落ちている
解決: リトライ設定を追加、またはモック化
"""
# Prompt: トラブル診断の支援
@app.prompt(name="ci_troubleshooting")
def ci_troubleshooting_prompt(
error_message: str,
job_logs: str,
recent_changes: str
) -> str:
"""
CI/CDトラブルの自動診断
"""
return f"""
CI/CDパイプラインのトラブル診断をしてください。
エラーメッセージ:
{error_message}
ジョブログ(最後の500行):
{job_logs[-500:]}
最近の変更:
{recent_changes}
トラブルシューティングガイドも参照してください。
診断項目:
1. エラーの根本原因は何か
2. このエラーは過去に発生したか(検索結果から)
3. 最近の変更が原因か
4. 即座に実行すべきアクション
5. 長期的な修正方法
"""
if __name__ == "__main__":
app.run()
Claude Desktop から以下のように使用:
ユーザー: 「GitHub Actions のビルドが失敗しました。
repo: my-app, run_id: 123456789
このエラーを分析してください」
↓ Claude が自動実行:
1. get_github_action_logs() → ログを取得
2. extract_errors_from_logs() → エラー抽出
3. search_build_history() → 過去パターン検索
4. ci_troubleshooting_prompt() → 診断実行
↓ 結果例:
「エラーの根本原因:
メインブランチへのマージで、
バージョン管理の競合が発生しています。
即座のアクション:
1. package.json の競合マーク部分を手動解決
2. npm ci で再インストール
3. ビルド再実行
過去履歴:
このパターンは2週間前にも発生しており、
その時は同様の競合が原因でした。」
MCP サーバー生態系:2026年版利用可能ツール一覧
| ツール | 公式 | 用途 | サポート状況 |
|---|---|---|---|
| Filesystem | ○ Anthropic | ファイルアクセス | 本番対応 |
| PostgreSQL | ○ Anthropic | DB操作 | 本番対応 |
| Git | ○ Anthropic | Git操作 | 本番対応 |
| GitHub | ○ Anthropic | GitHub API | 本番対応 |
| Slack | ○ Anthropic | Slack統合 | 本番対応 |
| Google Drive | ○ Anthropic | Google Drive アクセス | 本番対応 |
| Notion | ○ Anthropic | Notion API | 本番対応 |
| Jira | ○ Anthropic | Jira操作 | 本番対応 |
| AWS | 🔄 コミュニティ | AWS操作 | ベータ |
| Datadog | 🔄 コミュニティ | ログ分析 | ベータ |
| Docker | 🔄 コミュニティ | コンテナ操作 | 開発中 |
セキュリティ・ベストプラクティス
1. 認証情報の管理
import os
from dotenv import load_dotenv
# × 危険:ハードコード
GITHUB_TOKEN = "ghp_xxxxxxxxxxxx"
# ○ 安全:環境変数から読込
load_dotenv()
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
if not GITHUB_TOKEN:
raise ValueError("GITHUB_TOKEN が設定されていません")
# さらに安全:Azure Key Vault / AWS Secrets Manager
from azure.identity import DefaultAzureCredential
from azure.keyvault.secrets import SecretClient
def get_secret(secret_name: str) -> str:
credential = DefaultAzureCredential()
client = SecretClient(
vault_url=os.getenv("AZURE_VAULT_URL"),
credential=credential
)
return client.get_secret(secret_name).value
2. スコープ制限(最小権限の原則)
# × 危険:全権限を付与
GITHUB_TOKEN_SCOPES = ["repo", "admin"]
# ○ 安全:必要な権限のみ
GITHUB_TOKEN_SCOPES = [
"repo:read", # リポジトリ読取のみ
"issues:read", # イシュー読取のみ
"pull_requests:read" # PR読取のみ
]
3. レート制限の実装
from ratelimit import limits, sleep_and_retry
import time
# 1時間あたり60リクエストに制限
@sleep_and_retry
@limits(calls=60, period=3600)
@app.tool()
def rate_limited_tool(param: str) -> str:
"""
レート制限が適用されたツール
"""
pass
# またはキャッシング戦略
from functools import lru_cache
@lru_cache(maxsize=128)
@app.tool()
def cached_tool(param: str) -> str:
"""
結果をキャッシュして、API呼び出しを削減
"""
pass
4. エラーハンドリングとログ
import logging
from typing import Optional
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
@app.tool()
def secure_operation(param: str) -> dict:
"""
セキュアなエラーハンドリング付きツール
"""
try:
# 操作実行
result = perform_operation(param)
logger.info(f"Operation succeeded: {param}")
return result
except ValueError as e:
# 入力値エラー
logger.warning(f"Invalid input: {str(e)}")
return {"error": "Invalid input", "details": str(e)}
except PermissionError as e:
# 権限なし
logger.error(f"Permission denied: {str(e)}")
return {"error": "Permission denied"}
except Exception as e:
# 予期しないエラー
logger.critical(f"Unexpected error: {str(e)}", exc_info=True)
return {"error": "Internal error"}
デバッグ・トラブルシューティング
MCPサーバーのログ出力
# Claude Desktop のログを確認
tail -f ~/.claude/logs/debug.log
# または詳細デバッグモード
CLAUDE_DEBUG=1 /Applications/Claude.app/Contents/MacOS/Claude
一般的なエラーと解決方法
エラー1: "MCP server failed to start"
原因: サーバーコマンドが見つからない
解決: ~/.claude_desktop_config.json のパスを確認
エラー2: "Tool execution timeout"
原因: ツールが時間がかかりすぎている
解決: 非同期処理を実装、またはタイムアウト時間を増やす
エラー3: "Authentication failed"
原因: トークンが無効またはスコープ不足
解決: トークンを再生成、スコープを確認
まとめ
MCPの標準化により、2026年はAI開発のアプローチが大きく変わりました。以前は各LLM企業が異なるAPIを用いていましたが、現在はMCP標準で対応可能に。ツール統合も数週間から数時間に短縮されました。ベンダーロックインのリスクも低減しています。
実装時のチェックリスト:
- Claude Desktop の設定で3つ以上のMCPサーバーを統合
- 社内ツール用のMCPサーバーを1つ実装(Python or TypeScript)
- 本番環境での認証・レート制限を実装
- ログ・監視機能を設定
- チームで「使用禁止API」を明確化
MCPはUSBのようなシンプルさがありながら、その底には無限の可能性があります。AIアプリケーションに導入する価値があるプロトコルです。
参考リソース
- MCP Official Spec: https://modelcontextprotocol.io
- Claude Desktop Setup: https://claude.ai/docs
- FastMCP: https://github.com/anthropics/fastmcp
- MCP Server Gallery: https://github.com/modelcontextprotocol/servers