Skip to content

Let FastMCPError propagate unchanged from managers#2698

Closed
jlowin wants to merge 5 commits intomainfrom
release/2.x
Closed

Let FastMCPError propagate unchanged from managers#2698
jlowin wants to merge 5 commits intomainfrom
release/2.x

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Dec 23, 2025

Merge 2.x fixes to main, including #2697, which ensures FastMCP errors propogate. Some of these are redundant but the new commit history will simplify future merges from the release branch.

rjolaverria and others added 4 commits December 23, 2025 18:00
When a dependency raises ToolError or other FastMCPError subclasses, they
were getting wrapped in RuntimeError with a generic "Failed to resolve
dependency" message. This made it hard to use ToolError for validation
in dependencies.

Now FastMCPError subclasses propagate unchanged, matching the pattern
used elsewhere in the codebase.

Closes #2633

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Uses pydocket 0.16.0's `names=` parameter for explicit registration keys:
- Tools/prompts: registered by `.key`
- Resources/templates: registered by `.name`

Removes `_create_named_fn_wrapper` function.

Closes #2642
@jlowin jlowin changed the title Merge 2.x release branch to main Let FastMCPError propagate unchanged from managers Dec 23, 2025
@marvin-context-protocol marvin-context-protocol Bot added bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. server Related to FastMCP server implementation or server-side functionality. labels Dec 23, 2025
@jlowin
Copy link
Copy Markdown
Member Author

jlowin commented Dec 23, 2025

CLosing - too many conflicts. We will cherry pick instead

@jlowin jlowin closed this Dec 23, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 23, 2025

Walkthrough

This pull request consolidates exception handling across multiple manager and utility modules to treat FastMCPError as the primary exception type requiring special propagation. Changes include replacing specific exception handlers (PromptError, ResourceError, ToolError) with FastMCPError handlers in prompt_manager, resource_manager, and tool_manager. The dependency resolver is updated to re-raise FastMCPError unchanged instead of wrapping it as RuntimeError. Error middleware now unwraps exceptions to map to root causes. Additionally, the server removes the _create_named_fn_wrapper function and switches to using explicit names parameter for Docket registration.

