Skip to content

Update dependencies to latest versions with upper bounds#60

Open
druvv wants to merge 1 commit intopunitarani:mainfrom
druvv:fix/fastmcp-v3-compat
Open

Update dependencies to latest versions with upper bounds#60
druvv wants to merge 1 commit intopunitarani:mainfrom
druvv:fix/fastmcp-v3-compat

Conversation

@druvv
Copy link
Copy Markdown

@druvv druvv commented Mar 27, 2026

Summary

  • Pin all dependencies with upper bounds to prevent breaking major version upgrades (e.g., fastmcp>=3.0.0,<4 instead of fastmcp>=0.1.0)
  • Upgrade fastmcp to v3.x and remove the custom FliMCP subclass that relied on fastmcp internals (_tool_manager, _mcp_server) which no longer exist in v3
  • Use native FastMCP 3.x tool annotations and @mcp.prompt() decorators instead

Motivation

Running pip install flights and then fli-mcp fails because the loose fastmcp>=0.1.0 pin resolves to v3.x, but the MCP server code uses v2 internal APIs (_tool_manager.add_tool, _tool_manager.list_tools) that were removed. Adding upper bounds on all deps prevents similar breakage in the future.

Test plan

  • fli-mcp starts and responds to initialize JSON-RPC
  • tools/list returns both search_flights and search_dates with annotations
  • prompts/list returns both search-direct-flight and find-budget-window
  • search_flights tool executes a real flight search successfully

Greptile Summary

This PR fixes a real install-time breakage: the loose fastmcp>=0.1.0 pin was silently resolving to v3.x, but FliMCP used removed v2 internals (_tool_manager, _mcp_server). The fix is two-pronged — add explicit upper bounds to all dependencies and rewrite the MCP server to use FastMCP 3.x native decorators (@mcp.tool(annotations=...), @mcp.prompt()), removing the now-unnecessary FliMCP subclass entirely.

Key changes:

  • FliMCP subclass removed; plain FastMCP is used, eliminating all fragile internal-API access
  • Tool annotations are now passed as a dict to @mcp.tool(annotations={...}), which FastMCP 3.x accepts natively
  • Prompt builders now return str (FastMCP 3.x wraps it automatically) instead of constructing list[PromptMessage] manually
  • All direct dependencies now carry upper bounds; fastmcp is pinned to >=3.0.0,<4

Findings:

  • pydantic-settings is imported directly in server.py but is not listed as an explicit dependency — it's currently available as a transitive dep of fastmcp, but this is fragile
  • Several pre-1.0 packages (fastapi, uvicorn, typer, httpx, curl-cffi) use <1 as the upper bound, which does not protect against breaking changes between 0.x minor versions
  • Dev dependencies in the [project.optional-dependencies] dev group have no upper bounds, inconsistent with the PR's stated goal

Confidence Score: 5/5

Safe to merge — the core FastMCP v2 → v3 migration is correct and all remaining findings are P2 style/best-practice suggestions that do not block functionality.

The critical breakage (missing v2 internal APIs) is fully resolved by the migration to FastMCP 3.x native decorators. All three findings are P2: one missing transitive dep declaration, one note about the completeness of the <1 upper-bound strategy for 0.x packages, and an inconsistency in dev deps. None of these affect runtime correctness of the MCP server.

pyproject.toml — missing pydantic-settings direct dep and incomplete upper-bound coverage for pre-1.0 packages

Important Files Changed

Filename Overview
fli/mcp/server.py Removes the custom FliMCP subclass that relied on removed FastMCP v2 internals and replaces it with native FastMCP 3.x decorators (@mcp.tool with annotations dict, @mcp.prompt returning str). Migration looks correct and clean.
pyproject.toml Updates all dependencies with upper bounds; bumps fastmcp to >=3.0.0,<4. Several packages still in 0.x use <1 as their upper bound (fastapi, uvicorn, typer, httpx, curl-cffi), which does not protect against breaking changes between 0.x minor releases. pydantic-settings is a direct import in server.py but is missing from the dependency list.
uv.lock Lock file regenerated to reflect the updated dependency set for FastMCP 3.x and other bumped packages. No issues found.

Sequence Diagram

sequenceDiagram
    participant Client as MCP Client
    participant Server as FastMCP Server
    participant Tool as @mcp.tool()
    participant Search as SearchFlights/SearchDates
    participant Prompt as @mcp.prompt()

    Client->>Server: tools/list
    Server-->>Client: [search_flights, search_dates] + ToolAnnotations

    Client->>Server: tools/call search_flights(params)
    Server->>Tool: search_flights(origin, dest, date, ...)
    Tool->>Search: _execute_flight_search(FlightSearchParams)
    Search-->>Tool: list[FlightResult]
    Tool-->>Server: dict[str, Any]
    Server-->>Client: JSON result

    Client->>Server: prompts/list
    Server-->>Client: [search-direct-flight, find-budget-window]

    Client->>Server: prompts/get search-direct-flight(args)
    Server->>Prompt: search_direct_flight_prompt(origin, dest, date, ...)
    Prompt-->>Server: str (FastMCP wraps into PromptMessage)
    Server-->>Client: GetPromptResult
Loading

