alibaba/spring-ai-alibaba · error · McpNodeException

MCP call fail: {e.getMessage()}

Error message

MCP call fail: {e.getMessage()}

What it means

McpNode.apply() wraps any exception thrown while invoking the remote MCP tool (client.callTool) in a McpNodeException prefixed with 'MCP call fail:'. The original exception is chained as the cause. It signals that the MCP tool invocation itself failed — network, protocol, tool-argument, or server-side error — not that the node was misconfigured.

Source

Thrown at spring-boot-starters/spring-ai-alibaba-starter-builtin-nodes/src/main/java/com/alibaba/cloud/ai/graph/node/McpNode.java:126

		// 2. Then use params (after variable replacement) to overwrite
		Map<String, Object> replacedParams = replaceVariablesObj(params, state);
		if (replacedParams != null) {
			finalParams.putAll(replacedParams);
		}
		log.info("[McpNode] after replace params: url={}, tool={}, headers={}, params={}", url, finalTool, headers,
				finalParams);

		// Directly use the already initialized client
		CallToolResult result;
		try {
			McpSchema.CallToolRequest request = new McpSchema.CallToolRequest(finalTool, finalParams);
			log.info("[McpNode] CallToolRequest: {}", request);
			result = client.callTool(request);
			log.info("[McpNode] tool call result: {}", result);
		}
		catch (Exception e) {
			log.error("[McpNode] MCP call fail:", e);
			throw new McpNodeException("MCP call fail: " + e.getMessage(), e);
		}

		// Result handling
		Map<String, Object> updatedState = new HashMap<>();
		// updatedState.put("mcp_result", result.content());
		updatedState.put("messages", result.content());
		if (StringUtils.hasLength(this.outputKey)) {
			Object content = result.content();
			if (content instanceof List<?> list && !CollectionUtils.isEmpty(list)) {
				Object first = list.get(0);
				// Compatible with the text field of TextContent
				if (first instanceof TextContent textContent) {
					updatedState.put(this.outputKey, textContent.text());
				}
				else if (first instanceof Map<?, ?> map && map.containsKey("text")) {
					updatedState.put(this.outputKey, map.get("text"));
				}
				else {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Read the chained cause (e.getCause()) to find the root failure
  2. Verify the MCP server is running and the configured endpoint/connection is correct
  3. Confirm the tool name and arguments in the CallToolRequest match the server's tool schema
  4. Add retry/timeout handling around the node for transient network failures

Example fix

try {
    state = mcpNode.apply(state);
} catch (McpNodeException e) {
    log.error("MCP tool invocation failed", e.getCause());
    // fallback or rethrow
}
Defensive patterns

Strategy: try-catch

Validate before calling

// verify connectivity before graph run
boolean reachable = mcpEndpoint != null && !mcpEndpoint.isBlank();

Try / catch

try { state = mcpNode.apply(state); } catch (McpNodeException e) { Throwable root = e.getCause(); log.error("MCP call failed", root); }

Prevention

When it happens

Trigger: client.callTool(request) throws: MCP server unreachable, tool name not found, invalid tool arguments, timeout, or server returns a protocol error during graph execution of the McpNode.

Common situations: MCP server not running or wrong SSE/stdio endpoint; tool schema changed so arguments no longer validate; network/firewall blocking the MCP endpoint; MCP client misconfigured in application properties.

Understand the failure class

Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/9fe2005275e68a77. Report an issue: GitHub.