Repository navigation
Upgrade to fastmcp 4.0.5 (fixes COR2-475 path traversal at the source) - #16
Merged
Merged
Conversation
fastmcp 4 URL-encodes OpenAPI path parameters, which removes the path-traversal vector at the source (COR2-475) rather than guarding against it. The migration is import moves only -- the OpenAPI types were relocated, not changed: MCPType and the OpenAPI component classes now live in fastmcp.server.providers.openapi, HTTPRoute in fastmcp.utilities.openapi.models. Both callback signatures are unchanged, so custom_route_mapper and customize_components keep their bodies. fastmcp 4 moves to httpx2; applications call httpx2.alias_httpx() once at startup so existing `import httpx` code shares the httpx2 classes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LZtC15RMphgMhtsoDh4i4u
The previous commit swapped the httpx dependency for httpx2 but left
`import httpx` in src/clients/cortex.py, working only because the
downstream application called httpx2.alias_httpx() first. That broke
cortex-mcp as a standalone package -- its own console script and
Dockerfile entry point import that module directly:
ModuleNotFoundError: No module named 'httpx'
The tests did not catch it because none of them import src.clients.cortex.
httpx2's alias_httpx() is documented for applications, not libraries, and
cortex-mcp is imported as a library by cortex-remote-mcp. Import httpx2
under the httpx name in this module instead, so the package is correct on
its own and no longer depends on import ordering elsewhere.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LZtC15RMphgMhtsoDh4i4u
The import-path migration left a line ruff's isort rule wants split; CI runs `ruff check src tests` and failed on it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LZtC15RMphgMhtsoDh4i4u
brucesw
approved these changes
Sep 23, 2026
brucesw
left a comment
There was a problem hiding this comment.
LGTM! Seems pretty straightforward. Thanks for taking this on.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
fastmcp 2.12.3 interpolates OpenAPI path parameters into the backend URL with a plain
str.replace, unescaped. httpx then resolves the dot-segments per RFC 3986 while building the request, so a tool argument of../../internal/usersfortagOrIdproduced a real call to/api/internal/users— carrying the caller's bearer token. That is the path traversal Cimpress reported (COR2-475, under the COR2-349 umbrella).fastmcp 4 percent-encodes path parameters, so the value stays inside a single URL segment and the traversal cannot be expressed at all. This fixes the cause rather than guarding the symptom, which is why it supersedes #15.
What changed
Import moves only — the OpenAPI types were relocated in 4.x, not redesigned:
MCPType,OpenAPITool,OpenAPIResource,OpenAPIResourceTemplate→fastmcp.server.providers.openapiHTTPRoute→fastmcp.utilities.openapi.modelsBoth callback signatures are unchanged (
RouteMapFn = Callable[[HTTPRoute, MCPType], MCPType | None]), socustom_route_mapperandcustomize_componentskeep their bodies verbatim.fastmcp 4 builds on
httpx2; the dependency is swapped accordingly. Applications callhttpx2.alias_httpx()once at startup so existingimport httpxcode shares the httpx2 classes — see cortexapps/cortex-remote-mcp#17.Testing
examplevalues from the spec). One semantic change worth a look: a singleoneOf+discriminatorbecameanyOf.tagOrId='../../internal/users'now resolves to/api/v1/catalog/%2E%2E%2F%2E%2E%2Finternal%2Fusers/openapiinstead of/api/internal/users.Merge order
This PR must merge before cortexapps/cortex-remote-mcp#17. That repo depends on
cortex-mcp @ master, and while this pinsfastmcp==2.12.3its install cannot resolve againstfastmcp>=4.0.5:Note
The removed pin comment claimed 2.12.3 was needed to fix a "PublicIdentifier schema bug." The tool-schema diff came back clean, but whoever hit that bug should confirm before merging.
🤖 Generated with Claude Code
https://claude.ai/code/session_01LZtC15RMphgMhtsoDh4i4u