Skip to content

Fix nested path URI resolution#974

Open
Qshuai0213 wants to merge 2 commits into
modelcontextprotocol:mainfrom
Qshuai0213:fix/resolve-uri-nested-paths
Open

Fix nested path URI resolution#974
Qshuai0213 wants to merge 2 commits into
modelcontextprotocol:mainfrom
Qshuai0213:fix/resolve-uri-nested-paths

Conversation

@Qshuai0213
Copy link
Copy Markdown

@Qshuai0213 Qshuai0213 commented May 19, 2026

Summary

Fixes #257

Utils.resolveUri incorrectly handled nested base paths — relative endpoints with a leading slash (e.g. /api/v1) would replace the base path entirely instead of being appended to it. This affected HttpClientSseClientTransport and HttpClientStreamableHttpTransport when the base URL had a non-root path (e.g. https://example.com/some).

Root cause

URI.resolve() follows RFC 3986 §5.2.3: when the relative reference starts with /, it replaces the entire path of the base URI. So URI.create("https://example.com/some").resolve("/path") yields https://example.com/path, dropping /some.

Fix approach

  • Ensure the base URL always has a trailing slash (e.g. /root/root/)
  • Strip leading slashes from the endpoint (e.g. /api/v1api/v1)
  • URI.resolve() then performs path concatenation (/root/ + api/v1 = /root/api/v1), consistent with RFC 3986
  • Absolute endpoint validation behavior is preserved unchanged

Testing

  • ./mvnw.cmd -pl mcp-core -Dtest=UtilsTests test
  • ./mvnw.cmd -pl mcp-core test
  • Added parameterized test cases covering: nested base paths, leading/trailing slashes, and query strings

@Qshuai0213
Copy link
Copy Markdown
Author

@chemicL Hi, since you've looked into this issue in both #257 and #701, could you take a look at this PR when you have time? Happy to adjust the approach if needed. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

io.modelcontextprotocol.util.Utils#resolveUri incorrectly handles nested paths

1 participant