コンテンツにスキップ

MCPサーバー追加の実践

入門コースのMCPで能力を広げる(入門)では、信頼できるサーバーかを判定し、最小構成で1つ接続するところまでを扱いました。このレシピはその先 ─ 実務でMCPを運用するときに効く設定を、目的別にまとめます。MCPの仕組みとリスクの全体像はMCPとは何か、なぜ慎重に扱うかを、各キーの完全な一覧はMCPを前提とします。

考え方の軸は一貫しています。外部に頼るほど、できることと同時にリスクが増える。だから「広げる」設定ほど、範囲を絞る設定とセットで使います。

公開するツールを絞る(tools.include / exclude

サーバーが多くのツールを持っていても、使うものだけ登録するのが基本です。エージェントに見せる候補を減らすと、意図しないツール選択を防げます。

{
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/allowed"],
"env": {},
"tools": {
"include": ["read_file", "list_directory"]
}
}

include を指定すると、挙げたサーバー固有ツールだけが登録されます。逆に「これだけ外したい」場合は exclude を使います。両方書いた場合は include が優先します。リソースやプロンプトを使わないなら tools.resources / tools.prompts を切ることもできます。MCPタブでは、接続済みサーバーのツール名チップをクリックしても同じ include / exclude が書き換わります。

指定する名前はサーバー固有名のまま

エージェントに登録されるMCPツール名は mcp__<サーバー名>__<ツール名> 形式です(MCP)。ただし tools.include / exclude に書く名前はサーバーが公開する素のツール名(例: read_file)です。プレフィックス付きの登録名(mcp__filesystem__read_file など)を書いても一致しません。エージェントから見えるツール名やログ上の名前はプレフィックス付き形式で現れるため、両者を混同しないよう注意してください。

認証情報を安全に渡す

認証情報をJSONに直書きすると漏えいリスクになります。環境変数参照かOAuthを使います。

{
"url": "https://mcp.example.com/mcp",
"headers": {
"Authorization": "Bearer ${MCP_TOKEN}"
}
}

${MCP_TOKEN} のように環境変数を参照すれば、トークンそのものを設定に残さずに済みます。サーバーがOAuthに対応していれば、"auth": "oauth" でPKCEを使うのがさらに安全です。

HTTP接続では ssl_verify: false(証明書を検証しない)を実サービスで使わないでください。プライベートCAを使う場合は、ssl_verify にCA bundleのパスを指定します。

OAuthを実務で運用する

"auth": "oauth" の初回接続では、ブラウザで認可し、ローカルのコールバックポートで完了を受け取ります。両方のGUI(デスクトップ・Webダッシュボード)と特殊環境向けに、次の機能が用意されています。

  • GUIでフローを完了できる ─ デスクトップのMCPタブでは、「認証が必要です」状態のサーバーに「認証」ボタンが表示され、クリックするとブラウザでの認可待ち(「ブラウザを待機中…」)を経て「認証済み」になります。Webダッシュボード側にも同じOAuthフローが実装されています。
  • プロキシ経由のコールバック(redirect_uri / redirect_port ─ ゲートウェイをリモートで動かしているなど、ブラウザからループバックポートへ直接届かない環境では、公開HTTPSエンドポイント(公式ドキュメントはTailscale Funnelを例示)でコールバックポートへ転送し、oauth.redirect_uri にその転送元URLを設定します。あわせて oauth.redirect_port でローカルのコールバックポートを固定してください。省くと空きポートが自動で選ばれ(既定は 0 = 自動選択)、プロキシの転送先を一定に保てなくなるためです。
  • WAFが 127.0.0.1 を拒否する場合(redirect_host ─ 一部プロバイダのWAFは、authorizeリクエストのクエリに 127.0.0.1 が含まれると403で拒否します。oauth.redirect_host"localhost" を設定すると http://localhost:<ポート>/callback を使えます(リスナーのbindは 127.0.0.1 のまま変わりません)。
{
"url": "https://mcp.example.com/mcp",
"auth": "oauth",
"oauth": {
"redirect_port": 8765,
"redirect_uri": "https://oauth.example.ts.net/callback"
}
}

CLIと併用して config.yaml を直接編集する場合の注意 ─ 設定変更の自動再読み込みは30秒でタイムアウトするため、対話的なOAuthフローには足りません(公式ドキュメント記載)。OAuthサーバーを追記したら、別ターミナルで hermes mcp login <サーバー名> を実行してください。こちらは認可完了を5分まで待ちます。

stdioの環境とパスを最小化する

stdioサーバーはあなたのマシンで子プロセスとして起動し、渡したパスや環境変数にアクセスできます。env には子プロセスへ明示的に渡す変数だけを書きます(ホストの全環境は渡されません)。許可するディレクトリも必要最小限にします。

{
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/me/projects/this-one"],
"env": {}
}

作業対象のフォルダだけを引数で許可し、ホームディレクトリ全体のような広いパスは渡さないようにします。

常駐stdioサーバーを自動リサイクルする

Playwrightのようなブラウザ自動化系のstdioサーバーは、Chromiumを抱えたまま常駐するため、長く使うほどメモリが肥大しやすくなります。idle_timeout_seconds / max_lifetime_seconds で子プロセスを自動リサイクル(再起動)できます。公式ドキュメントのPlaywright向け設定例をJSONにするとこうなります。

{
"command": "npx",
"args": ["-y", "@playwright/mcp@latest", "--headless"],
"idle_timeout_seconds": 900,
"max_lifetime_seconds": 86400
}
  • idle_timeout_seconds ─ 最後のツール呼び出しからこの秒数を超えたらリサイクルする(例は15分)。
  • max_lifetime_seconds ─ 起動からの総経過時間でリサイクルする(例は1日)。
  • どちらも 0 は無効で、既定は未設定(リサイクルしない)。再起動は透過的で、次のツール呼び出し時に自動で立ち上がり直します。両キーは lifecycle: {...} の下にまとめて書くこともできます(MCP)。

sampling を制御する

MCPには、サーバー側からHermesのモデル推論を要求する sampling 機能があります(SDK対応時は既定で有効)。未信頼サーバーには止めるのが安全です。

{
"url": "https://mcp.example.com/mcp",
"sampling": {
"enabled": false
}
}

使わせる場合でも、max_tokens_capmax_rpmmax_tool_roundsallowed_models で上限と範囲を絞れます。log_level を上げておくと、何が要求されたかを監査できます。

確実に無効化する(enabled: false

実行時にサーバーを止める正式なキーは enabled: false です。これで接続・検出・登録がすべて停止します。

デスクトップのMCPタブの有効/無効スイッチは enabled キーそのものを操作します(オフで enabled: false を書き込み、オンで enabled キーを削除)。UI表示もランタイムの停止判定も同じ enabled フラグを読むため、スイッチの見た目と実際の停止状態は一致します。disabled は正式な停止キーではありません。

一時的に外したいサーバーは、削除せず enabled: false にしておくと、設定を残したまま無効化できます。

反映と検証

設定変更は原則として自動で反映されます。

  1. MCPタブで変更を保存する。保存が成功すると実行中のセッションへ自動で再読み込みされ、手動の「MCP を再読み込み」は不要になった(ボタン自体は手動更新用に残っている)。有効/無効スイッチやツール名チップの操作も同様に即時反映される。
  2. config.yaml を直接編集した場合も、mcp.auto_reload_on_config_change(既定 true)のファイルウォッチャーが mcp_servers セクションの変更を検知し、自動で再読み込みする。
  3. どちらの場合も、新しいツールスキーマが使われるのは次の新しいターンから。新しいターンで、狙ったツールが使えるか・余計なツールが増えていないかを確認する。
  4. サーバー側の警告・エラーは、MCPタブ下部のログペイン(stdio / agent 切替)か ~/.hermes/logs/agent.log で確認する。MCPサーバーが送るログ通知(notifications/message)は、サーバー名タグ付きで agent.log に記録される。

自動再読み込みは毎回エージェントのツール一覧を再構築し、プロバイダーのプロンプトキャッシュを無効化します(次のメッセージで入力プレフィックスを再送します)。外部ツールが config.yaml を頻繁に書き換える環境では、mcp.auto_reload_on_config_change: false にして /reload-mcp で明示的に適用する運用も選べます。false でもウォッチャーは変更を検知し、適用方法を案内します。

approvals.mcp_reload_confirm安全性)をオンにしておくと、再読み込み時にサーバー名・実行コマンド・URL・公開ツールを確認できます。安全のためオンを推奨します。

複数サーバーを運用するときの勘所

  • サーバーは用途ごとに分け、各サーバーで tools.include を絞る。1つのサーバーに何でも積まない。
  • 書き込み系ツールを持つサーバーで supports_parallel_tool_calls を安易に有効化しない(同時実行は副作用の順序が読みにくくなる)。
  • ブラウザ自動化系など常駐でメモリを抱えるstdioサーバーには idle_timeout_seconds / max_lifetime_seconds を設定して肥大を防ぐ。
  • 用途ごとに使うサーバーが違うなら、プロファイル(プロファイル管理)で構成を分けると、不要なサーバーを常時起動せずに済む。

前提・操作・期待結果・つまずいたら

  • 前提: 入門の最小1接続ができる。接続候補の配布元・実行方法を把握している。
  • 操作: tools.include で公開ツールを絞り、認証情報は環境変数参照かOAuthで渡し、未信頼サーバーは sampling.enabled: false、停止は enabled: false。保存すると自動で再読み込みされるので、新しいターンで検証する。
  • 期待結果: 必要なツールだけが登録され、認証情報を設定に残さず、止めたいサーバーは確実に停止し、変更が新しいターンに反映される。
  • つまずいたら:
    • 追加したツールが使えない: 保存が成功しているか(無効なJSONは保存できない)と、新しいターンで試したかを確認する。config.yaml 直接編集の場合は mcp.auto_reload_on_config_change をオフにしていないか確認する。
    • tools.include の指定が効かない: プレフィックス付きの mcp__サーバー名__ツール名 を書いていないか確認する。指定はサーバー固有の素のツール名で行う。
    • 無効化したのに動く: 停止キーは enabled: false。UIスイッチはこのキーを直接書くため、スイッチ操作でも確実に止まる。
    • HTTP接続が失敗する: URL・ホスト名・認証方式を確認する。ssl_verify: false で回避しない。
    • OAuthの認可が403 Forbiddenで弾かれる: WAFが 127.0.0.1 のコールバックを拒否している可能性がある。oauth.redirect_host"localhost" を設定する。
    • 再読み込みできない: ゲートウェイが切断中だと再読み込みできない(ゲートウェイ)。
    • ツールが多すぎて挙動が読みにくい: tools.include で絞る。サーバーを分ける。
    • サーバー側で何が起きたか見えない: MCPタブ下部のログペインか agent.log でサーバーログを確認する。

関連

© 2026 Hermes Desktop ガイド(非公式)。引用・部分転載は、出典として本ページへのリンクを添えていただければ歓迎します。記事全文の無断複製・転載はご遠慮ください。