Claude Media
プラグインに同梱されたMCPサーバーの仕組みとツール名の付け方

プラグインに同梱されたMCPサーバーの仕組みとツール名の付け方

プラグインが同梱するMCPサーバーは、プラグインを有効にすると自動で起動し、ツール名にプラグイン名とサーバー名を含めて登録されます。設定形式と起動・切断のタイミングを扱います。

プラグインに同梱されたMCPサーバーはどこに定義するか

プラグインはツールや外部サービスとの連携を提供するMCPサーバーを同梱できます。定義場所は2通りで、プラグインルートの.mcp.jsonか、plugin.jsonへのインライン記述です。書式は手動で追加するMCPサーバーの設定と同じで、プラグイン同梱のMCPサーバーはユーザーが手動設定したサーバーと機能的に同一に動きます。

.mcp.jsonに書く場合の例です(プラグインルートの.mcp.json)。

{
  "mcpServers": {
    "database-tools": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
      "env": {
        "DB_URL": "${DB_URL}"
      }
    }
  }
}

plugin.jsonにインラインで書くこともできます。小さなプラグインで設定ファイルを1つに集約したいときに向いています。

{
  "name": "my-plugin",
  "mcpServers": {
    "plugin-api": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/api-server",
      "args": ["--port", "8080"]
    }
  }
}

プラグインを有効にすると何が起きるか

プラグインを有効にすると、Claude Codeはそのプラグインが同梱するMCPサーバーを自動で起動します。追加や削除は/mcpコマンドでは行わず、プラグイン自体をインストール・アンインストールすることで行います。ただし、インストール済みのプラグインが持つサーバーを一時的に止めたいだけなら、/mcpパネルからそのサーバーだけをオフに切り替えられます。プラグインを削除せずに接続だけを止める操作です。

/mcpパネルでプラグイン同梱のサーバーをオフに切り替えると、Claude Codeはその選択をプロジェクトごとに~/.claude.jsondisabledMcpServersリストへ記録します。このリストは、手動設定サーバー・プラグインサーバー・claude.aiコネクタ・既定でオンの組み込みサーバーをまとめて扱う「オプトアウト」用のリストで、既定でオフの組み込みサーバー(computer-useなど)を有効化するenabledMcpServersとは別物です。Claude Codeはサーバーごとにどちらか一方のリストだけを参照するので、プラグインサーバーを誤ってenabledMcpServersに書いても無視されます。

セッション起動時は有効なプラグインのサーバーがまとめて接続されますが、リモート(HTTP・SSE)サーバーで以前使ったことがあるものはcachedステータスで表示され、実際の接続はClaudeが最初にそのサーバーのツールを呼び出すタイミングまで遅延します。

セッションの途中でプラグインを有効・無効にした場合は、/reload-pluginsを実行してMCPサーバーの接続・切断を反映させます。再読み込み時、設定が変わっていないプラグインサーバーの接続はそのまま維持されます。Claude Code v2.1.246以降では、/cdでセッションのディレクトリを移動すると、移動先のディレクトリで有効なプラグインのサーバーが自動で接続され、無効になったプラグインのサーバーは自動で切断されるため、移動のたびに/reload-pluginsを手動で叩く必要がありません。MCPサーバー全般の管理コマンドclaude mcp add / removeなど別系統で、プラグイン同梱のサーバーはそちらでは操作できない点も押さえておくと混乱しません。Webセッションでは、まだ接続していないプラグインサーバーへの呼び出しが発生すると、その場でサーバーを起動して接続を待つ動きになります。

ツール名にはプラグイン名とサーバー名が入る

プラグイン同梱のMCPサーバーが提供するツールの呼び出し名には、プラグイン名とサーバー名の両方が含まれます。形式は次のとおりです。

mcp__plugin_<plugin-name>_<server-name>__<tool-name>

A-Za-z0-9_-以外の文字はすべて_に置き換わります。my-pluginというプラグインに同梱されたdatabase-toolsサーバーのqueryツールなら、呼び出し名は次のようになります。

mcp__plugin_my-plugin_database-tools__query

この完全な名前は、MCPの権限ルール・Skillのallowed-tools・サブエージェントのtoolsフィールド・hookのマッチャーで参照するときに使います。サーバー自体はplugin:<plugin-name>:<server-name>というスコープ付きの名前で登録されるため、mcp_toolフックのserverフィールドのようにサーバー名を渡す箇所ではこちらを使います。素のサーバー名(database-toolsだけ)を書いたhookマッチャーは、プラグイン同梱サーバーに対しては一度も発火しません。

パスプレースホルダーとユーザー環境変数

プラグイン同梱のMCPサーバー設定では、3つのパスプレースホルダーが使えます。${CLAUDE_PLUGIN_ROOT}はプラグインのインストールディレクトリ、${CLAUDE_PLUGIN_DATA}は永続データディレクトリ、${CLAUDE_PROJECT_DIR}は安定したプロジェクトルートに解決されます。置換の対象はサーバーの種類ごとに異なります。stdioサーバーはcommandargsenv、HTTP・SSE・WebSocketサーバーはurlheadersheadersHelperです。プラグイン同梱のMCPサーバーは、手動設定のサーバーと同じユーザー環境変数へアクセスでき、stdio・SSE・HTTP・WebSocketの4つの通信方式にも対応します。

プラグインサーバーは/mcpパネル上で、プラグイン由来であることを示すインジケーター付きで表示されます。

