MCPで同じツール名が競合するとどうなる?名前付けとNamespace設計

MCPで同じツール名が競合するとどうなる?名前付けとNamespace設計 AI開発

MCPサーバーでToolを増やしていくと、意外と問題になりやすいのがTool名の競合です。たとえば2つの機能を、どちらもsearchという同じ名前で登録したらどうなるでしょうか。

さらに複数のMCPサーバーをClaude Codeなどへ接続すると、GitHub MCPのsearch、社内ドキュメントMCPのsearch、商品検索MCPのsearchが同時に見えてしまうこともあります。

この2種類の競合は分けて考える必要があります。MCP 2026-07-28仕様では、Tool名は1つのServer内では一意にすることが推奨(SHOULD)されています。一方、Tool名の一意性はServer単位であり、複数Serverを集約するClientやProxyでは同名Toolが存在し得ます。その場合は、Client側がServer Identifierを付けるなどして区別することが推奨されています。

名前の一意性の範囲
同一Server内
  → Tool名を重複させない

別Server間
  → 同名Toolはあり得る
  → Host側でNamespaceを付けて区別する

「Clientが区別してくれるから全部searchでよい」という設計もおすすめできません。AIモデルはTool名とDescriptionを見てどのToolを呼ぶか判断するため、名前が似すぎたToolが並ぶと、技術的には衝突していなくても選択が難しくなります。

この記事では、同じTool名を登録するとどうなるのか、複数Server間の名前衝突、Claude Codeのmcp__server__tool形式、Namespace設計と検証方法を解説します。Toolの基本的な仕組みはMCPサーバーが「Method not found」になる原因|tools/list・tools/callを確認、ToolとResourceの役割分担はMCPのtools・resources・promptsの違い|何をどこに実装するべきかで解説しています。悪意ある偽装Toolによる名前の乗っ取りはClaude Code + MCP セキュリティ設計完全ガイド|OAuth 2.1認証・ツール毒性化対策・最小権限・監査ログで扱っており、本記事は意図しない名前の衝突に絞ります。

スポンサーリンク

MCPのTool名はServer内で一意にする

MCP Clientはまずtools/listを実行して、そのServerが提供しているToolを取得します。

tools/listの結果
{
  "tools": [
    {
      "name": "search_products"
    },
    {
      "name": "get_product"
    }
  ]
}

Toolを実行するときはtools/callへTool名を渡します。

tools/callのリクエスト
{
  "method": "tools/call",
  "params": {
    "name": "search_products",
    "arguments": {
      "query": "RTX 5070"
    }
  }
}

基本的にはnameだけでToolを特定します。別のFunction IDやRegistration IDのような識別子はありません。そのため、1つのServerからsearchとsearchという2つの異なるToolを公開する設計は避けるべきです。

同じServerに同名Toolを登録するとどうなる?

MCPプロトコル自体は、同名Toolが見つかった場合にどちらが勝つか、起動を失敗させるかといったルールを定義していません。仕様が求めているのは、そもそも重複させないことです。実際の挙動は利用するSDKに依存します。

現在のMCP Python SDKのHigh-level APIでは、同じ名前のToolを2回登録すると次のようなWarningがServer Logへ出ます。

NG: 同名で2回登録
from mcp.server import MCPServer

mcp = MCPServer("Weather")


@mcp.tool(name="forecast")
def forecast_today(
    city: str
) -> str:
    return f"{city}: rain"


@mcp.tool(name="forecast")
def forecast_hourly(
    city: str,
    hours: int
) -> str:
    return f"{city}: rain for {hours}h"
Server Logに出るWarning
WARNING mcp.server.mcpserver.tools.tool_manager: Tool already exists: forecast

先に登録されたToolが残り、後から同名で登録されたToolは静かに捨てられます。tools/listには1つしか出ないため、Warningを見ないと気付きにくいのが厄介なところです。

Warningを無効にして解決したことにしない

Python SDKには、このWarningを止めるwarn_on_duplicate_tools=Falseという設定があります。ただしこれは警告を見えなくするだけで、衝突した結果は変わりません。

公式のTroubleshootingでも、Warningは残したままどちらかのTool名を変えるよう案内されています。たとえば次のように分けます。

OK: 名前を分ける
@mcp.tool(name="forecast_current")
def forecast_today(
    city: str
) -> str:
    return f"{city}: rain"


