n8n-io/n8n · error · Error

MCP server name "${cfg.name}" is already registered

Error message

MCP server name "${cfg.name}" is already registered

What it means

Thrown by the McpClient constructor when two McpServerConfig entries share the same name. The name is used as a tool-name prefix and as the connection key, so duplicates would collide in the surfaced tool namespace.

Source

Thrown at packages/@n8n/agents/src/sdk/mcp-client.ts:78

	 * @param configs - Server configurations. Each must have either `url` or `command`.
	 *   Duplicate names within the list are rejected.
	 */
	constructor(configs: McpServerConfig[]) {
		for (const cfg of configs) {
			if (!cfg.url && !cfg.command) {
				throw new Error(
					`MCP server "${cfg.name}": exactly one of "url" or "command" must be provided`,
				);
			}
			if (cfg.url && cfg.command) {
				throw new Error(`MCP server "${cfg.name}": provide either "url" or "command", not both`);
			}
		}

		const seen = new Set<string>();
		for (const cfg of configs) {
			if (seen.has(cfg.name)) {
				throw new Error(`MCP server name "${cfg.name}" is already registered`);
			}
			seen.add(cfg.name);
		}

		this.configs = configs;
		this.connections = configs.map((cfg) => new McpConnection(cfg));
	}

	/**
	 * Returns the names of all configured MCP servers. Does NOT require a
	 * network connection — safe to call before `listTools()` or `connect()`.
	 */
	get serverNames(): string[] {
		return this.configs.map((cfg) => cfg.name);
	}

	/**
	 * Explicitly connect to all servers without listing tools.

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Give each server a unique name (the name prefixes tool names, so pick something descriptive).
  2. De-duplicate configs by name before constructing McpClient.
  3. If you intended to replace a server, filter the older entry out before adding the new one.

Example fix

// before
new McpClient([
  { name: 'fs', command: 'npx', args: ['@anthropic/mcp-fs', '/a'] },
  { name: 'fs', command: 'npx', args: ['@anthropic/mcp-fs', '/b'] },
]);
// after
new McpClient([
  { name: 'fs-a', command: 'npx', args: ['@anthropic/mcp-fs', '/a'] },
  { name: 'fs-b', command: 'npx', args: ['@anthropic/mcp-fs', '/b'] },
]);
Defensive patterns

Strategy: validation

Validate before calling

function assertUniqueNames(configs: { name: string }[]) {
  const seen = new Set<string>();
  for (const c of configs) {
    if (seen.has(c.name)) throw new Error(`Duplicate MCP server name: ${c.name}`);
    seen.add(c.name);
  }
}

Type guard

function mcpNamesUnique(configs: { name: string }[]): boolean {
  return new Set(configs.map((c) => c.name)).size === configs.length;
}

Prevention

When it happens

Trigger: Passing an array with two entries whose .name is identical, e.g. [{ name: 'fs', ... }, { name: 'fs', ... }].

Common situations: Concatenating two config lists that both define a 'fs' server; loading MCP config from multiple sources without de-duplicating by name; copy-paste of a server block.

Related errors


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