n8n-io/n8n · error · Error

MCP tool name collision — the following tool names resolve t

Error message

MCP tool name collision — the following tool names resolve to duplicates: ${collisions.join(', ')}

What it means

Thrown by Agent.build() after listing MCP server tools, when an MCP tool's name matches a name already in the static or deferred tool set. MCP tools are discovered at build time via listTools(), so this collision is detected after the static/deferred checks. Duplicate names between MCP and local tools make tool dispatch ambiguous.

Source

Thrown at packages/@n8n/agents/src/sdk/agent.ts:1034

				staticNames.has(tool.name) ||
				reservedDeferredToolNames.has(tool.name) ||
				deferredNames.has(tool.name)
			) {
				deferredCollisions.push(tool.name);
			}
			deferredNames.add(tool.name);
		}
		if (deferredCollisions.length > 0) {
			throw new Error(
				`Deferred tool name collision — the following tool names resolve to duplicates or reserved tools: ${deferredCollisions.join(', ')}`,
			);
		}

		const collisions = mcpTools
			.filter((t) => staticNames.has(t.name) || deferredNames.has(t.name))
			.map((t) => t.name);
		if (collisions.length > 0) {
			throw new Error(
				`MCP tool name collision — the following tool names resolve to duplicates: ${collisions.join(', ')}`,
			);
		}

		let allTools = [...finalStaticTools, ...mcpTools];

		// Validate checkpoint again after discovering actual MCP tools
		// (catches the case where MCP tools have suspendSchema after listing).
		const allNeedCheckpoint =
			allTools.some((t) => t.suspendSchema) || finalDeferredTools.some((t) => t.suspendSchema);
		if (allNeedCheckpoint && !this.checkpointStore) {
			throw new Error(
				`Agent "${this.name}" has tools requiring approval or suspend/resume but no checkpoint storage. ` +
					"Add .checkpoint('memory') for in-process storage, " +
					'or pass a persistent store (e.g. LibSQLStore, PgStore).',
			);
		}

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Rename the local static or deferred tool to avoid the collision with the MCP-provided name.
  2. Configure the MCP client to filter or rename tools if it supports tool name remapping.
  3. Remove the conflicting local tool if the MCP version is sufficient.
  4. Inspect the error message for the specific colliding names and resolve each.

Example fix

// before
agent.tools([{ name: 'search', ... }])
     .mcp(myMcpClient); // MCP also exposes 'search'
// after
agent.tools([{ name: 'local_search', ... }])
     .mcp(myMcpClient);
Defensive patterns

Strategy: validation

Validate before calling

function findMcpCollisions(localNames: Set<string>, mcpTools: { name: string }[]): string[] {
  return mcpTools.filter((t) => localNames.has(t.name)).map((t) => t.name);
}
// After listing MCP tools, check before build:
const localNames = new Set([...staticTools, ...deferredTools].map((t) => t.name));
const collisions = findMcpCollisions(localNames, mcpTools);

Prevention

When it happens

Trigger: An MCP server exposes a tool whose name matches a locally-registered static or deferred tool. For example, an MCP server provides 'search' and the agent also has a local tool named 'search'. Also triggered by two MCP servers exposing tools with the same name (though ensureUniqueMcpToolNames may handle intra-MCP dedup first).

Common situations: Connecting to a third-party MCP server that provides generic-named tools (search, fetch, get) that overlap with custom local tools. Using multiple MCP servers with overlapping functionality. An MCP server updating its tool list to include a name that now conflicts.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/5bf0f707210f30ce. Report an issue: GitHub.