n8n-io/n8n · error · Error

Failed to read MCP servers from endpoint: ${response.status}

Error message

Failed to read MCP servers from endpoint: ${response.status}

What it means

HTTP-status branch of Microsoft MCP server discovery in microsoft-utils. After proxyFetch(endpoint) with the Bot Framework auth headers, if response.ok is false the code throws a bare Error with the HTTP status code. This is a transport-level failure talking to the Microsoft Tooling Gateway.

Source

Thrown at packages/@n8n/nodes-langchain/nodes/vendors/Microsoft/microsoft-utils.ts:240

async function getMcpServerConfigsWithoutAudienceTokens(
	turnContext: TurnContext,
	mcpAuthToken: string,
) {
	MicrosoftToolingUtility.ValidateAuthToken(mcpAuthToken);

	const agenticAppId = MicrosoftRuntimeUtility.ResolveAgentIdentity(turnContext, mcpAuthToken);
	const endpoint = getToolingGatewayUrl(agenticAppId);
	const response = await proxyFetch(endpoint, {
		headers: MicrosoftToolingUtility.GetToolRequestHeaders(
			mcpAuthToken,
			turnContext,
			MICROSOFT_TOOL_OPTIONS,
		),
	});

	if (!response.ok) {
		throw new Error(`Failed to read MCP servers from endpoint: ${response.status}`);
	}

	const payload: unknown = await response.json();
	const rawServers = getRawMcpServers(payload);
	if (!rawServers) {
		// Log only the payload type, never the raw body: it's an untrusted external
		// response that may carry sensitive values.
		console.error('Microsoft MCP server discovery returned an unsupported payload shape', {
			payloadType: Array.isArray(payload) ? 'array' : typeof payload,
		});
		throw new Error('Failed to read MCP servers from endpoint: response is not a server list');
	}

	const servers = rawServers
		.map((rawServer) => normalizeMcpServerConfig(rawServer))
		.filter((server): server is MCPServerConfig => server !== undefined);

	console.warn(`Microsoft MCP server discovery completed: ${servers.length} servers found`);

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Decode the status: 401/403 → refresh/verify the MCP auth token and scopes; 404 → verify ResolveAgentIdentity returns the right agentic app id; 5xx → transient, retry.
  2. Confirm the Microsoft 365 agent / app registration is granted the MCP/Tooling permissions in the tenant.
  3. Check getToolingGatewayUrl() returns the expected regional endpoint for the tenant.
  4. Retry with backoff for 5xx; surface to admin for 4xx permission errors.
Defensive patterns

Strategy: retry

Type guard

function isHttpStatusError(e: unknown): e is Error {
  return e instanceof Error && /^Failed to read MCP servers from endpoint: \d{3}$/.test(e.message);
}

Try / catch

for (let attempt = 1; attempt <= 3; attempt++) {
  try { return await getMcpServerConfigsWithoutAudienceTokens(turnContext, token); }
  catch (e) {
    const status = parseInt((/^.*?(\d{3})$/.exec((e as Error).message) ?? [])[1] ?? '', 10);
    if (attempt === 3 || (status >= 400 && status < 500 && status !== 429)) throw e; // don't retry most 4xx
    await new Promise(r => setTimeout(r, 1000 * attempt));
  }
}

Prevention

When it happens

Trigger: The Tooling Gateway returns 4xx/5xx: 401/403 if the MCP auth token is expired or lacks scope, 404 if the agentic app id resolved wrong, 5xx for gateway outage, or a network-layer non-2xx from the proxy.

Common situations: MCP auth token expired between turns; the agent's app id doesn't resolve to a registered gateway; Tooling Gateway regional outage; tenant not provisioned for MCP.

Related errors


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