openclaw - 💡(How to fix) Fix [Feature]: MCP tool namespace isolation to prevent cross-server name collisions [1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#54860Fetched 2026-04-08 01:35:07
View on GitHub
Comments
0
Participants
1
Timeline
1
Reactions
0
Author
Participants
Timeline (top)
labeled ×1

Problem When multiple MCP servers are configured in openclaw.json, tools from different servers that share the same name cause a silent collision. The second tool is skipped with a warning: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because the name already exists. Currently, OpenClaw registers all MCP tools into a flat global namespace. When two servers expose a tool with the same name, the first one wins and the second is silently dropped. This means users lose access to functionality from the second server with no error — only a warning log. Real-world scenario We run two observability MCP servers simultaneously because our stack uses different tracing backends for different languages: { "mcpServers": { "skywalking-mcp": { "command": "/path/to/swmcp" }, "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp" } } } skywalking-mcp — for Java services (SkyWalking backend) opentelemetry-mcp — for Golang services (OpenTelemetry backend) Both servers expose list_services, list_traces, get_trace_detail, etc. — which are standard operations for any tracing tool. The collision means we can only query one backend, defeating the purpose of having both configured. This is not unique to observability tools. As the MCP ecosystem grows, name collisions across independent servers will become increasingly common (e.g., multiple database MCP servers all exposing query, list_tables; multiple cloud provider MCPs all exposing list_instances, etc.). Current workaround Using toolPrefix to manually namespace one of the servers: "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp", "toolPrefix": "otel_" } This works but is manual, fragile, and the user has to know about the collision in advance.

Error Message

WARN: skipped tool "list_services" from server "opentelemetry-mcp" because the name already exists. Currently, OpenClaw registers all MCP tools into a flat global namespace. When two servers expose a tool with the same name, the first one wins and the second is silently dropped. This means users lose access to functionality from the second server with no error — only a warning log. Option C (minimal): Warn + suggest fix WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts Option C (minimal): Warn + suggest fix WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts Option C (minimal): Warn + suggest fix WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts

Root Cause

Problem When multiple MCP servers are configured in openclaw.json, tools from different servers that share the same name cause a silent collision. The second tool is skipped with a warning: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because the name already exists. Currently, OpenClaw registers all MCP tools into a flat global namespace. When two servers expose a tool with the same name, the first one wins and the second is silently dropped. This means users lose access to functionality from the second server with no error — only a warning log. Real-world scenario We run two observability MCP servers simultaneously because our stack uses different tracing backends for different languages: { "mcpServers": { "skywalking-mcp": { "command": "/path/to/swmcp" }, "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp" } } } skywalking-mcp — for Java services (SkyWalking backend) opentelemetry-mcp — for Golang services (OpenTelemetry backend) Both servers expose list_services, list_traces, get_trace_detail, etc. — which are standard operations for any tracing tool. The collision means we can only query one backend, defeating the purpose of having both configured. This is not unique to observability tools. As the MCP ecosystem grows, name collisions across independent servers will become increasingly common (e.g., multiple database MCP servers all exposing query, list_tables; multiple cloud provider MCPs all exposing list_instances, etc.). Current workaround Using toolPrefix to manually namespace one of the servers: "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp", "toolPrefix": "otel_" } This works but is manual, fragile, and the user has to know about the collision in advance.

Fix Action

Fix / Workaround

Problem When multiple MCP servers are configured in openclaw.json, tools from different servers that share the same name cause a silent collision. The second tool is skipped with a warning: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because the name already exists. Currently, OpenClaw registers all MCP tools into a flat global namespace. When two servers expose a tool with the same name, the first one wins and the second is silently dropped. This means users lose access to functionality from the second server with no error — only a warning log. Real-world scenario We run two observability MCP servers simultaneously because our stack uses different tracing backends for different languages: { "mcpServers": { "skywalking-mcp": { "command": "/path/to/swmcp" }, "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp" } } } skywalking-mcp — for Java services (SkyWalking backend) opentelemetry-mcp — for Golang services (OpenTelemetry backend) Both servers expose list_services, list_traces, get_trace_detail, etc. — which are standard operations for any tracing tool. The collision means we can only query one backend, defeating the purpose of having both configured. This is not unique to observability tools. As the MCP ecosystem grows, name collisions across independent servers will become increasingly common (e.g., multiple database MCP servers all exposing query, list_tables; multiple cloud provider MCPs all exposing list_instances, etc.). Current workaround Using toolPrefix to manually namespace one of the servers: "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp", "toolPrefix": "otel_" } This works but is manual, fragile, and the user has to know about the collision in advance.

RAW_BUFFERClick to expand / collapse

Summary

Problem When multiple MCP servers are configured in openclaw.json, tools from different servers that share the same name cause a silent collision. The second tool is skipped with a warning: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because the name already exists. Currently, OpenClaw registers all MCP tools into a flat global namespace. When two servers expose a tool with the same name, the first one wins and the second is silently dropped. This means users lose access to functionality from the second server with no error — only a warning log. Real-world scenario We run two observability MCP servers simultaneously because our stack uses different tracing backends for different languages: { "mcpServers": { "skywalking-mcp": { "command": "/path/to/swmcp" }, "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp" } } } skywalking-mcp — for Java services (SkyWalking backend) opentelemetry-mcp — for Golang services (OpenTelemetry backend) Both servers expose list_services, list_traces, get_trace_detail, etc. — which are standard operations for any tracing tool. The collision means we can only query one backend, defeating the purpose of having both configured. This is not unique to observability tools. As the MCP ecosystem grows, name collisions across independent servers will become increasingly common (e.g., multiple database MCP servers all exposing query, list_tables; multiple cloud provider MCPs all exposing list_instances, etc.). Current workaround Using toolPrefix to manually namespace one of the servers: "opentelemetry-mcp": { "command": "/path/to/opentelemetry-mcp", "toolPrefix": "otel_" } This works but is manual, fragile, and the user has to know about the collision in advance.