@mcp.tool(name="forecast_hourly")
def forecast_hourly(
    city: str,
    hours: int
) -> str:
    return f"{city}: rain for {hours}h"

別のMCPサーバーなら同じTool名を使える

一方、Server AとServer Bがそれぞれsearchを公開する構成は、MCP仕様上あり得ます。Tool名の一意性はServer単位だからです。仕様でも、複数ServerのToolを集約するClientやProxyでは名前衝突が起き得ると明記されています。

問題になるのは、それらを1つのAI Applicationへまとめたときです。Hostが区別する仕組みを持たないと、モデルにはどちらのsearchを指しているのか分かりません。

MCP Client側でNamespaceを付ける

複数Serverを1つのModelへ接続するHostやProxyは、Server Identifierを付けてTool名を区別します。

Hostによる区別の例
github.search
documents.search

(または github__search / documents__search など)

形式は実装によって異なります。大事なのは、Hostが一意に管理できるIdentifierを使うことです。

serverInfo.nameを一意なNamespaceだと思わない

MCP ServerはServer自身の名前をserverInfo.nameで返します。しかし仕様では、serverInfo.nameがServer間で一意であることは保証されず、衝突の解消に使うべきではない(SHOULD NOT)とされています。

serverInfo.name + tool.nameだけで一意性を保証する設計は避けます。Hostは設定時に付けたServer IDや接続IDなど、自分で一意性を管理できる値をNamespaceに使います。

Claude Codeではmcp__server__tool形式になる

Claude CodeではMCP Toolが内部的にmcp__<server>__<tool>という名前で扱われます。githubという名前で設定したServerがsearch_issuesを提供していれば、mcp__github__search_issuesになります。

Permission Ruleもこの名前で書きます。Server内の全Toolを対象にするなら、末尾に*を付けます。

.claude/settings.json
{
  "permissions": {
    "allow": [
      "mcp__github__search_issues",
      "mcp__docs__*"
    ]
  }
}

これにより、githubのsearchとdocsのsearchは、Claude Code上では別の名前として区別できます。

Claude CodeではServer名もAccess Controlの識別子になる

Permission Ruleでmcp__github__*のように書く以上、Server名は単なる表示名ではありません。Access Controlにも関係するIdentifierとして扱うべきです。

server1・server2よりgithub・company-docs・production-dbのほうが、PermissionやHookを設定するときに意味が分かりやすくなります。

同じServer名を複数Scopeに定義すると上書きされる

Claude CodeではUser・Project・Localなど複数のScopeにMCP Serverを設定できます。同じ名前の定義が複数あると、Tool名の競合とは別の問題が起きます。

公式ドキュメントによると、優先順位はLocal(最優先)→Project→User→Plugin提供のServer→claude.aiコネクタの順です(組織がmanagedMcpServersで配布するServerはこれより優先されます)。同じServerが複数箇所に定義されている場合、Claude Codeは最も優先度の高い定義を1回だけ使い、フィールドを合成しません。

User ScopeのgithubとProject Scopeのgithubは同時に存在するのではなく、一方の定義がまるごと採用されます。複数のGitHub Serverを同時に使いたいなら、github-personalとgithub-companyのように名前そのものを変えます。

Tool名の文字と長さは仕様の推奨に合わせる

MCP 2026-07-28仕様では、Tool名について次のような推奨が定められています。

  • 長さは1〜128文字
  • 大文字と小文字は区別する
  • 使う文字はASCIIの英字・数字・_・-・.
  • スペース・カンマなどの特殊文字は避ける

search productsよりsearch_productsやproducts.searchのほうが適しています。.を使えば、admin.tools.listのような階層的な名前も仕様上の例として挙げられています。

ただし、大文字と小文字だけが違う名前は作らないほうが安全です。仕様上は別物でも、人間もAIも取り違えやすく、Permissionやログ検索で混乱します。すべて小文字に統一するのが管理しやすいでしょう。

抽象的すぎるTool名と同じ意味のToolを増やさない

searchという名前自体は仕様上問題ありません。ただ、GitHub・Slack・社内Wiki・DBの検索が同時に見えると、どれもsearchでは意味が広すぎます。

対象まで名前に含めてsearch_issues・search_messages・search_documentsとすると、モデルが選びやすくなります。

