apache/shardingsphere · critical · IOException

Failed to start %s server.

Error message

Failed to start %s server.

What it means

MCPRuntimeLauncher.launch() builds the runtime context, chooses a StreamableHttpMCPServer or StdioMCPServer from the transport type, and calls start(); if start() throws IOException, the launcher stops the partially started server and rethrows IOException('Failed to start %s server.'), naming HTTP or STDIO. The message is a wrapper — the attached cause carries the actual transport failure.

Source

Thrown at mcp/bootstrap/src/main/java/org/apache/shardingsphere/mcp/bootstrap/MCPRuntimeLauncher.java:64

    
    /**
     * Launch.
     *
     * @param config launch configuration
     * @return MCP Server
     * @throws IOException when the active server startup fails
     */
    public MCPRuntimeServer launch(final MCPLaunchConfiguration config) throws IOException {
        ShardingSpherePreconditions.checkNotNull(config, () -> new IllegalArgumentException("MCP launch configuration cannot be null."));
        MCPRuntimeContext runtimeContext = new MCPRuntimeContext(new MCPSessionManager(config.getDatabases()), new MCPDatabaseCapabilityProvider(config.getDatabases()),
                config.getTransportType());
        MCPRuntimeServer result = isHttpTransport(config) ? new StreamableHttpMCPServer(config.getHttpTransport(), runtimeContext) : new StdioMCPServer(runtimeContext);
        try {
            result.start();
            log.info(createStartupLogMessage(config, result));
        } catch (final IOException ex) {
            result.stop();
            throw new IOException(String.format("Failed to start %s server.", isHttpTransport(config) ? "HTTP" : "STDIO"), ex);
        }
        return result;
    }
    
    private String createStartupLogMessage(final MCPLaunchConfiguration config, final MCPRuntimeServer server) {
        return isHttpTransport(config) ? createHttpStartupLogMessage(config, (StreamableHttpMCPServer) server) : createStdioStartupLogMessage(config);
    }
    
    private String createHttpStartupLogMessage(final MCPLaunchConfiguration config, final StreamableHttpMCPServer server) {
        String endpoint = String.format("http://%s:%d%s", config.getHttpTransport().getBindHost(), server.getLocalPort(), config.getHttpTransport().getEndpointPath());
        SessionAttributionResolver sessionAttributionResolver = new SessionAttributionResolver(config.getHttpTransport().getSessionAttributionSource());
        return String.format("ShardingSphere MCP Server started, transport=%s, config=%s, databases=%d, endpoint=%s, session_attribution=%s, logs=%s.",
                config.getTransportType().name().toLowerCase(Locale.ENGLISH), configPath, config.getDatabases().size(), endpoint, sessionAttributionResolver.getSummary(), LOG_PATH);
    }
    
    private String createStdioStartupLogMessage(final MCPLaunchConfiguration config) {
        return String.format("ShardingSphere MCP Server started, transport=%s, config=%s, databases=%d, logs=%s. Stdout is reserved for MCP protocol frames.",
                config.getTransportType().name().toLowerCase(Locale.ENGLISH), configPath, config.getDatabases().size(), LOG_PATH);

View on GitHub (pinned to e952770a21)

Solutions

  1. Read the cause of the IOException (getCause) — it distinguishes port-in-use, bind failure, or stream problems.
  2. Free the configured HTTP port or change it to an unused one, and set bindHost to a local interface (127.0.0.1 unless LAN exposure is intended).
  3. For STDIO transport, run the launcher attached to real stdin/stdout (no daemonization) and keep logs on stderr only.
  4. Ensure one MCP instance per endpoint; stop previous instances before relaunching.
  5. Verify write access to the temp directory the embedded server uses.

Example fix

# before
java -jar shardingsphere-mcp.jar --transport http --port 8080   # port already bound

# after
# free the port or pick another
java -jar shardingsphere-mcp.jar --transport http --bind-host 127.0.0.1 --port 18080
Defensive patterns

Strategy: try-catch

Validate before calling

// before launch, verify the HTTP port is free
try (java.net.ServerSocket probe = new java.net.ServerSocket(port, 1, InetAddress.getByName(bindHost))) { /* port free */ }

Try / catch

try { MCPRuntimeServer server = launcher.launch(config); } catch (final IOException ex) { Throwable cause = ex.getCause(); /* cause distinguishes port bind vs stdio vs temp-dir failure */ }

Prevention

When it happens

Trigger: Launching the ShardingSphere MCP server with an HTTP transport whose port is taken or bind host is invalid (delegated to the Tomcat-based server, which throws IOException), or with a STDIO transport where the standard streams cannot be acquired; any IOException from server.start() triggers the wrap after result.stop().

Common situations: Port already in use for the HTTP endpoint; bindHost set to an interface the host does not own; running in a container/sandbox where STDIO is detached; conflicting MCP instance on the same endpoint path; insufficient permission to create the temp directory used by the embedded server.

Related errors


AI-assisted analysis of apache/shardingsphere@e952770a21 (2026-08-14). Data as JSON: /api/errors/f4932b487df70265. Report an issue: GitHub.