🦔

Claude Desktop で始める MCP (Model Context Protocol) 入門

に公開

1. はじめに

ClaudeやCursor、ClineなどのAI開発支援ツールで注目を集めている「MCP(Model Context Protocol)」。これは、AIにツールを持たせるための標準プロトコルで、いわば"AI用USB-Cポート"のようなもの。これを使えば、AIがファイル操作、API呼び出し、DB問い合わせ、ブラウザ操作など、さまざまな機能を外部ツールとして活用できるようになります。

この記事では、Claude for Desktop(Freeプラン)を使って、MCPを実際に動かしてみた記録と、MCPクライアントの自作方法まで丁寧に紹介していきます。


2. MCPとは?

正式名称:Model Context Protocol(モデル・コンテキスト・プロトコル)
開発元:Anthropic社

MCPは、AIモデルが外部のツールやデータソースに安全かつ標準化された方法でアクセスするためのオープンプロトコルです。USB-Cがデバイス接続の標準であるように、MCPはAIとツールの接続標準となることを目指しています。

利用例(一部)

カテゴリ 機能例
ファイル操作 ローカルファイルの読み書き
DBアクセス Postgres, SQLite
Web操作 Puppeteerによるスクレイピング
チャット連携 Slack, Discord
クラウド制御 AWS, Docker, Kubernetes

3. Claude for Desktop での設定

必要なもの

  • Claude for Desktop(WindowsまたはMac)
  • Node.js(npxコマンドが使えること)

手順概要

  1. Claudeの設定画面を開く(Ctrl + ,)
  2. "Developer > Edit Config"を選択し設定フォルダを開く
  3. claude_desktop_config.json を編集

設定例(Windows)

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "C:\\Users\\あなたのユーザー名\\Downloads\\mcp"
      ]
    }
  }
}

設定例(macOS)

{
  "mcpServers": {
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "/Users/あなたのユーザー名/Downloads/mcp"
      ]
    }
  }
}

設定ファイルを保存後、Claudeアプリを再起動すればMCPサーバーが起動されます。


4. MCPを使ってみる

テスト内容

Claudeに次のようなプロンプトを入力:

"Claudeの説明文を書いて、mcpフォルダ内にテキストファイルで保存して"

結果

  • ClaudeがMCP経由でローカルのmcpフォルダにテキストファイルを生成。
  • 中身にはClaudeの機能説明が記載されていた。

ファイル内容の一部:

Claudeは、Anthropic社が開発した高度なAIアシスタントです...

権限確認ダイアログが出る場合もありますが、許可すれば動作します。


5. 自作MCPクライアントの構築(Python)

ここからは「クライアント開発者向け」の情報です。ClaudeなどのLLMとMCPサーバーを連携させるためのチャットボットクライアントをPythonで構築します。

5-1. システム要件

  • MacまたはWindows
  • 最新のPython
  • uv パッケージマネージャ(pip install uv

5-2. 開発環境のセットアップ

uv init mcp-client
cd mcp-client
uv venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
uv add mcp anthropic python-dotenv
rm main.py
touch client.py

5-3. APIキーの準備

.env ファイルを作成して以下のように書き込みます:

ANTHROPIC_API_KEY=your-api-key-here

.gitignore.env を追加してセキュリティ確保:

echo ".env" >> .gitignore

5-4. クライアント実装の基本構造

import asyncio
from typing import Optional
from contextlib import AsyncExitStack
from mcp import ClientSession, StdioServerParameters
from mcp.client.stdio import stdio_client
from anthropic import Anthropic
from dotenv import load_dotenv
import sys

load_dotenv()

class MCPClient:
    def __init__(self):
        self.session: Optional[ClientSession] = None
        self.exit_stack = AsyncExitStack()
        self.anthropic = Anthropic()

5-5. サーバー接続処理

    async def connect_to_server(self, server_script_path: str):
        is_python = server_script_path.endswith('.py')
        is_js = server_script_path.endswith('.js')
        if not (is_python or is_js):
            raise ValueError("Server script must be a .py or .js file")

        command = "python" if is_python else "node"
        server_params = StdioServerParameters(
            command=command,
            args=[server_script_path],
            env=None
        )

        stdio_transport = await self.exit_stack.enter_async_context(stdio_client(server_params))
        self.stdio, self.write = stdio_transport
        self.session = await self.exit_stack.enter_async_context(ClientSession(self.stdio, self.write))

        await self.session.initialize()
        tools = (await self.session.list_tools()).tools
        print("Connected to server with tools:", [tool.name for tool in tools])

5-6. クエリ処理とツール呼び出し

    async def process_query(self, query: str) -> str:
        messages = [{"role": "user", "content": query}]
        tools = await self.session.list_tools()
        available_tools = [
            {"name": t.name, "description": t.description, "input_schema": t.inputSchema}
            for t in tools.tools
        ]

        response = self.anthropic.messages.create(
            model="claude-3-5-sonnet-20241022",
            max_tokens=1000,
            messages=messages,
            tools=available_tools
        )

        final_text = []
        assistant_message_content = []

        for content in response.content:
            if content.type == 'text':
                final_text.append(content.text)
                assistant_message_content.append(content)
            elif content.type == 'tool_use':
                result = await self.session.call_tool(content.name, content.input)
                final_text.append(f"[Calling tool {content.name} with args {content.input}]")

                messages += [
                    {"role": "assistant", "content": assistant_message_content},
                    {"role": "user", "content": [{"type": "tool_result", "tool_use_id": content.id, "content": result.content}]}
                ]

                response = self.anthropic.messages.create(
                    model="claude-3-5-sonnet-20241022",
                    max_tokens=1000,
                    messages=messages,
                    tools=available_tools
                )
                final_text.append(response.content[0].text)

        return "\n".join(final_text)

5-7. チャットループとメイン処理

    async def chat_loop(self):
        print("\nMCP Client Started! Type your queries or 'quit' to exit.")
        while True:
            query = input("\nQuery: ").strip()
            if query.lower() == 'quit': break
            try:
                print("\n" + await self.process_query(query))
            except Exception as e:
                print(f"\nError: {str(e)}")

    async def cleanup(self):
        await self.exit_stack.aclose()

async def main():
    if len(sys.argv) < 2:
        print("Usage: python client.py <path_to_server_script>")
        sys.exit(1)

    client = MCPClient()
    try:
        await client.connect_to_server(sys.argv[1])
        await client.chat_loop()
    finally:
        await client.cleanup()

if __name__ == "__main__":
    asyncio.run(main())

5-8. 実行例

uv run client.py ./server/weather.py  # Python製MCPサーバーを指定

5-9. よくあるエラーと対処法

  • FileNotFoundError: サーバースクリプトのパスを確認
  • Connection refused: サーバーが起動していない可能性
  • Tool execution failed: ツールの環境変数が不足している場合
  • Timeout: 初回実行時は最大30秒程度かかることがあります

6. VS Code + MCP連携も可能に!

VS Code Insider版では、設定画面からMCPサーバーを追加でき、GitHub Copilotのagent modeとも連携可能。

参考:
VS Code InsiderでMCPサーバー追加とCopilot agent mode活用 - Qiita


7. まとめ

Claude FreeプランでもMCPを通じて、AIにファイル操作などのツールを与えることが可能です。また、Pythonでクライアントを自作することで、独自のワークフローに合わせたAIチャットエージェントを構築できます。

今後さらに多くのツールがMCP対応していくことが予想され、AI×ツール連携の標準技術としての普及が期待されます。


📌 参考リンク

Discussion