1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MCP(Model Context Protocol)2026完全ガイド ─ AIとツールをつなぐ標準プロトコル実践入門

1
Last updated at Posted at 2026-02-13

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アプリケーションに導入する価値があるプロトコルです。

参考リソース

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?