== Streamable-HTTP MCP Servers The link:https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http[Streamable HTTP transport] allows MCP servers to operate as independent processes that can handle multiple client connections using HTTP POST and GET requests, with optional Server-Sent Events (SSE) streaming for multiple server messages. It replaces the SSE transport. These servers, introduced with spec version link:https://modelcontextprotocol.io/specification/2025-03-26[2025-03-26], are ideal for applications that need to notify clients about dynamic changes to tools, resources, or prompts. TIP: Set the `spring.ai.mcp.server.protocol=STREAMABLE` property TIP: Use the xref:api/mcp/mcp-client-boot-starter-docs#_streamable_http_transport_properties[Streamable-HTTP clients] to connect to the Streamable-HTTP servers. === Streamable-HTTP WebMVC Server Use the `spring-ai-starter-mcp-server-webmvc` dependency: [source,xml] ---- org.springframework.ai spring-ai-starter-mcp-server-webmvc ---- and set the `spring.ai.mcp.server.protocol` property to `STREAMABLE`. * Full MCP server capabilities with Spring MVC Streamable transport * Support for tools, resources, prompts, completion, logging, progression, ping, root-changes capabilities * Persistent connection management === Streamable-HTTP WebFlux Server Use the `spring-ai-starter-mcp-server-webflux` dependency: [source,xml] ---- org.springframework.ai spring-ai-starter-mcp-server-webflux ---- and set the `spring.ai.mcp.server.protocol` property to `STREAMABLE`. * Reactive MCP server with WebFlux Streamable transport * Support for tools, resources, prompts, completion, logging, progression, ping, root-changes capabilities * Non-blocking, persistent connection management == Configuration Properties === Common Properties All common properties are prefixed with `spring.ai.mcp.server`: [options="header"] |=== |Property |Description |Default |`enabled` |Enable/disable the streamable MCP server |`true` |`protocol` |MCP server protocol | Must be set to `STREAMABLE` to enable the streamable server |`tool-callback-converter` |Enable/disable the conversion of Spring AI ToolCallbacks into MCP Tool specs |`true` |`name` |Server name for identification |`mcp-server` |`version` |Server version |`1.0.0` |`instructions` |Optional instructions for client interaction |`null` |`type` |Server type (SYNC/ASYNC) |`SYNC` |`capabilities.resource` |Enable/disable resource capabilities |`true` |`capabilities.tool` |Enable/disable tool capabilities |`true` |`capabilities.prompt` |Enable/disable prompt capabilities |`true` |`capabilities.completion` |Enable/disable completion capabilities |`true` |`resource-change-notification` |Enable resource change notifications |`true` |`prompt-change-notification` |Enable prompt change notifications |`true` |`tool-change-notification` |Enable tool change notifications |`true` |`expose-mcp-client-tools` |Whether to re-expose downstream MCP tools (provided by MCP clients) as tools in this MCP server |`false` |`tool-response-mime-type` |Response MIME type per tool name |`-` |`request-timeout` |Request timeout duration |`20 seconds` |=== === MCP Annotations Properties MCP Server Annotations provide a declarative way to implement MCP server handlers using Java annotations. The server mcp-annotations properties are prefixed with `spring.ai.mcp.server.annotation-scanner`: [cols="3,4,3"] |=== |Property |Description |Default Value |`enabled` |Enable/disable the MCP server annotations auto-scanning |`true` |=== === Streamable-HTTP Properties All streamable-HTTP properties are prefixed with `spring.ai.mcp.server.streamable-http`: [options="header"] |=== |Property |Description |Default |`mcp-endpoint` |Custom MCP endpoint path |`/mcp` |`keep-alive-interval` |Connection keep-alive interval |`null` (disabled) |`disallow-delete` |Disallow delete operations |`false` |=== == Features and Capabilities The MCP Server supports four main capability types that can be individually enabled or disabled: - **Tools** - Enable/disable tool capabilities with `spring.ai.mcp.server.capabilities.tool=true|false` - **Resources** - Enable/disable resource capabilities with `spring.ai.mcp.server.capabilities.resource=true|false` - **Prompts** - Enable/disable prompt capabilities with `spring.ai.mcp.server.capabilities.prompt=true|false` - **Completions** - Enable/disable completion capabilities with `spring.ai.mcp.server.capabilities.completion=true|false` All capabilities are enabled by default. Disabling a capability will prevent the server from registering and exposing the corresponding features to clients. The MCP Server Boot Starter allows servers to expose tools, resources, and prompts to clients. It automatically converts custom capability handlers registered as Spring beans to sync/async specifications based on the server type: === link:https://modelcontextprotocol.io/specification/2025-03-26/server/tools[Tools] Allows servers to expose tools that can be invoked by language models. The MCP Server Boot Starter provides: * Change notification support * xref:api/tools.adoc[Spring AI Tools] are automatically converted to sync/async specifications based on the server type * Automatic tool specification through Spring beans: [source,java] ---- @Bean public ToolCallbackProvider myTools(...) { List tools = ... return ToolCallbackProvider.from(tools); } ---- or using the low-level API: [source,java] ---- @Bean public List myTools(...) { List tools = ... return tools; } ---- The auto-configuration will automatically detect and register all tool callbacks from: - Individual `ToolCallback` beans - Lists of `ToolCallback` beans - `ToolCallbackProvider` beans Tools are de-duplicated by name, with the first occurrence of each tool name being used. TIP: You can disable the automatic detection and registration of all tool callbacks by setting the `tool-callback-converter` to `false`. ==== Tool Context Support The xref:api/tools.adoc#tool-context[ToolContext] is supported, allowing contextual information to be passed to tool calls. It contains an `McpSyncServerExchange` instance under the `exchange` key, accessible via `McpToolUtils.getMcpExchange(toolContext)`. See this https://github.com/spring-projects/spring-ai-examples/blob/3fab8483b8deddc241b1e16b8b049616604b7767/model-context-protocol/sampling/mcp-weather-webmvc-server/src/main/java/org/springframework/ai/mcp/sample/server/WeatherService.java#L59-L126[example] demonstrating `exchange.loggingNotification(...)` and `exchange.createMessage(...)`. === link:https://modelcontextprotocol.io/specification/2025-03-26/server/resources/[Resources] Provides a standardized way for servers to expose resources to clients. * Static and dynamic resource specifications * Optional change notifications * Support for resource templates * Automatic conversion between sync/async resource specifications * Automatic resource specification through Spring beans: [source,java] ---- @Bean public List myResources(...) { var systemInfoResource = McpSchema.Resource.builder(...); var resourceSpecification = new McpServerFeatures.SyncResourceSpecification(systemInfoResource, (exchange, request) -> { try { var systemInfo = Map.of(...); String jsonContent = new JsonMapper().writeValueAsString(systemInfo); return McpSchema.ReadResourceResult.builder( List.of(McpSchema.TextResourceContents.builder(request.uri(), jsonContent).mimeType("application/json").build())).build(); } catch (Exception e) { throw new RuntimeException("Failed to generate system info", e); } }); return List.of(resourceSpecification); } ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/server/prompts/[Prompts] Provides a standardized way for servers to expose prompt templates to clients. * Change notification support * Template versioning * Automatic conversion between sync/async prompt specifications * Automatic prompt specification through Spring beans: [source,java] ---- @Bean public List myPrompts() { var prompt = McpSchema.Prompt.builder("greeting").description("A friendly greeting prompt") .arguments(List.of(McpSchema.PromptArgument.builder("name").title("The name to greet").required(true).build())).build(); var promptSpecification = new McpServerFeatures.SyncPromptSpecification(prompt, (exchange, getPromptRequest) -> { String nameArgument = (String) getPromptRequest.arguments().get("name"); if (nameArgument == null) { nameArgument = "friend"; } var userMessage = PromptMessage.builder(Role.USER, TextContent.builder("Hello " + nameArgument + "! How can I assist you today?").build()).build(); return GetPromptResult.builder(List.of(userMessage)).description("A personalized greeting message").build(); }); return List.of(promptSpecification); } ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/completion/[Completions] Provides a standardized way for servers to expose completion capabilities to clients. * Support for both sync and async completion specifications * Automatic registration through Spring beans: [source,java] ---- @Bean public List myCompletions() { var completion = new McpServerFeatures.SyncCompletionSpecification( McpSchema.PromptReference.builder( "code-completion").title("Provides code completion suggestions").build(), (exchange, request) -> { // Implementation that returns completion suggestions return new McpSchema.CompleteResult(List.of("python", "pytorch", "pyside"), 10, true); } ); return List.of(completion); } ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/server/utilities/logging/[Logging] Provides a standardized way for servers to send structured log messages to clients. From within the tool, resource, prompt or completion call handler use the provided `McpSyncServerExchange`/`McpAsyncServerExchange` `exchange` object to send logging messages: [source,java] ---- (exchange, request) -> { exchange.loggingNotification(LoggingMessageNotification.builder(LoggingLevel.INFO, "This is a test log message") .logger("test-logger") .build()); } ---- On the MCP client you can register xref::api/mcp/mcp-client-boot-starter-docs#_customization_types[logging consumers] to handle these messages: [source,java] ---- mcpClientSpec.loggingConsumer((McpSchema.LoggingMessageNotification log) -> { // Handle log messages }); ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/basic/utilities/progress[Progress] Provides a standardized way for servers to send progress updates to clients. From within the tool, resource, prompt or completion call handler use the provided `McpSyncServerExchange`/`McpAsyncServerExchange` `exchange` object to send progress notifications: [source,java] ---- (exchange, request) -> { exchange.progressNotification(ProgressNotification.builder("test-progress-token", 0.25) .total(1.0) .message("tool call in progress") .build()); } ---- The Mcp Client can receive progress notifications and update its UI accordingly. For this it needs to register a progress consumer. [source,java] ---- mcpClientSpec.progressConsumer((McpSchema.ProgressNotification progress) -> { // Handle progress notifications }); ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/client/roots#root-list-changes[Root List Changes] When roots change, clients that support `listChanged` send a root change notification. * Support for monitoring root changes * Automatic conversion to async consumers for reactive applications * Optional registration through Spring beans [source,java] ---- @Bean public BiConsumer> rootsChangeHandler() { return (exchange, roots) -> { logger.info("Registering root resources: {}", roots); }; } ---- === link:https://modelcontextprotocol.io/specification/2025-03-26/basic/utilities/ping/[Ping] Ping mechanism for the server to verify that its clients are still alive. From within the tool, resource, prompt or completion call handler use the provided `McpSyncServerExchange`/`McpAsyncServerExchange` `exchange` object to send ping messages: [source,java] ---- (exchange, request) -> { exchange.ping(); } ---- === Keep Alive Server can optionally, periodically issue pings to connected clients to verify connection health. By default, keep-alive is disabled. To enable keep-alive, set the `keep-alive-interval` property in your configuration: [source,yaml] ---- spring: ai: mcp: server: streamable-http: keep-alive-interval: 30s ---- NOTE: Currently, for streamable-http servers, the keep-alive mechanism is available only for the link:https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#listening-for-messages-from-the-server[Listening for Messages from the Server (SSE)] connection. == Usage Examples === Streamable HTTP Server Configuration [source,yaml] ---- # Using spring-ai-starter-mcp-server-streamable-webmvc spring: ai: mcp: server: protocol: STREAMABLE name: streamable-mcp-server version: 1.0.0 type: SYNC instructions: "This streamable server provides real-time notifications" resource-change-notification: true tool-change-notification: true prompt-change-notification: true streamable-http: mcp-endpoint: /api/mcp keep-alive-interval: 30s ---- === Creating a Spring Boot Application with MCP Server [source,java] ---- @Service public class WeatherService { @Tool(description = "Get weather information by city name") public String getWeather(String cityName) { // Implementation } } @SpringBootApplication public class McpServerApplication { private static final Logger logger = LoggerFactory.getLogger(McpServerApplication.class); public static void main(String[] args) { SpringApplication.run(McpServerApplication.class, args); } @Bean public ToolCallbackProvider weatherTools(WeatherService weatherService) { return MethodToolCallbackProvider.builder().toolObjects(weatherService).build(); } } ---- The auto-configuration will automatically register the tool callbacks as MCP tools. You can have multiple beans producing ToolCallbacks, and the auto-configuration will merge them.