{"record":{"id":"cf538bb3c718c091","repo":"spring-projects/spring-ai","slug":"sse-connection-connectionname-requires-a-url","errorCode":null,"errorMessage":"SSE connection '<connectionName>' requires a 'url' property. Example: url: http://localhost:3000","messagePattern":"SSE connection '<connectionName>' requires a 'url' property\\. Example: url: http://localhost:3000","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/src/main/java/org/springframework/ai/mcp/client/httpclient/autoconfigure/SseHttpClientTransportAutoConfiguration.java","lineNumber":115,"sourceCode":"\t * @return list of named MCP transports\n\t */\n\t@Bean\n\tpublic List<NamedClientMcpTransport> sseHttpClientTransports(McpSseClientConnectionDetails connectionDetails,\n\t\t\tObjectProvider<JsonMapper> jsonMapperProvider,\n\t\t\tObjectProvider<McpClientCustomizer<HttpClientSseClientTransport.Builder>> transportCustomizers) {\n\n\t\tJsonMapper jsonMapper = jsonMapperProvider.getIfAvailable(JsonMapper::new);\n\n\t\tList<NamedClientMcpTransport> sseTransports = new ArrayList<>();\n\n\t\tfor (Map.Entry<String, SseParameters> serverParameters : connectionDetails.getConnections().entrySet()) {\n\t\t\tString connectionName = serverParameters.getKey();\n\t\t\tSseParameters params = serverParameters.getValue();\n\n\t\t\tString baseUrl = params.url();\n\t\t\tString sseEndpoint = params.sseEndpoint() != null ? params.sseEndpoint() : \"/sse\";\n\t\t\tif (baseUrl == null || baseUrl.trim().isEmpty()) {\n\t\t\t\tthrow new IllegalArgumentException(\"SSE connection '\" + connectionName\n\t\t\t\t\t\t+ \"' requires a 'url' property. Example: url: http://localhost:3000\");\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tvar transportBuilder = HttpClientSseClientTransport.builder(baseUrl)\n\t\t\t\t\t.sseEndpoint(sseEndpoint)\n\t\t\t\t\t.clientBuilder(HttpClient.newBuilder())\n\t\t\t\t\t.jsonMapper(new JacksonMcpJsonMapper(jsonMapper));\n\n\t\t\t\tfor (McpClientCustomizer<HttpClientSseClientTransport.Builder> customizer : transportCustomizers) {\n\t\t\t\t\tcustomizer.customize(connectionName, transportBuilder);\n\t\t\t\t}\n\n\t\t\t\tsseTransports.add(new NamedClientMcpTransport(connectionName, transportBuilder.build()));\n\t\t\t}\n\t\t\tcatch (Exception e) {\n\t\t\t\tthrow new IllegalArgumentException(\"Failed to create SSE transport for connection '\" + connectionName\n\t\t\t\t\t\t+ \"'. Check URL splitting: url='\" + baseUrl + \"', sse-endpoint='\" + sseEndpoint","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/auto-configurations/mcp/spring-ai-autoconfigure-mcp-client-httpclient/src/main/java/org/springframework/ai/mcp/client/httpclient/autoconfigure/SseHttpClientTransportAutoConfiguration.java#L97-L133","documentation":"SseHttpClientTransportAutoConfiguration builds SSE transports from the spring.ai.mcp.client.sse.connections map. Each named connection must declare a 'url' property; when the URL is null or blank, the configuration fails fast with this IllegalArgumentException naming the offending connection and showing the expected format.","triggerScenarios":"Defining an MCP SSE connection under spring.ai.mcp.client.sse.connections.<name> without a url key, or with an empty/whitespace-only url, at application startup.","commonSituations":"Typo in the property key (e.g. 'uri' or 'server-url' instead of 'url'), YAML indentation placing url under the wrong connection, environment-variable placeholders (URL_REPLACED or ${...}) resolving to empty, or copy-pasted config where url was deleted.","solutions":["Add the url key to the connection: spring.ai.mcp.client.sse.connections.<name>.url=http://localhost:3000","Check YAML indentation so url sits directly under the correct connection name.","Verify any environment placeholder in the value resolves to a non-empty value at runtime.","Fix key typos — the property must be exactly 'url' (sse-endpoint is optional and defaults to /sse)."],"exampleFix":"# before\nspring:\n  ai:\n    mcp:\n      client:\n        sse:\n          connections:\n            server1:\n              sse-endpoint: /sse\n\n# after\nspring:\n  ai:\n    mcp:\n      client:\n        sse:\n          connections:\n            server1:\n              url: http://localhost:3000\n              sse-endpoint: /sse","handlingStrategy":"validation","validationCode":"spring.ai.mcp.client.sse.connections.forEach((name, p) -> {\n    if (p.url() == null || p.url().trim().isEmpty()) {\n        throw new IllegalArgumentException(\"SSE connection '\" + name + \"' requires a 'url' property\");\n    }\n});","typeGuard":"boolean hasValidUrl(SseParameters p) { return p != null && p.url() != null && !p.url().trim().isEmpty(); }","tryCatchPattern":"try {\n    context = SpringApplication.run(App.class, args);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().startsWith(\"SSE connection\")) {\n        // add the missing url to the named connection in application.yml\n    }\n    throw e;\n}","preventionTips":["Always set url for every named SSE connection","Keep property key exactly 'url' — avoid uri/server-url typos","Check YAML indentation when nesting connection properties","Verify env placeholders used in url resolve at runtime"],"tags":["mcp","sse","configuration","startup","validation"],"backgroundTag":"missing-required-config-field","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}