There is no option to expose MCP tools/resources/prompt with webmvc without sse sessions. That is something supported in other languages, like fastmcp with python new FastMCP( ... stateless_http=True)

Expected Behavior

Client should be able to send POST like below to get list of tools or execute a tool without sessionId.

curl -X POST http://<MCP_SERVER_HOST>:<PORT>/mcp \
-H "Content-Type: application/json" \
-d '{
    "jsonrpc": "2.0",
    "method": "tools/list",
    "params": {},
    "id": 1
}'

Current Behavior

Client has to establish session with /sse endpoint first or use STDIO.

Context

Not able to expose MCP server easily with Spring AI.

Comment From: quaff

See https://docs.spring.io/spring-ai/reference/1.1-SNAPSHOT/api/mcp/mcp-stateless-server-boot-starter-docs.html

Comment From: pavelorehov

That is great, I tried to use that but seems not working.

maven

<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-server-webmvc</artifactId>
        <version>1.1.0-SNAPSHOT</version>
</dependency>

config

spring.ai.mcp.server.name=demo-mcp-server
spring.ai.mcp.server.version=1.0.0
spring.ai.mcp.server.type=ASYNC
spring.ai.mcp.server.instructions="This server provides Demo information tools, resources and prompts"
spring.ai.mcp.server.streamable-http.mcp-endpoint=/mcp
spring.ai.mcp.server.protocol=STATELESS
spring.ai.mcp.server.capabilities.tool=true

mcp

@Service
public class TestMCPService {

    @Tool(returnDirect = true, description = "Test 1 descr.")
    public Map<String, String> getTest1() {
        return Map.of("a", "b");
    }
}

app

@Bean
public ToolCallbackProvider testMCPTools(TestMCPService service) {
    return MethodToolCallbackProvider.builder().toolObjects(service).build();
}

POST

http://localhost:8080/mcp
{
    "jsonrpc": "2.0",
    "id": 0,
    "method": "getTest1",
    "params": {}
}

error

2025-08-26 04:31:26 DEBUG o.s.web.servlet.DispatcherServlet - POST "/mcp", parameters={}
2025-08-26 04:31:26 DEBUG o.s.w.s.f.s.RouterFunctionMapping - Mapped to io.modelcontextprotocol.server.transport.WebMvcStatelessServerTransport$$Lambda$1035/0x000000080100b928@4b265bfc
2025-08-26 04:31:26 DEBUG o.s.web.servlet.DispatcherServlet - Completed 400 BAD_REQUEST


Comment From: quaff

Have you tried with curl like you posted?

Comment From: pavelorehov

Have you tried with curl like you posted?

Yes, sent above POST request with Postman/curl and got the BAD_REQUEST as shown in logs

Comment From: quaff

Please try -H "Accept: application/json, text/event-stream".

Comment From: pavelorehov

Please try -H "Accept: application/json, text/event-stream".

That helped and tools/list started to work but actual tool still does not work.

2025-08-26 17:36:55 DEBUG o.s.web.servlet.DispatcherServlet - POST "/mcp", parameters={}
2025-08-26 17:36:55 DEBUG o.s.w.s.f.s.RouterFunctionMapping - Mapped to io.modelcontextprotocol.server.transport.WebMvcStatelessServerTransport$$Lambda$1035/0x000000080102a5a8@64d5580e
2025-08-26 17:36:55 DEBUG i.m.spec.McpSchema - Received JSON message: {
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/list",
    "params": {}
}
2025-08-26 17:36:55 DEBUG o.s.web.servlet.DispatcherServlet - Completed 200 OK
2025-08-26 17:36:59 DEBUG o.s.web.servlet.DispatcherServlet - POST "/mcp", parameters={}
2025-08-26 17:36:59 DEBUG o.s.w.s.f.s.RouterFunctionMapping - Mapped to io.modelcontextprotocol.server.transport.WebMvcStatelessServerTransport$$Lambda$1035/0x000000080102a5a8@64d5580e
2025-08-26 17:36:59 DEBUG i.m.spec.McpSchema - Received JSON message: {
    "jsonrpc": "2.0",
    "id": 3,
    "method": "getTest1",
    "params": {}
}
2025-08-26 17:36:59 ERROR i.m.s.t.WebMvcStatelessServerTransport - Failed to handle request: Missing handler for request type: getTest1
2025-08-26 17:37:00 DEBUG o.s.web.servlet.DispatcherServlet - Completed 500 INTERNAL_SERVER_ERROR

tools response

{
    "jsonrpc": "2.0",
    "id": 2,
    "result": {
        "tools": [
            {
                "name": "getTest1",
                "description": "Test 1 descr.",
                "inputSchema": {
                    "type": "object",
                    "properties": {},
                    "required": [],
                    "additionalProperties": false
                }
            }
        ]
    }
}

Comment From: pavelorehov

Any updates why actual getTest1 tool invocation does not work ? See above details and error.