プラグインに同梱されたMCPサーバーの仕組みとツール名の付け方
プラグインが同梱するMCPサーバーは、プラグインを有効にすると自動で起動し、ツール名にプラグイン名とサーバー名を含めて登録されます。設定形式と起動・切断のタイミングを扱います。
プラグインに同梱されたMCPサーバーはどこに定義するか
プラグインはツールや外部サービスとの連携を提供するMCPサーバーを同梱できます。定義場所は2通りで、プラグインルートの.mcp.jsonか、plugin.jsonへのインライン記述です。書式は手動で追加するMCPサーバーの設定と同じで、プラグイン同梱のMCPサーバーはユーザーが手動設定したサーバーと機能的に同一に動きます。同梱するサーバー自体の作り方はmcp-server-devプラグインの解説にあります。
.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.jsonのdisabledMcpServersリストへ記録します。このリストは、手動設定サーバー・プラグインサーバー・claude.aiコネクタ・既定でオンの組み込みサーバーをまとめて扱う「オプトアウト」用のリストで、既定でオフの組み込みサーバー(computer-useなど)を有効化するenabledMcpServersとは別物です。Claude Codeはサーバーごとにどちらか一方のリストだけを参照するので、プラグインサーバーを誤ってenabledMcpServersに書いても無視されます。
接続と切断のタイミングは、次の4つの場面で決まります。
プラグインのサーバーが接続・切断される場面
- 1
セッション起動時
有効なプラグインのサーバーがまとめて接続されます。使ったことのあるリモート(HTTP・SSE)サーバーは
/mcpでcachedと表示され、実際の接続はClaudeが最初にそのツールを呼ぶ時点です。 - 2
セッション途中で有効・無効を切り替えたとき
/reload-pluginsで接続・切断を反映します。設定が変わっていないサーバーの接続は、再読み込み後もそのまま残ります。 - 3
/cdでディレクトリを移したとき
Claude Code v2.1.246以降は、移動先で有効なプラグインのサーバーを自動で接続し、無効になったものを切断します。移動のたびに
/reload-pluginsを打つ必要はありません。 - 4
クラウドセッションで未接続のサーバーを呼んだとき
アイドル後に再開した直後などは、その場でサーバーを起動し、接続を待ってから呼び出しが進みます。
v2.1.260以降は、対話用の端末を持たないセッション(-p、Agent SDK、デスクトップアプリ)でも/reload-pluginsを実行できます。ただしMCPサーバーの接続・切断は行われず、変更が効くのは次のセッションからです。
MCPサーバー全般の管理コマンドのclaude mcp add / removeは、手動設定のサーバー用です。プラグイン同梱のサーバーには使いません。
ツール名にはプラグイン名とサーバー名が入る
プラグイン同梱のMCPサーバーが提供するツールの呼び出し名には、プラグイン名とサーバー名の両方が含まれます。形式は次のとおりです。
mcp__plugin_<plugin-name>_<server-name>__<tool-name>A-Z・a-z・0-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サーバーはcommand・args・env、HTTP・SSE・WebSocketサーバーはurl・headers・headersHelperです。プラグイン同梱の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.jsonのuserConfigフィールドを使います。宣言した項目は、プラグインを有効にするタイミングでClaude Codeが入力ダイアログを出して尋ねます(plugin.jsonのuserConfigの例)。
{
"userConfig": {
"api_endpoint": {
"type": "string",
"title": "API endpoint",
"description": "チームのAPIエンドポイント"
},
"api_token": {
"type": "string",
"title": "API token",
"description": "API認証トークン",
"sensitive": true
}
}
}必須の設定に保存済みの値がないと、同梱サーバーは起動しません。/pluginのErrorsタブにBundled MCP server "<name>" was not started: it needs configurationと出ます。値は/pluginのInstalledタブで該当プラグインを選び、Configureから入力します。シェルからは--config <server>.<key>=<value>でも渡せます(v2.1.285以降、プラグイン内に同梱したバンドルのみ)。
宣言した値は${user_config.KEY}として、MCPサーバー設定・LSPサーバー設定・hookコマンドに埋め込めます(sensitiveでない値ならSkillやサブエージェントの内容にも埋め込めます)。sensitive: trueを付けた値は入力時にマスクされ、settings.jsonではなくmacOSのKeychainに保存されます。Keychainが書き込みを拒んだ場合や、対応するキーチェーンのないプラットフォームでは~/.claude/.credentials.jsonに保存されます。
ただしheadersHelperだけは例外です。シェル経由で実行されるフィールドは${user_config.*}の埋め込みを拒否するため、headersHelperは設定値をコード側で読むスクリプトとして書き、${user_config.KEY}を直接埋め込むことはできません。シェルが値を解釈し直すため、埋め込むと値の中身次第で任意のコマンドが実行されうるからです。
/reload-pluginsにはトークンコストがある
スキル・コマンド・エージェント・hook・モニター・テーマだけのプラグインなら、有効・無効の切り替えでキャッシュは無効化されません。内容は既存の会話の後ろに追記されるだけです。MCPサーバーを持つプラグインは扱いが違い、MCPサーバーを接続・削除したときと同じルールに従います。
分かれ目はtool searchです。MCPツールの読み込みが遅延されている場合(対応モデルの既定)、Claude Codeは最初のリクエストで作ったツール一覧を会話の間ずっと保つので、途中でサーバーが増減してもキャッシュは崩れません。遅延されていない場合は、ツール定義が変わった時点でキャッシュが無効になり、次のリクエストで会話履歴全体を読み直します。
読み直しになる再読み込みは、Claude Codeが適用せずに止めます。/reload-pluginsは次のような行を出し、--forceを付けて再実行するまで進みません。
This reload changes MCP tools (<server>) — your next message will re-read the whole conversation instead of using the cache. Run /reload-plugins --force to apply.同梱サーバーの多いプラグインを頻繁にオン・オフするなら、トークン消費が上振れする場面があります。
公開前にclaude plugin validateで確かめる
claude plugin validateは、プラグインのマニフェストをローカルで検査します。.mcp.json・mcpServersが指す.json・インラインの各サーバーエントリも対象です(v2.1.281以降)。${user_config.*}の参照先が宣言されているかも見てくれます。userConfigを宣言せずに${user_config.api_token}を書いたplugin.jsonでは、claude plugin validateは次のエラーを返します(v2.1.289)。
claude plugin validate .✘ Found 1 error:
❯ mcpServers.database-tools.env.TOKEN: references ${user_config.api_token}, which plugin.json does not declare under "userConfig" (or in this server's "channels" entry), so on a fresh install it cannot resolve: the loader drops the server or passes the literal text through. Declare the option or fix the key.
✘ Validation failedプラグイン作者が踏みやすい落とし穴
予約済みのサーバー名と衝突する: Claude Codeはworkspace・claude-in-chrome・computer-use・Claude Preview・Claude Browserを組み込みサーバー用に予約しています。プラグインが同梱するMCPサーバーにこれらと同じ名前を付けると、Claude Codeは読み込み時にそのサーバーをスキップし、名前の変更を促す警告を出します。サーバー名は組み込みサーバーと衝突しない固有の名前にします。
headersHelperでは${user_config.*}が使えない: パスプレースホルダーはheadersHelperの値にも展開されますが、${user_config.KEY}はエラーになります(詳しくは前の節)。設定値を渡したいときは、headersフィールドに${user_config.KEY}を書くか、ヘルパースクリプトが設定ファイルから読みます。headersはシェルで解釈されないため、こちらでは埋め込めます。ヘルパーの環境にはCLAUDE_PLUGIN_ROOT・CLAUDE_CODE_MCP_SERVER_NAME・CLAUDE_CODE_MCP_SERVER_URLが渡されますが、userConfigの値は入りません。
ユーザー設定のMCPサーバーと何が違うか
機能面では、プラグイン同梱のMCPサーバーと手動で追加したMCPサーバーに違いはありません。違いはライフサイクルの持ち主にあります。
サーバーを管理する主体の違い
手動設定のサーバー
claude mcp add / claude mcp removeで追加・削除します。接続情報を変えるのも、使う人自身の操作です。
プラグイン同梱のサーバー
プラグインの有効・無効に合わせて接続・切断されます。/mcpパネルでできるのは、一時的にオフにするところまでです。
チームで同じサーバーを配るなら、サーバーをプラグインに同梱してマーケットプレイスで配布する形が選べます。メンバーごとにclaude mcp addのコマンドを案内する運用と比べて、接続定義が1か所にまとまります。
まとめ
同梱サーバーは、プラグインの有効・無効に連動して接続と切断が決まります。サーバー名は予約名を避け、人によって違う値はuserConfigに切り出すと、配布後に手元で直す箇所が残りません。