逆に、search・find・lookup・queryをすべて用意するのも問題です。モデルから見て機能の違いが分からず、Tool選択が不安定になります。名前が一意でも、意味が競合していればTool選択の問題は残ります。Namespaceは衝突を避けるためだけでなく、モデルへToolの意味を伝えるための設計でもあります。

動詞の意味を固定する

同じServer内では、動詞の意味を固定します。

  • get_customer:customer_idを指定して1件取得
  • search_customers:名前やメールなどの条件から複数候補を検索
  • list:既知のCollectionを一覧化
  • create・update・delete:新規作成・既存の更新・削除

「IDが分かっているならget、対象を探すならsearch」と決めておけば、モデルも判断しやすくなります。Snake Caseならsearch_customers・get_customer、Domain-firstならcustomer.search・customer.getのように揃えます。どちらかが絶対に正しいわけではなく、Server内で統一することが重要です。

Tool Descriptionも名前とセットで設計する

名前が似た系統になってしまう場合は、Descriptionで違いをはっきり書きます。たとえばsearch_documentsが2つあるなら、一方は「社内のエンジニアリングWikiを検索」、もう一方は「ベンダーのサポートポータルの公開ドキュメントを検索」と説明します。名前もsearch_internal_documents・search_vendor_documentsと分ければ、モデルは迷いにくくなります。引数の書き方はMCPツールのinputSchemaはどう書く?JSON Schemaの実例付きで解説も参照してください。

ただし、Descriptionはモデルの選択精度を上げる補助であり、Permissionや検証の代わりにはなりません。

Tool名は一度決めたら気軽に変えない

Tool名は表示ラベルではありません。tools/callのparams.nameとして使われ、Streamable HTTPの2026-07-28仕様ではMcp-Nameヘッダにもミラーされます。これはGatewayがBodyを解析せずにRoutingなどを行えるようにするためで、仕様ではServerがヘッダとBodyの値の不一致を400 Bad Requestで拒否することも求められています。

tools/callのHTTPヘッダ(例)
POST /mcp HTTP/1.1
MCP-Protocol-Version: 2026-07-28
Mcp-Method: tools/call
Mcp-Name: search_products

delete_userをuser.deleteへ変えると、Client設定・Permission・Proxy Rule・Gateway Policy・監査ログ検索・Hook・Automationに影響し得ます。Tool名はAPI Endpointと同じく、Stable Identifierとして扱います。

Claude CodeでもPermissionはmcp__server__toolという名前で照合されるため、名前の変更はSecurity設定の変更でもあります。

API Versionや深すぎるNamespaceを名前へ入れない

API Versionが変わるたびにsearch_v1・search_v2と増やすと、同時にどちらを使うべきかという新たな競合が生まれます。後方互換が不要なら、内部実装を更新しつつTool名はsearch_productsのまま保つほうが単純です。互換を保てない破壊的変更のときだけ、新しい名前を検討します。

.が使えるからといってcompany.production.crm.customer.profile.address.updateのように長くする必要はありません。Tool Catalogが読みにくくなり、モデルにとってもノイズになります。Namespaceに何を含めるかの基準は、「その情報がないと別Toolと区別できないか」です。

小さなServerと大規模Gatewayでは命名の深さを変える

商品検索専用のServerなら、search_products・get_product・get_stockで十分です。Serverという境界そのものがNamespaceとして機能しています。Claude Codeではmcp__shop__search_productsになります。

逆に、1つのMCP GatewayからGitHub・Slack・Jiraなど多くのServiceを公開するなら、Service Namespaceを入れます。github.issue.search・slack.message.search・jira.issue.searchのように、Service → Resource → Actionという構造を名前から読み取れるようにします。

Gatewayでは、Server IDをGateway側の設定で決めて、そのIDをprefixにします。serverInfo.nameは使いません。

Gatewayの設定例
{
  "servers": {
    "github": { "url": "https://github-mcp.internal/mcp" },
    "docs": { "url": "https://docs-mcp.internal/mcp" }
  }
}

Gatewayが各ServerのTool名を連結するとき、区切りに.を使うなら、Server IDに.を含めてはいけません。たとえばServer IDがa.bでToolがcの場合と、Server IDがaでToolがb.cの場合が、どちらもa.b.cになってしまうからです。連結後の名前も重複チェックを通してから、モデルへ公開します。