Problem to solve

Option A (preferred): Automatic server-scoped namespacing Register tools internally as {serverName}.{toolName} (or {serverName}_{toolName}), so the model sees: skywalking_mcp_list_services opentelemetry_mcp_list_services This could be opt-in via a global config flag: { "mcpServers": { "_options": { "autoNamespace": true } } } Option B: Per-server namespace with explicit opt-in Add a namespace field per server: "opentelemetry-mcp": { "command": "...", "namespace": "otel" } Tools become otel_list_services, otel_list_traces, etc. Option C (minimal): Warn + suggest fix Keep the current flat namespace, but improve the warning message to suggest using toolPrefix: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts with the same tool from "skywalking-mcp". Add "toolPrefix" to one of the servers to resolve.

Proposed solution

Option A (preferred): Automatic server-scoped namespacing Register tools internally as {serverName}.{toolName} (or {serverName}_{toolName}), so the model sees: skywalking_mcp_list_services opentelemetry_mcp_list_services This could be opt-in via a global config flag: { "mcpServers": { "_options": { "autoNamespace": true } } } Option B: Per-server namespace with explicit opt-in Add a namespace field per server: "opentelemetry-mcp": { "command": "...", "namespace": "otel" } Tools become otel_list_services, otel_list_traces, etc. Option C (minimal): Warn + suggest fix Keep the current flat namespace, but improve the warning message to suggest using toolPrefix: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts with the same tool from "skywalking-mcp". Add "toolPrefix" to one of the servers to resolve.

Alternatives considered

Option A (preferred): Automatic server-scoped namespacing Register tools internally as {serverName}.{toolName} (or {serverName}_{toolName}), so the model sees: skywalking_mcp_list_services opentelemetry_mcp_list_services This could be opt-in via a global config flag: { "mcpServers": { "_options": { "autoNamespace": true } } } Option B: Per-server namespace with explicit opt-in Add a namespace field per server: "opentelemetry-mcp": { "command": "...", "namespace": "otel" } Tools become otel_list_services, otel_list_traces, etc. Option C (minimal): Warn + suggest fix Keep the current flat namespace, but improve the warning message to suggest using toolPrefix: WARN: skipped tool "list_services" from server "opentelemetry-mcp" because it conflicts with the same tool from "skywalking-mcp". Add "toolPrefix" to one of the servers to resolve.

Impact

OpenClaw version: 2026.3.23-2 OS: macOS (headless, SSH) MCP servers: skywalking-mcp + opentelemetry-mcp (both expose list_services)

Evidence/examples

No response

Additional information

The MCP protocol itself identifies servers by name, so the namespace information already exists at the transport level. The collision only happens because OpenClaw flattens tools into a single registry during loading. This will become a more common issue as users adopt multiple MCP servers from the growing ecosystem — especially servers in the same domain (databases, cloud providers, observability, CI/CD, etc.) that naturally use similar tool names.

extent analysis

Fix Plan

To resolve the issue of silent collisions between tools from different MCP servers, we will implement Automatic server-scoped namespacing. This involves registering tools internally as {serverName}_{toolName}.

Step-by-Step Solution

  1. Add a global config flag: Introduce a new flag autoNamespace in the mcpServers configuration.
  2. Modify tool registration: Update the tool registration logic to prefix tool names with the server name when autoNamespace is enabled.
  3. Update tool lookup: Modify the tool lookup logic to handle the new namespaced tool names.

Example Code

# config.json
{
  "mcpServers": {
    "_options": {
      "autoNamespace": true
    },
    "skywalking-mcp": {
      "command": "/path/to/swmcp"
    },
    "opentelemetry-mcp": {
      "command": "/path/to/opentelemetry-mcp"
    }
  }
}

# tool_registration.py
def register_tool(server_name, tool_name):
    if config.autoNamespace:
        namespaced_tool_name = f"{server_name}_{tool_name}"
        # Register the tool with the namespaced name
        register_tool_internal(namespaced_tool_name)
    else:
        # Register the tool with the original name
        register_tool_internal(tool_name)

# tool_lookup.py
def get_tool(server_name, tool_name):
    if config.autoNamespace:
        namespaced_tool_name = f"{server_name}_{tool_name}"
        # Lookup the tool with the namespaced name
        return get_tool_internal(namespaced_tool_name)
    else:
        # Lookup the tool with the original name
        return get_tool_internal(tool_name)

Verification

To verify that the fix worked, you can:

  • Enable autoNamespace in the configuration and restart the OpenClaw service.
  • Verify that tools from different servers with the same name are no longer skipped and can be accessed using the namespaced name (e.g., skywalking_mcp_list_services and opentelemetry_mcp_list_services).

Extra Tips

  • Make sure to update the documentation to reflect the new autoNamespace configuration option and the changes to tool naming.
  • Consider adding a warning message when autoNamespace is not enabled and a tool collision is detected, to encourage users to enable the feature.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING