Claude Codeの仕組み講座(講師のためのエンジニア水準)
区分5 自分で作る(エンジニア水準)★★MCP(Model Context Protocol)は、AIアプリと外の道具をつなぐための約束事です。登場人物は No.11 と同じ3者です。ホストは Claude Code 本体、クライアントはホストの中にある接続用の部品、サーバーは道具を出す側のプログラムです。この単元で作るのは、サーバーです。
たとえるなら、サーバーは取引先の専用窓口です。窓口は「見積もりを出して」「在庫を調べて」のような決まった依頼だけを受け付け、AIは窓口の依頼票の書き方を見て、必要な時に依頼を出します。
サーバーが出せるものは、公式の説明で3種類あります。
この単元で作るのは、いちばん使う道具1つだけです。
サーバーとホストのやり取りには、大きく2つの方法があります。
| 方法 | どう動くか | 向いている物 |
|---|---|---|
| stdio(標準入出力) | Claude Code が、自分のMac上でサーバーのプログラムを子プロセス(別のプログラムから起動された小さなプログラム)として起動し、文字のやり取りで会話する | 自分のMac上だけで使う小さな道具 |
| HTTP | ネット上のURLにあるサーバーに接続する | 離れた場所に置いて、複数人で使う物 |
この単元では、いちばん手軽な stdio で作ります。stdio では、Claude Code がサーバーを起動し、プログラムの出入り口(標準入力と標準出力)で文字をやり取りします。この性質が、第1章の大事な注意につながります。
作るのは「2つの整数を足す道具」です。道具としては地味ですが、サーバーの作りは本物と同じです。流れは6つです。
準備は、公式のチュートリアルにならって、ターミナル(命令を文字で打つ画面)で次のように行います。
uv init hello
cd hello
uv add "mcp[cli]"
uv は Python の部品とその置き場(仮想環境)をまとめて管理する道具で、入っていない時はAIに頼めば用意してくれます。uv init hello は hello フォルダを作り、見本の main.py を置きます。uv add は、そのフォルダの中に .venv(このフォルダ専用の Python と部品の置き場)を作って、mcp を入れます。つまり hello/.venv/bin/python は、mcp が入った専用の Python です。
サーバーのコードは、同じ hello フォルダの中に server.py という名前で新しく作ります。main.py は使いません(消してもそのままでも構いません)。
公式チュートリアルの形に沿った、最小のサーバーです。mcp 2.3.0・Python 3.11 の手元の Mac で動かして確かめました。
from mcp.server import MCPServer
mcp = MCPServer("hello")
@mcp.tool()
def add(a: int, b: int) -> int:
"""2つの整数を足して返す。"""
return a + b
if __name__ == "__main__":
mcp.run(transport="stdio")
読み方は3か所です。
MCPServer("hello"):サーバーを作り、名前を付ける。この名前が、AIから見える道具の名前の一部になる@mcp.tool() の付いた関数:これが道具1つ。関数の名前・引数の型(int)・説明文("""...""")から、依頼票の書式が自動で作られる(公式:型ヒントと説明文から道具の定義を自動生成する)。引数とは、道具に渡す値のことmcp.run(transport="stdio"):stdio で待ち受ける説明文は、AIが「この道具をいつ使うか」を判断する主な手がかりになります。道具の名前や引数の形と並んで、AIが読む材料です。人間向けのコメントではなく、AI向けの仕様書として書きます。
コードを書くのはAIに任せてよい。頼み方の例:「MCPサーバーを Python で作って。公式チュートリアルの形で、道具は『2つの整数を足す add』1つだけ。stdio で動かす。入れた mcp のバージョンの公式の書き方に合わせて、1行ずつ何をしているか説明して」
○ 深追いしない 公式チュートリアルは、Python のSDKが 2.0.0 以上であることを前提に書かれています。クラス名や書き方は版で変わるので、古い解説記事のコードがそのまま動かないことがあります。AIには「入れた版の公式の例に合わせて」と頼みます
○ TypeScript で作る場合の公式の部品は @modelcontextprotocol/server です(公式チュートリアルに別の手順があります)
stdio では、標準出力(プログラムが文字を出す出口)が、JSON-RPC というメッセージ形式のやり取りの通り道になっています。JSON は、機械が読み書きしやすい決まった書式の文字列です。通り道に関係ない文字が混ざると、受け取る側が読めなくなって壊れうる、というのが公式の根拠です。
print() は標準出力に書くので使わない。ログは標準エラーに書く logging を使うconsole.log() も同じで、console.error() を使う窓口の電話線に、関係ない独り言を流してはいけない、という約束です。
○ 手元の確認:わざと print() を入れたサーバーを、最新のSDK(mcp 2.3.0)で動かしたところ、Claude Code にも Inspector にもつながり、道具の呼び出しも成功しました。壊れなかったのはこの版の作りによるもので、公式が禁止している書き方であることは変わりません。他の版や言語、つなぎ方では壊れる可能性があるので、動いたからと破っていい約束ではありません
○ 画面に出したい確認は、標準エラーに出す。AIに作らせる時に「ログは標準エラーへ」と頼む
Claude Code につなぐ前に、サーバーだけを単体で確かめます。MCP Inspector は、MCPの公式の確認用道具で、npx(Node.js の部品を、入れずに1回だけ動かす命令)で起動できます。次の命令は、hello フォルダの中で打ちます。
npx @modelcontextprotocol/inspector --cli ./.venv/bin/python server.py --method tools/list
./.venv/bin/python は、第1章で uv add が作った専用の Python です。./ は「今いるフォルダの中」の意味です。これで add という道具と、その引数(a と b、どちらも整数)の書式が返りました。「AIから見えているサーバーの中身」です。
道具を実際に呼ぶ確認も、同じ道具でできます。
npx @modelcontextprotocol/inspector --cli ./.venv/bin/python server.py \
--method tools/call --tool-name add --tool-arg a=2 --tool-arg b=3
結果の中に "text": "5" が返れば、道具は正しく動いています。--cli を付けずに起動すると、ブラウザで操作できる画面版になります。ここで動かなければ、Claude Code につないでも動きません。単体で確かめておくと、サーバーの故障か、AIとの連携の故障かを分けられます。
つなぐ命令は、公式で次の形です。
claude mcp add --transport stdio hello -- /絶対パス/.venv/bin/python /絶対パス/server.py
hello は、あとで見分けるための名前-- の左は Claude Code への指定、右はサーバーを起動する命令そのもの(公式:-- より後ろはそのままサーバーに渡される)/Users/… のようにフォルダの一番上から全部書いたパス)で書く。相対パスは、どこで起動するかで指す場所が変わってしまうため。hello フォルダの中で pwd(今いるフォルダの絶対パスを表示する命令)を打つと調べられるどこに設定を残すかを、範囲(有効にする範囲。公式の呼び名は「スコープ」)で選べます。
| 範囲 | 効く範囲 | 保存先 |
|---|---|---|
| local(標準) | 今の作業場だけ。自分だけ | ~/.claude.json |
| project | 今の作業場。チームで共有 | 作業場の .mcp.json |
| user | 自分の全部の作業場 | ~/.claude.json |
まず local で試して、動いたら必要に応じて広げるのが安全です。つないだ後の確認は、命令かアプリ内の画面で行います。
claude mcp list # 全部のサーバーとつながり具合
claude mcp get hello # 1つのサーバーの詳細
claude mcp remove hello # 外す
アプリ内では /mcp で、サーバーごとの接続状態と道具の数が見えます(公式)。
手元では、本物の設定を触らないよう、環境変数(命令に渡す設定値)の CLAUDE_CONFIG_DIR に一時フォルダを指定して試しました。設定の保存先がその一時フォルダに変わるので、試し終わったらフォルダごと消せます。claude mcp add のあと claude mcp list で ✔ Connected(つながった)と出て、claude mcp get でスコープ・種類・起動命令が表示されました。
AIから見ると、サーバーの道具は mcp__サーバー名__道具名 という名前になります。今回なら mcp__hello__add です。
claude -p "helloサーバーのadd道具で 2 と 3 を足して、答えだけ言って" \
--mcp-config m.json --strict-mcp-config \
--allowedTools "mcp__hello__add" --output-format json
--mcp-config m.json:サーバーの設定を書いたファイルを渡す(claude mcp add を使わず、この実行だけで有効にする方法)--strict-mcp-config:渡したサーバーだけを使う(ほかの設定を無視する)--allowedTools "mcp__hello__add":この道具だけ、聞かずに使ってよいと先に許可する(No.16)結果の result が 5 で返りました。AIがサーバーに依頼票を出し、答えが戻り、AIがそれを使って返事をした。この一連の流れが実物で確かめられたことになります。
m.json の中身は、公式の .mcp.json と同じ形です。
{
"mcpServers": {
"hello": {
"command": "/絶対パス/.venv/bin/python",
"args": ["/絶対パス/server.py"]
}
}
}
どこが悪いかを、外側から順に切ります。
| 順番 | 見る物 | 分かること |
|---|---|---|
| 1 | claude mcp list / claude mcp get 名前 |
つながっているか。つながらない時は、get に原因の行(HTTPの番号やエラー)が出る(公式) |
| 2 | /mcp(アプリ内) |
接続状態・道具の数・認証が必要かどうか |
| 3 | Inspector(単体で動かす) | サーバーそのものが正しく道具を返せるか |
| 4 | claude --debug-file ログの場所 |
Claude Code 側の詳しいログ(公式のオプション) |
1と2で問題がなければ、サーバーはつながっています。道具が呼ばれない時は、道具の説明文が、AIにとって「いつ使うか」の手がかりになっているかを疑います。
公式の環境変数で、次のような上限が決まっています。数字は2026年10月時点の公式です。
| 環境変数 | 何のための上限か |
|---|---|
MCP_TIMEOUT |
サーバーの起動を待つ時間(ミリ秒)。例:MCP_TIMEOUT=10000 claude |
MCP_TOOL_TIMEOUT |
道具1回の実行にかけられる時間 |
MAX_MCP_OUTPUT_TOKENS |
道具の結果の最大の大きさ(標準は25,000トークン。トークンはAIが文章を数える単位) |
結果が大きすぎる道具は、AIの作業机(コンテキスト)を圧迫します(No.05)。道具が返す結果は、必要な部分に絞って返すのが、サーバーを作る側の腕の見せどころです。
コードはAIが書きます。あなたが判断するのは、次の4つです。
claude mcp add の --env で渡せる、公式)道具の許可・サーバーの設定・説明文が効く強さの順番は、機能ごとに違います。機能ごとの比較は No.15 にあります。
○ 受講生によく聞かれる質問 1:「MCPサーバーを作るのに、プログラミングは必須ですか?」
答え方:書くのはAIに任せられます。ただし「何を道具にするか」「説明文」「許可」は人が決める所です。公式の最小の例は、型と説明文付きの関数1つなので、読める量です
○ 受講生によく聞かれる質問 2:「stdio と HTTP、どちらで作るべき?」
答え方:自分のMac上で、自分だけが使う物は stdio が手軽です。離れた場所に置いて複数人で使うなら HTTP です(第0章②)
○ 受講生によく聞かれる質問 3:「作ったのに、AIが道具を使ってくれません」
答え方:まず claude mcp list でつながりを見て、次に Inspector でサーバーが道具を返しているか確かめます。両方問題なければ、説明文が手がかりとして足りているかを見直します
○ 関係する単元:No.11 MCP/No.13 許可/No.15 設定の強さ/No.16 -p と SDK
MCPサーバー = 道具を貸し出す窓口。型付きの関数1つで作れる。stdio では標準出力に関係ない文字を書かない。単体(Inspector)で確かめてから、claude mcp add でつなぎ、mcp__名前__道具名 で呼ばせる。
問1 自作のMCPサーバー(stdio)を作りました。ログを見たくて、サーバーのコードに print() で状況を書き足そうとしています。本文の約束から、どう扱うのが正しい?
問2 claude mcp add でつないだのに、AIが道具を使いません。最初にやる順番として合うのは?
問3 hello という名前のサーバーに、add という道具があります。AIから見える道具の名前は?
問4 道具の説明文("""..."""の部分)は、何のために書く?
出典:Claude Code 公式ドキュメント「Connect Claude Code to tools via MCP」(https://code.claude.com/docs/en/mcp)「CLI reference」(https://code.claude.com/docs/en/cli-reference)、Model Context Protocol 公式「Build an MCP server」(https://modelcontextprotocol.io/docs/develop/build-server)「stdio」(https://modelcontextprotocol.io/specification/2026-07-28/basic/transports/stdio)「MCP Inspector」(https://modelcontextprotocol.io/docs/tools/inspector)/手元のMacで、Python の最小サーバーを作り、Inspector(tools/list・tools/call)、claude mcp add / list / get / remove、claude -p --mcp-config での呼び出しを実際に動かして確認(2026-10-13)