Comments Outside Diff (1)

  1. pyproject.toml, line 41-50 (link)

    P2 Dev dependencies lack upper bounds

    The [project.optional-dependencies] dev group still has no upper bounds on any of its packages, which is inconsistent with the goal stated in the PR. While dev deps don't affect end-users, a future pytest major bump (for example) could silently break the CI test suite in the same way fastmcp 3.x broke the MCP server. Consider applying the same <NEXT_MAJOR bound pattern here for consistency.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (1): Last reviewed commit: "Update dependencies to latest versions w..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

Pin all dependencies with upper bounds to prevent breaking major version
upgrades. Upgrade fastmcp from >=0.1.0 to >=3.0.0,<4 and remove the
custom FliMCP subclass that relied on fastmcp internals (_tool_manager,
_mcp_server) which no longer exist in v3. The native FastMCP 3.x API
supports tool annotations and prompt decorators directly, so the
subclass was replaced with plain FastMCP usage.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@punitarani punitarani marked this pull request as ready for review March 28, 2026 22:45
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Comment on lines +26 to +37
"curl-cffi>=0.13.0,<1",
"fastapi>=0.116.0,<1",
"fastmcp>=3.0.0,<4",
"httpx>=0.28.1,<1",
"pandas>=2.3.0,<3",
"plotext>=5.3.2,<6",
"pydantic>=2.11.0,<3",
"python-dotenv>=1.1.0,<2",
"ratelimit>=2.2.1,<3",
"tenacity>=9.1.0,<10",
"typer>=0.16.0,<1",
"uvicorn>=0.35.0,<1",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 <1 upper bounds don't protect against within-0.x breaking changes

Several dependencies are still in the 0.x release series (fastapi, uvicorn, typer, httpx, curl-cffi). Per SemVer convention, pre-1.0 packages may introduce breaking changes between minor versions (e.g. 0.116.00.200.0). The <1 upper bound prevents an upgrade to 1.x, but it still allows any future 0.x release, which could carry breaking changes — the same class of problem this PR is trying to prevent.

The stated motivation is preventing breakage like fastmcp 0.x → 3.x, where <1 would indeed have caught it. For fastapi, uvicorn, typer, etc. however, a stricter compatible-release constraint (e.g. ~=0.116.0 or >=0.116.0,<0.117.0) would fully close that gap. Alternatively, this tradeoff is acceptable if the intent is only to guard against major-series jumps — worth a note in the PR description for future maintainers.

Comment on lines 25 to 38
dependencies = [
"curl-cffi>=0.7.4",
"fastapi>=0.115.6",
"fastmcp>=0.1.0",
"httpx>=0.28.1",
"pandas>=2.2.3",
"plotext>=5.3.2",
"pydantic>=2.10.4",
"python-dotenv>=1.0.1",
"ratelimit>=2.2.1",
"tenacity>=9.0.0",
"typer>=0.15.1",
"uvicorn>=0.34.0",
"curl-cffi>=0.13.0,<1",
"fastapi>=0.116.0,<1",
"fastmcp>=3.0.0,<4",
"httpx>=0.28.1,<1",
"pandas>=2.3.0,<3",
"plotext>=5.3.2,<6",
"pydantic>=2.11.0,<3",
"python-dotenv>=1.1.0,<2",
"ratelimit>=2.2.1,<3",
"tenacity>=9.1.0,<10",
"typer>=0.16.0,<1",
"uvicorn>=0.35.0,<1",
]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 pydantic-settings used directly but not declared as a dependency

fli/mcp/server.py line 15 imports directly from pydantic_settings:

from pydantic_settings import BaseSettings, SettingsConfigDict

However, pydantic-settings is not listed in the [project.dependencies] table. It is currently available as a transitive dependency (pulled in by fastmcp), but relying on transitive deps is fragile — if fastmcp ever stops depending on it, this import will fail at runtime without any change to pyproject.toml.

Suggested change
dependencies = [
"curl-cffi>=0.7.4",
"fastapi>=0.115.6",
"fastmcp>=0.1.0",
"httpx>=0.28.1",
"pandas>=2.2.3",
"plotext>=5.3.2",
"pydantic>=2.10.4",
"python-dotenv>=1.0.1",
"ratelimit>=2.2.1",
"tenacity>=9.0.0",
"typer>=0.15.1",
"uvicorn>=0.34.0",
"curl-cffi>=0.13.0,<1",
"fastapi>=0.116.0,<1",
"fastmcp>=3.0.0,<4",
"httpx>=0.28.1,<1",
"pandas>=2.3.0,<3",
"plotext>=5.3.2,<6",
"pydantic>=2.11.0,<3",
"python-dotenv>=1.1.0,<2",
"ratelimit>=2.2.1,<3",
"tenacity>=9.1.0,<10",
"typer>=0.16.0,<1",
"uvicorn>=0.35.0,<1",
]
"curl-cffi>=0.13.0,<1",
"fastapi>=0.116.0,<1",
"fastmcp>=3.0.0,<4",
"httpx>=0.28.1,<1",
"pandas>=2.3.0,<3",
"plotext>=5.3.2,<6",
"pydantic>=2.11.0,<3",
"pydantic-settings>=2.0.0,<3",
"python-dotenv>=1.1.0,<2",
"ratelimit>=2.2.1,<3",
"tenacity>=9.1.0,<10",
"typer>=0.16.0,<1",
"uvicorn>=0.35.0,<1",

@punitarani
Copy link
Copy Markdown
Owner

potentially a copy of #66
lmk if there are other issues to fix as well

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.

2 participants