n8n-io/n8n · error · Error
MCP server " ": exactly one of "url" or "command" must be…
Error message
MCP server "${cfg.name}": exactly one of "url" or "command" must be provided What it means
Validation in the McpClient constructor over the supplied server configs. It fires when a server entry sets neither `url` (remote HTTP transport) nor `command` (local stdio transport), leaving the client unable to open any connection. Enforces the documented contract that each config must carry exactly one transport.
Solutions
- Set cfg.url for SSE/StreamableHTTP transports or cfg.command for stdio.
- Validate configs with a schema (zod) before passing to McpClient.
- Log the offending config name early to pinpoint which entry is incomplete.
Example fix
// before
new McpClient([{ name: 'fs' }]);
// after
new McpClient([{ name: 'fs', command: 'npx', args: ['@anthropic/mcp-fs', '/tmp'] }]); Defensive patterns
Strategy: validation
Validate before calling
import { z } from 'zod';
const mcpConfigSchema = z.object({
name: z.string().min(1),
url: z.string().url().optional(),
command: z.string().optional(),
}).refine((c) => Boolean(c.url) !== Boolean(c.command), {
message: 'Provide exactly one of url or command',
});
mcpConfigSchema.parse(cfg); Type guard
function hasMcpTransport(c: { url?: string; command?: string }): boolean {
return Boolean(c.url) !== Boolean(c.command);
} Prevention
- Validate McpServerConfig arrays with zod before constructing McpClient.
- Centralize config construction in a factory that requires a transport discriminator.
When it happens
Trigger: Passing { name: 'foo' } (or { name: 'foo', transport: 'sse' }) with no url and no command to new McpClient([...]).
Common situations: Building McpServerConfig from env vars where both URL and command env entries are empty; typo in config key (e.g. cmd vs command); loading from JSON whose transport field was omitted.
Related errors
- MCP server " ": provide either "url" or "command", not both
- not found
- Database type currently not supported
- Expected Supabase credentials host to be a string
- Failed to enable MCP access
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/8aafcaca74ec654f.
Report an issue: GitHub.
Appendix: source
Thrown at packages/@n8n/agents/src/sdk/mcp-client.ts:66
private listToolsPromise: Promise<BuiltTool[]> | undefined;
private closePromise: Promise<void> | undefined;
/**
* Per-server connection failures recorded during the last `listTools()`.
* Tools from these servers were skipped; the run continues with the
* remaining servers' tools. Read via `getConnectionFailures()`.
*/
private connectionFailures: McpConnectionFailedEvent[] = [];
/**
* @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));View on GitHub (pinned to 5ac6606e81)