1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Claude Codeで自作MCPサーバーを動かす — claude mcp addの1行登録から動作確認まで

1
Posted at

はじめに

Claude CodeのようなCLI型AIコーディングツールが普及し、自作ツールをAIに安全に渡したいニーズが高まっています。その標準規格がMCP (Model Context Protocol) です。本記事では、Pythonで書いた最小のMCPサーバーをClaude Codeに登録し、ツールを実際に呼び出せるところまでを確認します。

Claude Desktopへの接続手順は、前回の記事で解説しました。

Claude Codeの登録方法は、設定ファイルを手で編集する方式ではなく、登録はclaude mcp addコマンド1つで済む点が大きく異なります。本記事はその手順と、つまづきやすいポイントの整理です。

前提

  • Python 3.10以上
  • Python SDKは pip install "mcp[cli]" で導入します
  • Claude Code CLIがインストール済み

ディレクトリ構成は次のとおりです。

mcp-echo/
  src/server.py      (サーバー本体)
  .mcp.json          (共有設定、後述)

ステップ1: 最小のMCPサーバーを書く

動作確認用として、行リストを受け取って整形レポートを返すツールを1つだけ持つサーバーを作ります。ファイル名はsrc/server.pyとします。

#!/usr/bin/env python3
"""Claude Code接続確認用の最小MCPサーバー"""
import sys
import asyncio
import logging

from mcp.server import Server
from mcp.server.stdio import stdio_server
import mcp.types as types

# ログは必ずstderrへ出すこと
# stdoutはMCPの通信路なので汚さない
logging.basicConfig(
    level=logging.INFO,
    stream=sys.stderr,
    format="%(asctime)s - %(levelname)s - %(message)s",
)

server = Server("echo-utilities")

@server.list_tools()
async def list_tools() -> list[types.Tool]:
    return [
        types.Tool(
            name="format_report",
            description="タイトルと行リストから整形レポートを生成する",
            inputSchema={
                "type": "object",
                "properties": {
                    "title": {"type": "string", "description": "レポートの見出し"},
                    "rows": {"type": "array", "items": {"type": "string"}, "description": "本文行"},
                },
                "required": ["title", "rows"],
            },
        ),
    ]

ツール定義で大切なのは2点です。

  1. nameとdescriptionはLLMがツール選択に使う — 曖昧な説明だと、使うべき場面でClaudeがそのツールを選んでくれません
  2. inputSchemaはJSON Schemaとして正確に — ここが正確なほど、引数の渡し間違いが減ります

call_toolハンドラとエントリポイントを追加します。

@server.call_tool()
async def call_tool(name: str, arguments: dict):
    if name == "format_report":
        title = arguments["title"]
        rows = arguments["rows"]
        lines = ["## " + title, ""]
        lines += ["- " + r for r in rows]
        text = "\n".join(lines) + "\n"
        return [types.TextContent(type="text", text=text)]
    raise ValueError(f"Unknown tool: {name}")

async def main():
    async with stdio_server() as (read_stream, write_stream):
        await server.run(read_stream, write_stream)

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

MCPのstdioトランスポートは標準出力をJSON-RPCの通信路として使います。ログをstdoutに出すと通信が壊れるため、ログ出力は必ずstderrへ向けてください。

MCP Inspectorで動作確認

クライアントに渡す前に、まずMCP Inspectorで単体動作を確認できます。

mcp dev src/server.py

ブラウザでInspectorが起動するので、そのtoolsタブからformat_reportを実行してみてください。期待どおりのレポートが返れば、サーバー側の準備は完了です。

ステップ2: claude mcp add で登録する

登録コマンドは1行です。セパレータの--の後にサーバー起動コマンドを並べます。

cd mcp-echo
claude mcp add echo-utils -- python src/server.py

スコープは3種類あります。用途で使い分けます。

スコープ コマンド例 用途
local claude mcp add echo-utils -- python src/server.py 自分専用、このプロジェクト限定
project claude mcp add --scope project echo-utils -- python src/server.py .mcp.jsonに書き込まれ、チーム共有
user claude mcp add --scope user echo-utils -- python src/server.py マシン内の全プロジェクトで使用

登録結果は次のコマンドで確認します。

claude mcp list

一覧にecho-utilsが現れ、接続ステータスが正常なら成功です。セッション内では/mcpコマンドで、サーバーとツールの状態をいつでも確認できます。

ステップ3: .mcp.json でチーム共有する

projectスコープで登録すると、設定がプロジェクトルートの .mcp.json に書き込まれます。このファイルをGitにコミットすれば、チームの全員が同じMCPサーバーを使えます。

{
  "mcpServers": {
    "echo-utils": {
      "command": "python",
      "args": ["src/server.py"],
      "env": {}
    }
  }
}

形式はClaude Desktopの設定ファイルとほぼ同じです。初回読み込み時には「このプロジェクトのMCPサーバーを使用しますか」と承認を求められます。信頼できないリポジトリが勝手にサーバーを仕込むのを防ぐセーフガードなので、内容を確認してから承認してください。

ステップ4: セッションで実際に呼び出す

プロジェクトルートで claude を起動し、次のように依頼します。

src/sample_report.mdにレポートを保存してください。見出しは「週次進捗」、本文は3行です

初回呼び出し時には、パーミッション確認が出ます。「このセッションで許可」を選べば、以降は確認なしで動きます。ツールが呼ばれると標準入出力でMCPメッセージが往復し、整形されたレポートをファイルに書き込んでくれます。

つまづきポイントまとめ

最後に、私が実際に引っかかった点を整理します。

  • stdoutを汚す: ログ出力にprintを使うと、サーバーが応答しなくなります。ログはloggingでstderrへ出します
  • スコープの取り違え: localとprojectを混同すると、チームメンバーの環境だけサーバーが見えない事故になります。共有したいものは必ずprojectスコープで登録します
  • Windows環境のcommand: npxベースのサーバーではcmd /cのラッパーが必要なケースがあります。ただしPython製サーバーなら基本的に問題ありません
  • 承認プロンプトの見落とし: .mcp.jsonを読み込んだ直後は承認を求められます。承認するまでサーバーは無効のままです

どれも理解すれば単純ですが、初回は時間を溶かしがちです。この記事の手順に沿えば、登録から動作確認まで10分ほどで終わるはずです。


著者: 葉山悠希 — 書籍シリーズは Zenn / Amazon で公開中

1
0
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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?