# How to Handle Tool Name Conflicts Between MCP Tools and Dify Built-in Tools

> Learn how to avoid tool name conflicts between MCP tools and Dify built-in tools. This plugin automatically resolves collisions by prefixing MCP tool names, ensuring unique entries.

- Repository: [Junjie.M/dify-plugin-agent-mcp_sse](https://github.com/junjiem/dify-plugin-agent-mcp_sse)
- Tags: how-to-guide
- Published: 2026-03-05

---

**The junjiem/dify-plugin-agent-mcp_sse plugin automatically resolves collisions by prefixing conflicting MCP tool names with their server identifier and a double underscore, ensuring unique entries in the internal tool registry.**

When integrating external MCP (Model Context Protocol) servers into Dify agents, you may need to handle tool name conflicts when MCP tools have the same name as Dify built-in tools. The `junjiem/dify-plugin-agent-mcp_sse` repository solves this by implementing an automatic deduplication strategy in the MCP client that renames conflicting tools before they reach the agent's vocabulary. This approach allows both native Dify capabilities and third-party MCP tools to coexist without manual configuration or naming conventions.

## How the MCP Client Detects and Resolves Conflicts

The conflict resolution logic resides in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py), specifically within the `McpClients._iter_tools` method (lines 71-78). As the client iterates over tools returned by an MCP server, it maintains a flat dictionary called `_tool_actions` that serves as the single source of truth for all available tools.

### Conflict Detection in the Tool Registry

During initialization, the client checks each incoming tool name against the existing keys in `self._tool_actions`. This registry contains both Dify's native tools and any previously registered MCP tools. If the name already exists, the client identifies a collision that must be resolved to prevent routing ambiguity.

### Automatic Renaming with Server Prefix

When a conflict is detected, the client automatically rewrites the tool identifier by prepending the server name and a double underscore (`__`). For example, a tool named `search` from a server named `my_mcp` becomes `my_mcp__search`.

```python

# utils/mcp_client.py – lines 71-78

if name in self._tool_actions:                 # <-- conflict detected

    name = f"{server_name}__{name}"            # <-- rename with server prefix

self._tool_actions[name] = ToolAction(
    tool_name=name,
    server_name=server_name,
    action_type=ActionType.TOOL,
    action_feature=tool,
)

```

This deterministic renaming ensures reproducible identifiers, meaning the same tool name always resolves to the same fully-qualified key regardless of client reinitialization.

## Runtime Resolution in Function-Calling Agents

The agent strategy implemented in [`strategies/function_calling.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.py) (lines 84-106) resolves tool calls by performing exact lookups in `_tool_actions`. Because renamed MCP tools carry the `{server}__` prefix while built-in Dify tools use their original names, the agent can unambiguously route requests to either the native implementation or the appropriate MCP server.

When the LLM emits a function call, it uses the renamed identifier (e.g., `my_mcp__search`). The agent queries `_tool_actions` with this key and forwards the request via the MCP client, leaving Dify's native `search` tool untouched for other operations.

## Handling Resources and Prompts

The same conflict-resolution strategy applies to MCP resources and prompts to ensure complete namespace isolation. The methods `_iter_resources` (lines 86-98) and `_iter_prompts` (lines 49-57) in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py) implement identical prefixing logic. When these capabilities are dynamically converted to tools, they are checked against `_tool_actions` and prefixed with their server name if conflicts exist with existing tools or other MCP servers.

## Practical Implementation Examples

### Fetching Tools with Automatic Conflict Handling

When initializing `McpClients`, duplicate names are renamed internally without requiring manual intervention.

```python
from utils.mcp_client import McpClients

# Configuration containing a 'search' tool that collides with Dify's built-in search

servers_cfg = {
    "my_mcp": {
        "url": "https://mcp.example.com/api",
        "transport": "sse"
    }
}

clients = McpClients(servers_cfg)
all_tools = clients.fetch_tools()

# Output contains "my_mcp__search" if "search" conflicts with a Dify tool

print(all_tools)

```

### Invoking Renamed Tools from an Agent

When using `FunctionCallingAgentStrategy`, the renamed tool names are transparently passed to the LLM in the function-calling payload.

```python
from strategies.function_calling import FunctionCallingAgentStrategy

params = {
    "query": "Find AI research papers",
    "model": {"provider": "openai", "name": "gpt-4"},
    "tools": ["search"],  # Dify built-in tool

    "mcp_servers_config": '{"mcpServers": {"academic_mcp": {"url": "https://scholar.example.com/mcp"}}}',
    "maximum_iterations": 3,
}

agent = FunctionCallingAgentStrategy()
for msg in agent.invoke(params):
    # Tool calls use names like "academic_mcp__search" when conflicts exist

    print(msg)

```

### Customizing the Naming Separator

If the default double-underscore separator does not fit your naming conventions, you can modify the prefixing logic in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py) (line 73).

```python

# Override in utils/mcp_client.py

if name in self._tool_actions:
    # Custom separator example

    name = f"{server_name}--{name}"

```

After reloading the plugin, the new format (e.g., `my_mcp--search`) applies to all subsequent tool registrations.

## Summary

- **Automatic detection**: The `McpClients` class checks `_tool_actions` during tool iteration in `_iter_tools` (lines 71-78) to identify duplicate names.
- **Server-prefix renaming**: Conflicting tools are renamed to `{server_name}__{tool_name}` to ensure global uniqueness across all MCP servers and Dify built-ins.
- **Transparent routing**: The function-calling agent in [`strategies/function_calling.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/strategies/function_calling.py) (lines 84-106) resolves tool calls using the renamed identifiers, routing requests without ambiguity.
- **Extended coverage**: Resources and prompts receive identical treatment via `_iter_resources` (lines 86-98) and `_iter_prompts` (lines 49-57), preventing collisions across all MCP capabilities.

## Frequently Asked Questions

### How does the plugin detect conflicts between MCP tools and Dify built-in tools?

The plugin maintains a flat dictionary called `_tool_actions` in `McpClients` that registers every available tool. When iterating over tools from an MCP server in `_iter_tools` (lines 71-78), it checks if the tool name already exists as a key in this registry. If the name exists—whether from a previous MCP server or a Dify native tool—the conflict is detected immediately before the tool is registered.

### Can I customize the separator between server and tool names?

Yes. While the default implementation in [`utils/mcp_client.py`](https://github.com/junjiem/dify-plugin-agent-mcp_sse/blob/main/utils/mcp_client.py) (line 73) uses a double underscore (`__`) in the f-string `f"{server_name}__{name}"`, you can modify this to use any separator you prefer, such as a single dash or dot. This change affects all subsequent tool, resource, and prompt registrations after the plugin reloads.

### Does this conflict resolution work for MCP resources and prompts as well?

Yes. The same renaming logic is applied in `McpClients._iter_resources` (lines 86-98) and `McpClients._iter_prompts` (lines 49-57). When resources or prompts are converted to tools, they are checked against `_tool_actions` and prefixed with their server name if conflicts exist with built-in Dify tools or other MCP capabilities.

### What happens if two different MCP servers expose tools with identical names?

The first server to register a tool name claims the plain identifier in `_tool_actions`. When the second server attempts to register the same name, the plugin detects the conflict in `_iter_tools` and prefixes the second tool with its server name (e.g., `server2__tool_name`). Both tools remain accessible via their respective fully-qualified names, allowing multiple MCP servers to provide semantically similar tools without collision.