Possibly related PRs

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The description is missing required sections from the template (Contributors Checklist with issue reference, testing confirmation, and Review Checklist items). Only a brief summary is provided. Complete the description by adding the required checklist sections: link the issue (#2697 or #2698), confirm testing and documentation updates, and mark review readiness items.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: ensuring FastMCPError propagates unchanged from managers, which is the primary objective across multiple modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch release/2.x

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7dcccef and 7a46e21.

⛔ Files ignored due to path filters (5)
  • pyproject.toml is excluded by none and included by none
  • tests/server/middleware/test_error_handling.py is excluded by none and included by none
  • tests/server/tasks/test_server_tasks_parameter.py is excluded by none and included by none
  • tests/server/test_dependencies.py is excluded by none and included by none
  • uv.lock is excluded by !**/*.lock and included by none
📒 Files selected for processing (6)
  • src/fastmcp/prompts/prompt_manager.py
  • src/fastmcp/resources/resource_manager.py
  • src/fastmcp/server/dependencies.py
  • src/fastmcp/server/middleware/error_handling.py
  • src/fastmcp/server/server.py
  • src/fastmcp/tools/tool_manager.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use Python ≥ 3.10 with full type annotations
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/server.py
  • src/fastmcp/server/middleware/error_handling.py
  • src/fastmcp/resources/resource_manager.py
  • src/fastmcp/prompts/prompt_manager.py
  • src/fastmcp/server/dependencies.py
  • src/fastmcp/tools/tool_manager.py
🧠 Learnings (4)
📓 Common learnings
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T21:37:55.031Z
Learning: Applies to src/fastmcp/__init__.py : All module exports should be intentional - only re-export to `fastmcp.*` for fundamental types like `FastMCP` and `Client`, prefer users importing from specific submodules for specialized features
📚 Learning: 2025-12-21T21:37:55.031Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T21:37:55.031Z
Learning: Applies to src/fastmcp/__init__.py : All module exports should be intentional - only re-export to `fastmcp.*` for fundamental types like `FastMCP` and `Client`, prefer users importing from specific submodules for specialized features

Applied to files:

  • src/fastmcp/resources/resource_manager.py
  • src/fastmcp/prompts/prompt_manager.py
  • src/fastmcp/server/dependencies.py
  • src/fastmcp/tools/tool_manager.py
📚 Learning: 2025-11-26T21:51:44.174Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: .cursor/rules/core-mcp-objects.mdc:0-0
Timestamp: 2025-11-26T21:51:44.174Z
Learning: Review and update related Manager classes (ToolManager, ResourceManager, PromptManager) when modifying MCP object definitions

Applied to files:

  • src/fastmcp/prompts/prompt_manager.py
  • src/fastmcp/tools/tool_manager.py
📚 Learning: 2025-12-21T21:37:55.031Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-21T21:37:55.031Z
Learning: Applies to src/fastmcp/**/__init__.py : Core types that define a module's purpose should be exported (e.g., `Middleware` from `fastmcp.server.middleware`), while specialized features can live in submodules

Applied to files:

  • src/fastmcp/server/dependencies.py
🧬 Code graph analysis (6)
src/fastmcp/server/server.py (3)
src/fastmcp/resources/resource.py (2)
  • key (149-156)
  • FunctionResource (159-240)
src/fastmcp/resources/template.py (2)
  • key (221-228)
  • FunctionResourceTemplate (231-413)
src/fastmcp/utilities/components.py (1)
  • key (66-73)
src/fastmcp/server/middleware/error_handling.py (1)
src/fastmcp/server/context.py (1)
  • error (473-487)
src/fastmcp/resources/resource_manager.py (2)
src/fastmcp/server/context.py (1)
  • fastmcp (169-174)
src/fastmcp/exceptions.py (3)
  • FastMCPError (6-7)
  • NotFoundError (34-35)
  • ResourceError (14-15)
src/fastmcp/prompts/prompt_manager.py (1)
src/fastmcp/exceptions.py (3)
  • FastMCPError (6-7)
  • NotFoundError (34-35)
  • PromptError (22-23)
src/fastmcp/server/dependencies.py (1)
src/fastmcp/exceptions.py (1)
  • FastMCPError (6-7)
src/fastmcp/tools/tool_manager.py (1)
src/fastmcp/exceptions.py (4)
  • FastMCPError (6-7)
  • NotFoundError (34-35)
  • ToolError (18-19)
  • ValidationError (10-11)
🔇 Additional comments (6)
src/fastmcp/prompts/prompt_manager.py (1)

10-10: LGTM! Exception propagation pattern correctly implemented.

The addition of FastMCPError to the import and the explicit re-raise block ensures that FastMCPError subclasses (including PromptError) propagate unchanged through the render path. This aligns with the PR objective and matches the consistent pattern across other managers.

Also applies to: 110-111

src/fastmcp/tools/tool_manager.py (1)

11-11: LGTM! Exception handling correctly distinguishes FastMCPError and pydantic's ValidationError.

The changes properly re-raise both FastMCPError subclasses (like ToolError) and pydantic's ValidationError unchanged. Since pydantic's ValidationError is not a subclass of FastMCPError, handling them separately is correct and ensures validation errors propagate with their original context intact.

Also applies to: 161-164

src/fastmcp/server/middleware/error_handling.py (1)

90-90: LGTM! Error mapping now correctly uses root cause for wrapped exceptions.

The change to derive error_type from error.__cause__ when present ensures that wrapped exceptions (e.g., a ToolError wrapping a ValueError) are mapped to MCP error codes based on their root cause. This complements the broader exception propagation changes in this PR.

src/fastmcp/server/dependencies.py (1)

24-24: LGTM! FastMCPError propagation in dependency resolution correctly implemented.

The explicit re-raise of FastMCPError ensures that domain-specific errors like ToolError and ResourceError propagate unchanged from dependencies instead of being wrapped in RuntimeError. This restores the ability to use ToolError for validation as mentioned in the PR objectives.

Also applies to: 192-195

src/fastmcp/resources/resource_manager.py (1)

13-13: LGTM! FastMCPError propagation consistently applied across all resource paths.

The changes correctly propagate FastMCPError subclasses (including ResourceError) unchanged in:

  1. Template-based resource creation (get_resource)
  2. Concrete resource reading (read_resource)
  3. Template-derived resource reading (read_resource)

This ensures consistent exception behavior across the resource manager.

Also applies to: 271-273, 301-303, 323-324

src/fastmcp/server/server.py (1)

423-423: LGTM! Cleaner Docket registration using explicit names= parameter.

The removal of _create_named_fn_wrapper in favor of using Docket's names= parameter is a clean improvement:

  • Tools and prompts are registered by .key
  • Resources and templates are registered by .name

This approach is more straightforward than wrapping functions to manipulate __name__ and aligns with pydocket 0.16.0's API, which is specified in the project dependencies.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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

Labels

bug Something isn't working. Reports of errors, unexpected behavior, or broken functionality. server Related to FastMCP server implementation or server-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants