Bug description How does MCP Server define content path and connect to URL: localhost: port sse endpoint:/contentPath/sse using SSE after defining it? This format can be used for the first get request to connect, but for the second post request to access/mcp/message, the contentpath cannot be added, resulting in a 404 error

Environment springboot:3.4.2 jdk 17 spring-ai 1.0.0-SNAPSHOT

Steps to reproduce mcp: client: enabled: true name: mock-client version: 0.0.1 type: SYNC request-timeout: 20s sse: connections: soldier-server: url: http://localhost:port sse-endpoint: /content-path/sse

Comment From: quaff

If https://github.com/spring-projects/spring-ai/pull/3112 get merged, it should be fixed by set:

spring.ai.mcp.server.base-url: /context-path

Comment From: hbsjz-swl

If #3112 get merged, it should be fixed by set:

spring.ai.mcp.server.base-url: /context-path

The client side configuration is as follows: sse: connections: soldier-server: url: http:localhost:9526/soldier The server side configuration is as follows: spring.ai.mcp.server.name=soldier-server spring.ai.mcp.server.version=0.0.1 spring.ai.mcp.server.type=SYNC spring.ai.mcp.server.stdio=false spring.ai.mcp.server.base-url=/soldier spring.ai.mcp.server.sse-message-endpoint=/mcp/message

The client startup error is as follows: 2025-05-13 08:58:46 [ForkJoinPool.commonPool-worker-1] ERROR i.m.c.t.HttpClientSseClientTransport - SSE connection error java.util.concurrent.CompletionException: java.lang.RuntimeException: Failed to connect to SSE stream. Unexpected status code: 404 at java.base/java.util.concurrent.CompletableFuture.encodeThrowable(CompletableFuture.java:315) at java.base/java.util.concurrent.CompletableFuture.completeThrowable(CompletableFuture.java:320) at java.base/java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:722) at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:510) at java.base/java.util.concurrent.CompletableFuture.postFire(CompletableFuture.java:614) at java.base/java.util.concurrent.CompletableFuture$UniWhenComplete.tryFire(CompletableFuture.java:844) at java.base/java.util.concurrent.CompletableFuture$Completion.exec(CompletableFuture.java:483) at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373) at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182) at java.base/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655) at java.base/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622) at java.base/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165) Caused by: java.lang.RuntimeException: Failed to connect to SSE stream. Unexpected status code: 404 at io.modelcontextprotocol.client.transport.FlowSseClient.lambda$subscribe$2(FlowSseClient.java:202) at java.base/java.util.concurrent.CompletableFuture$UniAccept.tryFire(CompletableFuture.java:718) ... 9 common frames omitted

On the client side HttpClientSseClientTransport (line 417) The pseudo code is as follows:

URI requestUri = Utils.resolveUri(http://localhost:9526/soldier, /mcp/message?sessionId=cb613423-7fd1-413f-a2c0-89949d79f7e7) requestUri ignores /soldier http://localhost:9526/mcp/message?sessionId=a20245aa-8271-4c56-8365-d8f5503e4c7e

Comment From: quaff

Please note it's not merged yet, are you testing against that branch?

Comment From: hbsjz-swl

Please note it's not merged yet, are you testing against that branch?

Sorry, I just noticed that the merge request has been approved, I should wait for this fix before trying it again, thank you very much for your help!

Comment From: tzolov

@hbsjz-swl the https://github.com/spring-projects/spring-ai/pull/3112 has been merged. Could you please give it a try again

Comment From: tzolov

Closing this issue as resolved by #3112. Please feel free to re-open if the issue is still present

Comment From: hbsjz-swl

@tzolov @quaff I have verified it locally and this modification is effective. The following configuration is added on the service side: spring.ai.mcp.server.base-url=/soldier The following configuration is added on the client side: sse: connections: soldier-server: url: http://localhost:9526 sse-endpoint: /soldier/sse

Image

Thank you very much for your help