第12章 現実に起きる問題 — サーバーが増えたら
📖 MCPサーバーを作って学ぶ AIに道具を持たせる入門 — はじめに・目次 ← 目次に戻る ここまでは サーバー1つの世界でした。この章は、あなたが実際にMCPを使いはじめてから必ずぶつかる問題を、先回りして扱います。コードより設計と運用の話です。
📱 Claude ではこう見える 🟢
第5章から作ってきたメモサーバーが動くようになると、次にこう思うはずです。
「じゃあ、GitHub のも繋ごう。ファイル操作のも入れよう。あ、天気のもまだ残ってるな」
そうやって3つ4つと繋いだ Claude Desktop は、こんな見え方に変わります。
- 起動してから使えるようになるまで、少し待たされる
- コネクタの一覧にサーバーがずらりと並ぶ
- ツールの一覧が画面に収まらない
- そして——「メモを検索して」と頼んだのに、別のサーバーの道具が呼ばれる
最後のやつが、いちばん気持ち悪い症状です。壊れてはいません。エラーも出ません。ただ、思ったのと違うことが起きる。
MCP は、そもそも複数のサーバーを組み合わせて使うことを前提にした規格です。たとえば「旅行の予定を立てる」なら、旅程を管理するサーバー、天気を取るサーバー、カレンダーを見るサーバー——と、役割ごとに分かれたサーバーが並ぶのが自然な姿になります。つまりこれは異常事態ではなく、うまくいった先に必ず来る景色です。
🤔 なぜ?/やらないとどうなる 🟢
これは「規格が成功したこと」の副作用です
第1章で、規格があると N×M問題が消える、という話をしました。道具を1回作れば、どのAIからでも使える。素晴らしい。
でも、その裏返しがこれです。
繋ぐのが簡単になると、人は繋ぎすぎる。
昔なら、AIに道具を足すのは大仕事でした。だから慎重に選んだ。いまは設定ファイルに5行足すだけです。だから考えずに足せてしまう。
サボるとどうなるか
複数サーバーの設計を何も考えないと、こうなります。
| 症状 | 見え方 |
|---|---|
| 道具が多すぎる | AIが間違った道具を選ぶ、またはどれも選ばない |
| 名前がぶつかる | どちらが呼ばれているのか人間にも分からない |
| 起動が重い | Claude を開いてからしばらく使えない |
| 1つが落ちている | 落ちたことに気づかないまま「AIが今日はバカ」と思う |
とくに最後が厄介です。MCPは静かに壊れます。 サーバーが1つ死んでも、Claude は「その道具が無い状態」で普通に会話を続けてしまいます。
🛠 こう作る 🟢
6つの問題を、順番に潰していきます。
① サーバーが増える 🟢
設定ファイルは、mcpServers の中に名前をキーにして並べるだけです。第2章で1つだけ書いたところに、兄弟を足していきます。
{
"mcpServers": {
"memo": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/memo/build/index.js"],
"env": { "NOTES_DIR": "/ABSOLUTE/PATH/TO/notes" }
},
"weather": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/weather/build/index.js"]
},
"filesystem": {
"command": "npx",
"args": [
"-y",
"@modelcontextprotocol/server-filesystem",
"/ABSOLUTE/PATH/TO/Desktop"
]
}
}
}
1行ずつ見ます。
"memo""weather""filesystem"… あなたが付けるサーバーの名前です。ホストの画面に出るのはこの名前です- カンマ区切りで並べるだけ。上下の順番に意味はありません
- ルールは1つ目のときと同じ。絶対パス、環境変数は
env、変更したら完全再起動
そして、ここからが本題です。このJSONに1つ足すたびに、以下の②〜⑥が全部あなたに降ってきます。
💡 足す前に一度だけ考えてください。 「これは今日使う道具か?」。“いつか使うかも”で足したサーバーは、たいてい使われないまま、AIの判断だけを鈍らせます。
② ツール名がぶつかる 🟢
2つのサーバーが、両方 search という名前のツールを持っていたら、どうなるでしょう。
まず仕様の事実をはっきりさせます。MCPの仕様書では、ツールの name は「そのツールを一意に識別する名前」と定義されています。しかしこれは1つのサーバーが返すツール一覧の中での話です。複数のサーバーをまたいだ名前の衝突をどう解決するかは、仕様では決められていません。
つまり——
衝突したときにどうなるかは、繋ぐホスト(Claude Desktop や、あなたが第10章で作ったクライアント)の実装しだいです。
ホストによっては、サーバー名を付けて区別してくれます。片方を無視するかもしれません。そこに期待しないのが正解です。あなたがサーバー側で最初からぶつからない名前を付ける。これがいちばん確実です。
命名の指針(3つだけ)
1. 目的語を必ず入れる。動詞だけで終わらせない
| ✗ 危ない | ○ 安全 |
|---|---|
search |
search_notes |
read |
read_note |
write |
write_note |
list |
list_repositories |
search という名前は、世界中の誰もが付けたがる名前です。だから必ずぶつかります。
💡 気づきましたか。この教材のツールは最初からこの形でした(第5章の
search_notes、第6章のread_note/write_note)。あれは偶然ではありません。
2. 迷ったら、サーバー名を接頭辞にする
memo_search memo_read のように、自分のサーバー名を頭に付けるやり方です。確実にぶつからなくなります。
ただし、副作用が1つあります。名前が長くなり、AIから見た意味が薄まることです。memo_search より search_notes のほうが、AIには「何をする道具か」が伝わります。
| 方針 | 向いている場面 |
|---|---|
具体的な名前(search_notes) |
自分専用のサーバー。読んで意味が分かるのが最優先 |
サーバー名で接頭辞(memo_search) |
汎用的な名前しか付けられないとき/社内で配って多数のサーバーと混ざるとき |
3. 名前は、あとから変えにくいと覚悟する
ツール名を変えると、その名前を前提にしていたもの(あなたのクライアント、書き置いた手順、他人の設定)が全部影響を受けます。最初の30秒の命名が、あとの何時間かを決めます。
③ ツールが多すぎてAIが選べない 🟢
ここは正直に書きます。「ツールが◯個を超えると精度が◯%落ちる」といった数字は、この教材では出しません。 MCPの仕様書にそんな規定はありませんし、モデルによっても違うからです。
そのうえで、経験則としては、次のことが広く言われています(筆者の実感でもあります)。
ツールの数が数十個になると、AIの道具選びは目に見えて雑になる。
理由は考えれば当然です。AIが見ているのはツールの名前と説明文の一覧です(第1章)。それが50行あれば、人間だって読み飛ばします。しかも一覧そのものが毎回の会話に同梱されるので、長いほど本題に使える余地が減ります。
対処は3つあります。
対処1:減らす
いちばん効きます。そして、いちばんやりたくないやつです。使っていないサーバーは設定から外す。以上です。
対処2:粒度を上げる(細かい道具5つより、まとまった道具1つ)
初心者がやりがちなのが、関数の数だけツールを作ることです。
✗ 細かすぎる:
list_note_files … ファイル名を一覧する
open_note … 開く
read_note_body … 中身を読む
close_note … 閉じる
search_note_index … 索引を引く
○ まとまっている:
search_notes … 検索して、ファイル名と抜粋を返す
read_note … 1ファイルの全文を返す
左側はプログラムの都合の分け方です。AIから見ると「5つの中から正しい順番で選ぶ」という追加の宿題でしかありません。
道具の粒度は、人間の頼みごと1つに合わせます。「メモを探して」に対して1回で答えが返るなら、それが正しい粒度です。
💡 判断基準: その道具は、AIが単独で意味のある結果を返せますか? 「別の道具を先に呼ばないと使えない道具」は、たいてい分けすぎです。
対処3:用途ごとにサーバーを分け、必要なものだけ繋ぐ
「仕事用」「調べもの用」「メモ用」でサーバーを分けておき、その日いらないものは設定から外す(あるいはホストの画面でオフにする)。MCPの仕様も、どのツールがAIに見えているのかをユーザーにはっきり示すべき(SHOULD)、という考え方を取っています。裏で何が繋がっているか分からない状態にしない、ということです。Claude Desktop にもコネクタの管理画面があります。
1つの巨大サーバーに全部入れないのは、こういうときに効いてきます。
④ 説明文の競合 🟢
道具の数を減らしても、まだ残る問題があります。似た説明の道具が2つあるときです。
search_notes … 「メモを検索します」
search_files … 「ファイルを検索します」
あなたには違いが分かります。でもAIには分かりません。「議事録どこだっけ」と言われたとき、どっちを呼ぶべきか、この2行からは決められないのです。
直し方は、説明文に「いつ使うか」を書くことです。
search_notes … 「ユーザー自身が書いた .md のメモを全文検索する。
個人の記録・日誌・議事録メモを探すときはこちら」
search_files … 「デスクトップ配下のファイルをファイル名で探す。
メモの中身ではなく、ダウンロードした資料や画像を探すときに使う」
ポイントは3つです。
- 何をするか(検索する)だけでなく、対象(.mdのメモ/デスクトップのファイル)を書く
- どういう頼まれ方のときに使うかを、そのまま日本語で書く
- 紛らわしい相手がいるなら、「〜ではなく」と書いてしまう
引数の .describe() も同じです。第2章で見た get_alerts の “Two-letter state code” を思い出してください。あの1行があるかないかで、AIの振る舞いは変わります。
💡 通奏低音:AIが読むのは説明文だけ。 サーバーが増えるほど、この事実の重みが増します。1つのときは雑な説明でも動きました。3つになると、雑な説明は事故になります。
⑤ 起動が遅い・落ちる 🟢
起動が遅い
stdio のサーバーは、ホストが起動するたびに、全部まとめて立ち上がります(第1章)。5個繋いでいれば、5個のプロセスが同時に起動します。
だから、起動時に重い処理をしないのが鉄則です。
- ✗ 起動時に、メモを全部読んで索引を作る
- ✗ 起動時に、外部APIへ接続しにいく
- ○ 起動時は名乗るだけ。重い処理は、そのツールが呼ばれたときにやる
MCPの仕様では、接続の最初に initialize(初期化)というやりとりをして、バージョンと機能を確認し合うことになっています。ここが返ってこないと、その先へ進めません。また仕様は、リクエストにはタイムアウト(時間切れ)を設けるべきだとしています。つまり——待たせすぎるサーバーは、切られます。
🔧 どうしても重い準備が要るなら、起動時ではなく初回呼び出し時に一度だけやる(結果を変数に取っておく)形にします。2回目以降は速くなります。
落ちたときにどう気づくか
第4章に戻ります。Claude Desktop のログは、サーバーごとに分かれています。
mcp.log… MCP接続全般のログ。接続に失敗した記録はここmcp-server-SERVERNAME.log… そのサーバーが stderr に出した内容(SERVERNAMEは設定ファイルに書いた名前)
置き場所はこうでした。
- macOS:
~/Library/Logs/Claude - Windows:
%APPDATA%\Claude\logs
# macOS:全部まとめて追いかける
tail -n 20 -F ~/Library/Logs/Claude/mcp*.log
サーバーごとにファイルが分かれている——これが、複数サーバー時代の救いです。「どれが落ちたか」はここを見れば一発で分かります。
だからこそ、こう作っておいてください。
console.error("Memo MCP Server running on stdio");
第5章から書いていたこの1行が、「このサーバーは生きて起動した」という証拠になります。5個繋いでいて4個しかこの行が出ていなければ、残り1個が犯人です。
⚠️ 繰り返します。
console.logは絶対に使わない(第3章)。サーバーが増えても、この鉄則は変わりません。むしろ、どのサーバーが壊しているのか分かりにくくなる分、罪が重くなります。
⑥ バージョンと互換性 🔧
最後に、規格であることのコストの話をします。
第1章では、規格の良さをこう説明しました。「道具は1回作るだけ。どのAIからでも使える」。これを裏返すと、こうなります。
サーバーを1か所直すと、繋いでいる全部に影響する。
あなたのメモサーバーは、いま Claude Desktop からも、第11章で作った自作アプリからも使われています。ここで search_notes の引数名を query から keyword に変えたら——両方が同時に壊れます。
気をつける点は3つです。
1. 名前と引数は「公開したAPI」だと思う
一度どこかに繋いだら、それはもうあなただけのものではありません。変えるなら、繋ぎ先を全部把握してから。
2. プロトコルのバージョンは、接続時に交渉される
MCPの仕様では、initialize のときにクライアントが自分の対応バージョンを送り、サーバーが応答する、という手順が決められています。サーバーが同じバージョンに対応していれば同じものを返し、対応していなければ自分が対応する別のバージョンを返します。それをクライアントが対応していなければ、接続を切るべきとされています。
ここで大事なのは、あなたが手で管理する部分ではないということです。バージョン交渉は SDK がやってくれます。あなたの仕事は、SDK を古いまま放置しないことです。
3. MCPは、まだ動きの速い規格
仕様は日付でバージョンが付いています(例:2025-11-25)。トランスポートについても、古い方式が非推奨になった経緯があります(第8章)。「去年動いた書き方が、今年のベストとは限らない」——これがMCPの現在地です。
SDKを上げる → 手元で MCP Inspector(npx @modelcontextprotocol/inspector)で動作確認 → それからホストに繋ぐ。 この順番を守れば、たいていの事故は防げます。
⚠️ ハマりどころ 🟢
①「動かない」の原因が、設定ファイルのカンマ
サーバーを2つ目に足すとき、いちばん多い事故がこれです。
{
"mcpServers": {
"memo": { "command": "node", "args": ["..."] } ← ここのカンマを忘れる
"weather": { "command": "node", "args": ["..."] }
}
}
JSONが壊れると、1つだけでなく全部のサーバーが消えます。 「天気を足したらメモまで動かなくなった」ときは、まずJSONの書式を疑ってください(付録C)。
②「1つ落ちている」ことに気づかない
ホストは、落ちたサーバーについてあなたに強く教えてはくれません。会話は普通に続きます。だから——
「あれ、いつもならメモを見てくれるのに」と思ったら、AIを疑う前にログを見る。
これが複数サーバー時代の作法です。
③ 同じデータに、2つの道具から触れるようにしてしまう
メモフォルダを、自作のメモサーバーからも、ファイルシステム系のサーバーからも触れるようにしてある——という状態は、意外とよく起きます。
第9章でメモサーバーに入れた封じ込め(NOTES_DIR の外は拒否する)は、もう1つの道具からは効きません。安全対策は、道具ごとにやる必要があります。裏口を自分で開けていないか、たまに設定を見直してください。
④ ツール名を変えて、自作クライアントを壊す
第10章・第11章で作ったクライアントは、search_notes という名前で呼び出しています。サーバー側の名前を変えたら、そちらも直す。これは規格を使う側の宿命です。
⑤ 「全部入りサーバー」を作ってしまう
1つのサーバーにツールを20個入れると、外したいときに外せません。用途で分けておけば、設定ファイルの1ブロックを消すだけで切り離せます。分けておくのは、あとで減らすためです。
🤖 AIに頼むなら 🟢
ここは、この章でいちばん実務的な注意です。
AIに「MCPサーバーを作って」と丸投げすると、道具を作りすぎます。
これは筆者の経験則ですが、かなり再現します。「メモを管理するMCPサーバーを作って」と頼むと、AIは親切心を発揮して、list_notes create_note update_note delete_note search_notes get_note_metadata archive_note…… と、CRUDを几帳面に並べた10個のツールを返してきがちです。
AIは「網羅的であること」を良いことだと思っています。あなたが黙っていれば、必ず多いほうに倒れます。 そして皮肉なことに、その多すぎるツール一覧を読まされるのは、AI自身です。
だから、こう頼んでください。
「ツールは3つまで。増やす提案はしなくていい」 「動詞だけの名前(
searchなど)は禁止。目的語を必ず入れて」 「各ツールの説明文には、“どういうときに使うか”を1文入れて」 「起動時には重い処理をしないで。初期化は最小限に」
そして、できあがったものを見るときの目線はこれです。
- そのツール、今日使いますか?
- そのツール、単独で意味のある結果を返せますか?
- その説明文、似た名前の別の道具と区別できますか?
削るのは、あなたの仕事です。 AIは足すのが得意で、減らすのは苦手です(そう頼まれない限り)。
💡 第1章でも書いたとおり、MCPは動きの速い分野です。「公式ドキュメント(modelcontextprotocol.io)の最新の書き方で」と添えるのも忘れずに。
📗 ことばメモ
| ことば | よみ | 意味 |
|---|---|---|
| 名前空間 | なまえくうかん | 名前がぶつからないように区切りを作る考え方。MCPでは接頭辞で代用する |
| 接頭辞 | せっとうじ | 名前の頭に付ける目印(例:memo_search の memo_) |
| 粒度 | りゅうど | 道具1つがカバーする仕事の大きさ。細かすぎるとAIが選べない |
| initialize | イニシャライズ/初期化 | 接続の最初に行うやりとり。バージョンと機能を確認し合う |
| バージョン交渉 | — | クライアントとサーバーが、共通で話せる仕様の版を決めること |
| タイムアウト | — | 応答を待つ制限時間。超えると打ち切られる |
| mcp.log | — | Claude Desktop のMCP接続全般のログ |
| mcp-server-SERVERNAME.log | — | サーバーごとのログ。stderr の内容が入る |
➡️ 次へ
この章で扱ったのは、全部「うまくいったあとに来る問題」でした。動かないから困るのではなく、動いて、増えて、混ざるから困る。
そしてここまで来ると、最初の問いに戻れます。なぜ、わざわざ規格なのか。
規格には、この章で見たようなコストがあります。名前がぶつかる。バージョンに縛られる。直したら全部に響く。それでもなお、規格には払う価値がある——その理由を、最後にゆっくり考えます。
第13章 規格であることの意味(読み物) は、コードの出てこない読み物です。USBやHTTPが世界に何をしたのか。MCPは何を変えつつあるのか。煽らず、冷静にまとめます。
最後に、この章の一行だけ持って帰ってください。 道具は、足すより減らすほうが難しい。 足すのは設定ファイル5行、減らすのは「これは要らない」という判断です。判断のほうが、いつだって高くつきます。
関連ページ
- MCPサーバーを作って学ぶ AIに道具を持たせる入門 — はじめに・目次 — 目次
- 第4章 デバッグの作法 — 見えない通信を覗く — 落ちたときに戻ってくる場所
- 第5章 自分の道具を作りはじめる — メモを検索する — 説明文で呼ばれ方が変わる話
- 第9章 安全 — 書ける道具は、危ない道具 — 封じ込めは道具ごとに要る
- 第11章 自作ChatGPTクローンに繋ぐ — 名前を変えると壊れる相手
- 付録C 設定ファイルの場所とトラブル — JSONの書式ミス
- 自作CLIエージェントで学ぶ AIエージェント開発入門 — はじめに・目次 — 第3弾。道具の設計はこちらも