1つのプラグインに複数のMCPサーバーを同梱することもできます。データベース用とAPI用でサーバーを分けたい場合、mcpServersオブジェクトに並べて書くだけです(複数サーバーを同梱する.mcp.jsonの例)。

{
  "mcpServers": {
    "plugin-database": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
      "env": { "DB_PATH": "${CLAUDE_PLUGIN_ROOT}/data" }
    },
    "plugin-api-client": {
      "command": "npx",
      "args": ["@company/mcp-server", "--plugin-mode"]
    }
  }
}

ユーザーに入力させる値はuserConfigで宣言する

${DB_URL}のような環境変数参照は、値そのものを別の場所で用意しておく前提です。APIトークンやAPIエンドポイントのように、プラグインを有効にした人ごとに違う値を入力してもらいたいときは、plugin.jsonuserConfigフィールドを使います。宣言した項目は、プラグインを有効にするタイミングでClaude Codeが入力ダイアログを出して尋ねます(plugin.jsonuserConfigの例)。

{
  "userConfig": {
    "api_endpoint": {
      "type": "string",
      "title": "API endpoint",
      "description": "チームのAPIエンドポイント"
    },
    "api_token": {
      "type": "string",
      "title": "API token",
      "description": "API認証トークン",
      "sensitive": true
    }
  }
}

宣言した値は${user_config.KEY}として、MCPサーバー設定・LSPサーバー設定・hookコマンドに埋め込めます(sensitiveでない値ならSkillやサブエージェントの内容にも埋め込めます)。sensitive: trueを付けた値は入力時にマスクされ、settings.jsonではなくmacOSのKeychainか~/.claude/.credentials.jsonに保存されます。

ただしheadersHelperだけは例外です。シェル経由で実行されるフィールドは${user_config.*}の埋め込みを拒否するため、headersHelperは設定値をコード側で読むスクリプトとして書き、${user_config.KEY}を直接埋め込むことはできません。これは、設定値をそのままシェルコマンドへ埋め込むと、値の中身次第でシェルが任意のコマンドを実行できてしまうためです。

/reload-pluginsにはトークンコストがある

セッション途中でプラグインを有効・無効にしたあとの/reload-pluginsは、無料の操作ではありません。再読み込みで新しく読み込まれたコンポーネントは、会話に追記されるコンテンツとして自己申告されますが、それまでの会話履歴はプロンプトキャッシュから読まれ続けます。ここでMCPサーバーを提供するプラグインが絡むと、コストがさらに増えることがあります。tool search(数千ツールをオンデマンドで読み込む仕組み)でツールの読み込みが遅延されていない場合、プラグインの有効・無効の変更はキャッシュそのものを無効化し、次のリクエストで会話履歴全体を読み直すことになります。プロンプトキャッシュを無効化するほどの再読み込みになる場合、/reload-pluginsは警告を出していったん止まり、--forceを付けて再実行するまで進みません。

同梱するMCPサーバーの数が多いプラグインを頻繁にオン・オフする運用では、この再読み込みコストが積み重なる点を踏まえておくと、セッションのトークン消費を読みやすくなります。

プラグイン作者が踏みやすい落とし穴

予約済みのサーバー名と衝突する: Claude Codeはworkspaceclaude-in-chromecomputer-useClaude PreviewClaude Browserを組み込みサーバー用に予約しています。プラグインが同梱するMCPサーバーにこれらと同じ名前を付けると、Claude Codeは読み込み時にそのサーバーをスキップし、名前の変更を促す警告を出します。サーバー名は組み込みサーバーと衝突しない固有の名前にします。

headersHelperのプレースホルダー展開はバージョン依存: ${CLAUDE_PLUGIN_ROOT}などのパスプレースホルダーはheadersHelperの値にも展開されますが、これはClaude Code v2.1.195以降の挙動です。それより前のバージョンでは、headersHelperだけプレースホルダーがリテラル文字列のまま渡っていました。古いバージョンのユーザーがいる可能性があるプラグインでは、この差を考慮した動作確認をしておくと安全です。社内配布のプラグインでも、利用者全員が最新版のClaude Codeへ揃っているとは限らない点は見落としやすいところです。

ユーザー設定のMCPサーバーと何が違うか

機能面ではプラグイン同梱のMCPサーバーとユーザーが手動で追加したMCPサーバーに違いはありません。違うのはライフサイクルの持ち主です。手動設定のサーバーはclaude mcp add / claude mcp removeであなたが直接管理しますが、プラグイン同梱のサーバーはプラグインの有効・無効に連動して自動的に接続・切断されます。チームで同じMCPサーバーを配布したい場合、個々のメンバーにclaude mcp addのコマンドを配るよりも、サーバーをプラグインに同梱してマーケットプレイス経由で配布するほうが、設定の食い違いが起きにくいと言えます。誰か1人が接続情報を書き換えるたびに全員へ再共有する運用から抜け出せる点も、実務上の利点です。

まとめ

プラグイン同梱のMCPサーバーは、プラグインルートの.mcp.jsonplugin.jsonのインラインで定義し、プラグインを有効にすると自動で起動します。ツール名はmcp__plugin_<plugin-name>_<server-name>__<tool-name>の形式でプラグイン名とサーバー名の両方を含み、サーバー自体はplugin:<plugin-name>:<server-name>として登録されます。セッション途中の有効・無効切り替えは/reload-pluginsで反映し、Claude Code v2.1.246以降は/cdでのディレクトリ移動にも自動で追随します。チームでMCPサーバーを配布する場面では、個別のサーバー追加コマンドより配布・更新の手間が小さくなります。

この記事を共有:XはてブLinkedIn