第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_searchmemo_
粒度 りゅうど 道具1つがカバーする仕事の大きさ。細かすぎるとAIが選べない
initialize イニシャライズ/初期化 接続の最初に行うやりとり。バージョンと機能を確認し合う
バージョン交渉 クライアントとサーバーが、共通で話せる仕様の版を決めること
タイムアウト 応答を待つ制限時間。超えると打ち切られる
mcp.log Claude Desktop のMCP接続全般のログ
mcp-server-SERVERNAME.log サーバーごとのログ。stderr の内容が入る

➡️ 次へ

この章で扱ったのは、全部「うまくいったあとに来る問題」でした。動かないから困るのではなく、動いて、増えて、混ざるから困る

そしてここまで来ると、最初の問いに戻れます。なぜ、わざわざ規格なのか。

規格には、この章で見たようなコストがあります。名前がぶつかる。バージョンに縛られる。直したら全部に響く。それでもなお、規格には払う価値がある——その理由を、最後にゆっくり考えます。

第13章 規格であることの意味(読み物) は、コードの出てこない読み物です。USBやHTTPが世界に何をしたのか。MCPは何を変えつつあるのか。煽らず、冷静にまとめます。

最後に、この章の一行だけ持って帰ってください。 道具は、足すより減らすほうが難しい。 足すのは設定ファイル5行、減らすのは「これは要らない」という判断です。判断のほうが、いつだって高くつきます。

関連ページ