alibaba/spring-ai-alibaba · error · RuntimeException

No available endpoint found for service: <serviceName>

Error message

No available endpoint found for service: <serviceName>

What it means

handleMcpStreamProtocol asks Nacos (nacosMcpOperationService.selectEndpoint) to resolve an MCP service reference to a live endpoint. When Nacos returns null — no healthy/registered instance matches the serviceRef — the callback throws a RuntimeException naming the service, since there is no address to build the SSE/streamable URL from.

Source

Thrown at spring-boot-starters/spring-ai-alibaba-starter-config-nacos/src/main/java/com/alibaba/cloud/ai/agent/nacos/tools/NacosMcpGatewayToolCallback.java:469

				return "Error: Unsupported protocol " + protocol;
			}
		}
		catch (Exception e) {
			logger.error("[call] Unexpected error occurred", e);
			return "Error: " + e.getMessage();
		}
	}

	/**
	 * 处理MCP流式协议的工具调用 (mcp-sse, mcp-streamable)
	 */
	private String handleMcpStreamProtocol(Map<String, Object> args, McpServerRemoteServiceConfig remoteServerConfig,
			String protocol) throws NacosException {
		McpServiceRef serviceRef = remoteServerConfig.getServiceRef();
		if (serviceRef != null) {
			McpEndpointInfo mcpEndpointInfo = nacosMcpOperationService.selectEndpoint(serviceRef);
			if (mcpEndpointInfo == null) {
				throw new RuntimeException("No available endpoint found for service: " + serviceRef.getServiceName());
			}

			logger.info("[handleMcpStreamProtocol] Tool callback instance: {}", JacksonUtils.toJson(mcpEndpointInfo));
			String exportPath = remoteServerConfig.getExportPath();

			// 构建基础URL,根据协议类型调整
			String transportProtocol = StringUtils.hasText(serviceRef.getTransportProtocol()) ? serviceRef.getTransportProtocol() : "http";
			StringBuilder baseUrl;
			if ("mcp-sse".equalsIgnoreCase(protocol)) {
				baseUrl = new StringBuilder(transportProtocol + "://" + mcpEndpointInfo.getAddress() + ":" + mcpEndpointInfo.getPort());
			}
			else {
				// mcp-streamable 或其他协议
				baseUrl = new StringBuilder(transportProtocol + "://" + mcpEndpointInfo.getAddress() + ":" + mcpEndpointInfo.getPort());
			}

			logger.info("[handleMcpStreamProtocol] Processing {} protocol with args: {} and baseUrl: {}", protocol,
					args, baseUrl.toString());

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Confirm the target MCP server is running and registered in Nacos under the exact serviceName in serviceRef (check Nacos console service list).
  2. Verify namespace, group and cluster names in McpServiceRef match those the MCP server registered with.
  3. Check instance health status in Nacos; restart or re-register unhealthy instances.
  4. Wrap the tool call with retry/fallback logic since endpoint availability can be transient.

Example fix

// before
McpServiceRef ref = McpServiceRef.builder().serviceName("my-mcp").build(); // wrong namespace
// after
McpServiceRef ref = McpServiceRef.builder().serviceName("my-mcp").namespace("public").groupName("DEFAULT_GROUP").build();
Defensive patterns

Strategy: retry

Validate before calling

McpEndpointInfo ep = nacosMcpOperationService.selectEndpoint(serviceRef);
if (ep == null) { throw new IllegalStateException("Precheck: MCP service not resolvable: " + serviceRef.getServiceName()); }

Try / catch

try { return callback.call(args); }
catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("No available endpoint found")) {
        return retry.withBackoff(3, call); // endpoint discovery is transient
    }
    throw e;
}

Prevention

When it happens

Trigger: call() -> handleMcpStreamProtocol with a valid serviceRef, but selectEndpoint(serviceRef) returns null: no instance registered under that service name, all instances unhealthy/disabled, or wrong namespace/group in the McpServiceRef.

Common situations: The MCP server backing the tool is not started or has been deregistered from Nacos; namespace/group mismatch between the gateway and the MCP server; the endpoint was published to a different Nacos cluster; network partition prevents endpoint discovery.

Understand the failure class

Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.

Related errors


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