連結後のTool名の検証
def build_gateway_tool_names(
    servers: dict[str, list[str]]
) -> list[str]:
    for server_id in servers:
        if "." in server_id:
            raise ValueError(
                f"Server ID must not contain dot: {server_id}"
            )

    names = [
        f"{server_id}.{tool}"
        for server_id, tools in servers.items()
        for tool in tools
    ]

    if len(names) != len(set(names)):
        raise RuntimeError("Duplicate gateway tool name")

    return names

名前の重複と規則をコードで検証する

Toolが増えてくると、人の注意だけでNaming Ruleを守るのは難しくなります。Server起動時やTestで、重複と規則違反を検出しておくと安全です。ここでは前節の小文字統一を、プロジェクトの運用ルールとして正規表現で表しています。仕様上は大文字も使えるため、これは仕様の要求ではなく方針です。

Naming Ruleのチェック
import re

TOOL_NAME = re.compile(r"^[a-z0-9._-]{1,128}$")


def validate_tool_names(
    names: list[str]
) -> None:
    if len(names) != len(set(names)):
        raise RuntimeError("Duplicate MCP tool name")

    for name in names:
        if not TOOL_NAME.fullmatch(name):
            raise RuntimeError(
                f"Invalid tool name: {name}"
            )

最終的にClientへ見える名前はtools/listで確認できます。Integration Testで一覧を取得し、重複がないことを確認します。下のコードはClient APIの形を示す擬似コードです。SDKの実際のAPIに合わせて読み替えてください。

tools/listの重複テスト
result = await client.list_tools()

names = [
    tool.name
    for tool in result.tools
]

assert len(names) == len(set(names))

特に、DecoratorやPluginから動的にToolを登録するServerでは有効です。コード上では違うFunction名でも、@mcp.tool(name="search")のように同じPublic Nameを指定していれば衝突します。Python SDKではnameを省略するとFunction名がTool名になります。

MCPのTool名の競合に関するよくある質問

Q同じ名前のToolを登録すると、起動がエラーで止まりますか?

APython SDKでは起動は止まりません。先に登録したToolが残り、後から登録したToolは捨てられて、Server LogにWarningが出ます。エラーにならないため気付きにくい点が問題です。Warningは無効化せず、Tool名を変えて解消します。

QClaude Codeで2つのServerが同じ名前のToolを持つとき、Permissionはどう書けばよいですか?

ATool名はmcp__<server>__<tool>で区別されるため、mcp__github__searchとmcp__docs__searchのように別々に指定できます。Server単位でまとめて許可・拒否したい場合はmcp__github__*のようなwildcardを使います。

Q同じServer名をLocalとProjectの両方に設定したら、どちらが使われますか?

A両方が同時に動くわけではありません。優先順位が高いLocal側の定義が1つだけ採用され、フィールドは合成されずに定義全体が置き換わります。意図せず上書きされていないか、各Scopeの設定ファイルを確認するとよいでしょう。

QserverInfo.nameを使えば、名前の衝突は自動的に解消できますか?

Aできません。仕様ではserverInfo.nameがServer間で一意であることは保証されておらず、衝突の解消に使うべきではないとされています。AggregatorやHostは、自分で管理する一意なServer IDを使う必要があります。

QTool名を変えると既存の連携は壊れますか?

A壊れる可能性があります。tools/callはTool名で呼び出し、Streamable HTTPではMcp-Nameヘッダにも入ります。Claude CodeのPermissionもCanonical Nameで照合されるため、名前を変える前にClient設定、Permission、Gateway、Hook、監査ログ検索への影響を確認します。

MCPのTool名は「重複しなければよい」ではなく「モデルが迷わない」まで設計する

MCPのTool名は、Server内で一意なFunction IDであると同時に、AIモデルへ「何ができるToolか」を伝えるラベルです。

同じServer内では名前を重複させません。別Serverの同名は仕様上あり得るため、ClientやProxyがServer Identifierで区別します。その際、serverInfo.nameは一意と保証されないため使いません。

Claude Codeではmcp__server__tool形式で扱われ、Permissionもこの名前で照合されます。Server名はAccess Controlの識別子でもあり、同じ名前の定義はScopeの優先順位で1つに決まります。

命名は、Server・Domain・Resource・Actionのどこまでを名前へ含めればモデルが迷わないかを基準にします。そしてNaming Ruleと重複をテストで検証しておけば、Tool数が増えても管理しやすいMCP Serverになります。