Add FileSystemProvider for filesystem-based component discovery#2823
Add FileSystemProvider for filesystem-based component discovery#2823
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 65dbeac71e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # Import using standard import machinery | ||
| try: | ||
| return importlib.import_module(module_name) |
There was a problem hiding this comment.
Reload mode skips updated package modules
When a component file lives inside a package (__init__.py present), import_module_from_file uses importlib.import_module, which returns the cached module from sys.modules. In reload mode this means _load_components() will keep seeing the old module contents, so edits/new decorated functions inside a package will not show up until the process restarts. This breaks the documented behavior of reload=True for package-based layouts; consider reloading or invalidating the module entry when re-scanning.
Useful? React with 👍 / 👎.
WalkthroughAdds a filesystem-based component discovery surface under Possibly related PRs
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
src/fastmcp/fs/provider.py (2)
58-73: Consider validatingroot(exists/is_dir) to fail fast with a clearer error.
Path(root).resolve()+ eager_load_components()is good for surfacing import failures early, but ifrootis missing / not a directory you’ll likely get less actionable downstream errors.Proposed tweak
def __init__( self, root: str | Path = ".", reload: bool = False, ) -> None: super().__init__(on_duplicate="replace") self._root = Path(root).resolve() + if not self._root.exists(): + raise FileNotFoundError(f"FileSystemProvider root does not exist: {self._root}") + if not self._root.is_dir(): + raise NotADirectoryError(f"FileSystemProvider root is not a directory: {self._root}") self._reload = reload self._loaded = False
139-182: Resource vs template classification may be too aggressive for parameterized resources.
Right now, any user-facing function params (even with a fixed URI and no{}) forceResourceTemplate. If the framework intends to allow a fixed-URI resource with query/body params, this will be surprising. Worth confirming expected semantics (and adding a test) for “URI has no params but function has params”.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
FASTMCP_3_MARKETING_SUMMARY.mdis excluded by none and included by nonetests/fs/test_decorators.pyis excluded by none and included by nonetests/fs/test_discovery.pyis excluded by none and included by nonetests/fs/test_provider.pyis excluded by none and included by none
📒 Files selected for processing (11)
docs/docs.jsondocs/servers/providers/filesystem.mdxexamples/filesystem-provider/mcp/prompts/assistant.pyexamples/filesystem-provider/mcp/resources/config.pyexamples/filesystem-provider/mcp/tools/calculator.pyexamples/filesystem-provider/mcp/tools/greeting.pyexamples/filesystem-provider/server.pysrc/fastmcp/fs/__init__.pysrc/fastmcp/fs/decorators.pysrc/fastmcp/fs/discovery.pysrc/fastmcp/fs/provider.py
🧰 Additional context used
📓 Path-based instructions (4)
docs/**/*.mdx
📄 CodeRabbit inference engine (docs/.cursor/rules/mintlify.mdc)
docs/**/*.mdx: Use clear, direct language appropriate for technical audiences
Write in second person ('you') for instructions and procedures in MDX documentation
Use active voice over passive voice in MDX technical documentation
Employ present tense for current states and future tense for outcomes in MDX documentation
Maintain consistent terminology throughout all MDX documentation
Keep sentences concise while providing necessary context in MDX documentation
Use parallel structure in lists, headings, and procedures in MDX documentation
Lead with the most important information using inverted pyramid structure in MDX documentation
Use progressive disclosure in MDX documentation: present basic concepts before advanced ones
Break complex procedures into numbered steps in MDX documentation
Include prerequisites and context before instructions in MDX documentation
Provide expected outcomes for each major step in MDX documentation
End sections with next steps or related information in MDX documentation
Use descriptive, keyword-rich headings for navigation and SEO in MDX documentation
Focus on user goals and outcomes rather than system features in MDX documentation
Anticipate common questions and address them proactively in MDX documentation
Include troubleshooting for likely failure points in MDX documentation
Provide multiple pathways (beginner vs advanced) but offer an opinionated path to avoid overwhelming users in MDX documentation
Always include complete, runnable code examples that users can copy and execute in MDX documentation
Show proper error handling and edge case management in MDX code examples
Use realistic data instead of placeholder values in MDX code examples
Include expected outputs and results for verification in MDX code examples
Test all code examples thoroughly before publishing in MDX documentation
Specify language and include filename when relevant in MDX code examples
Add explanatory comments for complex logic in MDX code examples
Document all API...
Files:
docs/servers/providers/filesystem.mdx
docs/**/*.{md,mdx,json}
📄 CodeRabbit inference engine (AGENTS.md)
Documentation uses Mintlify framework. Files must be in docs.json to be included. Never modify docs/python-sdk/** (auto-generated)
Files:
docs/servers/providers/filesystem.mdxdocs/docs.json
docs/**/*.{md,mdx}
📄 CodeRabbit inference engine (AGENTS.md)
docs/**/*.{md,mdx}: Code examples in documentation must explain before showing code and make blocks fully runnable (include imports)
Documentation structure: Headers form navigation guide with logical H2/H3 hierarchy. Content should be user-focused with sections motivating features (why) before mechanics (how). Use prose over code comments for important information
Never use 'This isn't...' or 'not just...' constructions in writing - state what something IS directly. Avoid defensive writing patterns
Files:
docs/servers/providers/filesystem.mdx
src/fastmcp/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/fastmcp/**/*.py: Python ≥ 3.10 with full type annotations required
Prioritize readable, understandable code - clarity over cleverness. Avoid obfuscated or confusing patterns even if shorter
Follow existing patterns and maintain consistency in code implementation
Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Never use bare except - be specific with exception types
Files:
src/fastmcp/fs/decorators.pysrc/fastmcp/fs/__init__.pysrc/fastmcp/fs/provider.pysrc/fastmcp/fs/discovery.py
🧠 Learnings (2)
📚 Learning: 2025-12-25T15:53:07.656Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.656Z
Learning: Applies to src/fastmcp/**/*.py : Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Applied to files:
src/fastmcp/fs/__init__.pysrc/fastmcp/fs/discovery.pydocs/docs.json
📚 Learning: 2025-12-25T15:53:07.656Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.656Z
Learning: Applies to src/fastmcp/**/*.py : Python ≥ 3.10 with full type annotations required
Applied to files:
src/fastmcp/fs/__init__.pydocs/docs.json
🧬 Code graph analysis (8)
examples/filesystem-provider/mcp/tools/calculator.py (1)
src/fastmcp/fs/decorators.py (4)
tool(102-102)tool(106-117)tool(121-131)tool(134-214)
examples/filesystem-provider/mcp/resources/config.py (2)
src/fastmcp/fs/decorators.py (1)
resource(222-287)src/fastmcp/server/server.py (1)
name(419-420)
src/fastmcp/fs/__init__.py (2)
src/fastmcp/fs/decorators.py (9)
prompt(296-296)prompt(300-309)prompt(313-321)prompt(324-394)resource(222-287)tool(102-102)tool(106-117)tool(121-131)tool(134-214)src/fastmcp/fs/provider.py (1)
FileSystemProvider(34-244)
examples/filesystem-provider/server.py (1)
src/fastmcp/fs/provider.py (1)
FileSystemProvider(34-244)
examples/filesystem-provider/mcp/tools/greeting.py (1)
src/fastmcp/fs/decorators.py (4)
tool(102-102)tool(106-117)tool(121-131)tool(134-214)
src/fastmcp/fs/provider.py (5)
src/fastmcp/fs/decorators.py (12)
PromptMeta(71-80)ResourceMeta(55-67)ToolMeta(40-51)prompt(296-296)prompt(300-309)prompt(313-321)prompt(324-394)resource(222-287)tool(102-102)tool(106-117)tool(121-131)tool(134-214)src/fastmcp/fs/discovery.py (1)
discover_and_import(207-239)src/fastmcp/resources/resource.py (1)
Resource(208-397)src/fastmcp/resources/template.py (1)
ResourceTemplate(97-305)src/fastmcp/server/dependencies.py (1)
without_injected_parameters(86-140)
examples/filesystem-provider/mcp/prompts/assistant.py (1)
src/fastmcp/fs/decorators.py (4)
prompt(296-296)prompt(300-309)prompt(313-321)prompt(324-394)
src/fastmcp/fs/discovery.py (2)
src/fastmcp/fs/decorators.py (1)
get_fs_meta(86-88)src/fastmcp/utilities/logging.py (1)
get_logger(14-26)
🪛 Ruff (0.14.10)
src/fastmcp/fs/decorators.py
264-267: Avoid specifying long messages outside the exception class
(TRY003)
src/fastmcp/fs/provider.py
103-103: Do not catch blind exception: Exception
(BLE001)
114-114: Unused method argument: file_path
(ARG002)
src/fastmcp/fs/discovery.py
146-148: Avoid specifying long messages outside the exception class
(TRY003)
160-160: Avoid specifying long messages outside the exception class
(TRY003)
170-170: Avoid specifying long messages outside the exception class
(TRY003)
231-231: Do not catch blind exception: Exception
(BLE001)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run tests: Python 3.13 on ubuntu-latest
- GitHub Check: Run tests: Python 3.10 on windows-latest
- GitHub Check: Run tests with lowest-direct dependencies
- GitHub Check: Run tests: Python 3.10 on ubuntu-latest
🔇 Additional comments (36)
examples/filesystem-provider/mcp/tools/calculator.py (3)
1-3: LGTM! Clear module structure.The module docstring and import statement are correct and follow the filesystem provider pattern.
6-13: LGTM! Well-structured tool with custom metadata.The decorator correctly demonstrates custom naming, description, and tagging. The implementation is straightforward and correct.
16-24: LGTM! Good example of minimal decorator usage.This function demonstrates using the decorator with minimal metadata while relying on the docstring for description. The detailed Args section in the docstring is a nice touch.
examples/filesystem-provider/server.py (3)
1-14: LGTM! Comprehensive module documentation.The docstring provides clear usage instructions with specific commands for running and inspecting the server. The dev mode note is helpful for users.
16-19: LGTM! Correct imports.All necessary imports are present and appropriate for the filesystem provider example.
21-29: LGTM! Clean provider and server setup.The provider configuration correctly demonstrates the FileSystemProvider usage with dev mode enabled. The comments clearly explain the behavior, and the path construction is appropriate.
examples/filesystem-provider/mcp/tools/greeting.py (4)
1-3: LGTM! Clear module structure.The module docstring appropriately highlights that multiple tools can exist in a single file, which is a helpful demonstration.
6-13: LGTM! Clean tool implementation.The function demonstrates minimal decorator usage while providing good documentation through the docstring.
16-23: LGTM! Consistent implementation.The farewell function follows the same clean pattern as the greet function, demonstrating consistency in the codebase.
26-28: LGTM! Helpful demonstration of ignored functions.This is an excellent teaching example showing that undecorated helper functions are not registered by the filesystem provider. The private naming convention (leading underscore) further reinforces that this won't be discovered.
docs/docs.json (2)
112-112: LGTM! Filesystem provider added to navigation.The new provider page is correctly added to the Providers section navigation. The placement between "local" and "mounting" is reasonable and maintains the documentation flow.
352-360: LGTM! Python SDK group correctly structured.The new
fastmcp.fsgroup is properly configured with appropriate pages covering the module's main components (init, decorators, discovery, provider). The structure is consistent with other SDK groups.docs/servers/providers/filesystem.mdx (8)
1-12: LGTM! Proper frontmatter and introduction.The YAML frontmatter correctly includes required title and description fields. The version badge and opening paragraph establish the component's purpose clearly.
14-25: LGTM! Clear motivation without overselling.This section effectively explains the rationale for filesystem discovery using direct, user-focused language. The tradeoffs are presented honestly, following the guideline to state what something IS rather than using defensive patterns.
26-50: LGTM! Well-structured quick start with runnable examples.The quick start section follows documentation guidelines by explaining before showing code, including all necessary imports, and providing complete, runnable examples. The progression from server setup to component creation is logical.
51-133: LGTM! Comprehensive decorator documentation with excellent examples.The decorator section provides clear, runnable code examples for all three decorator types. Each example includes proper imports and demonstrates both basic and advanced usage patterns. The parameter documentation is clear and complete.
134-157: LGTM! Clear directory structure guidance with flexibility.This section effectively communicates that directory structure is organizational rather than functional, using progressive disclosure to show conventional patterns before introducing alternatives. The examples are clear and practical.
158-187: LGTM! Comprehensive rules with practical examples.The discovery rules table clearly documents all scanning behaviors. The package imports section effectively demonstrates when and why relative imports work, with a complete, runnable example.
188-217: LGTM! Clear guidance with appropriate warnings.Both sections effectively communicate important operational concerns. The reload mode section appropriately warns against production use, and the error handling explanation helps users understand failure behavior without panic.
218-250: LGTM! Complete example with clear next steps.The example project section provides a comprehensive, realistic example with proper directory structure and fully runnable code. The run instructions at the end give users clear next steps, following documentation best practices.
src/fastmcp/fs/__init__.py (1)
1-45: LGTM! Well-structured module with clear documentation.The module provides a clean public API with intentional re-exports of core types (FileSystemProvider and the three decorators). The docstring examples effectively demonstrate the filesystem-based component discovery workflow.
examples/filesystem-provider/mcp/resources/config.py (1)
1-55: LGTM! Well-structured resource examples.The three resource functions demonstrate different patterns effectively:
- Static resource with fixed URI
- Templated resource with parameter extraction
- Custom metadata (name, mime_type, tags)
All functions have proper type annotations and return formatted JSON strings. The defensive fallback in
get_env_config(line 35) handles unknown environments gracefully.examples/filesystem-provider/mcp/prompts/assistant.py (1)
1-39: LGTM! Clear prompt examples demonstrating decorator flexibility.Both prompt functions showcase different usage patterns:
code_review: Simple decorator usage with default parametersexplain: Custom name and metadata (description, tags)Type annotations are complete, and the implementation demonstrates the decorator's flexibility effectively.
src/fastmcp/fs/decorators.py (4)
39-93: LGTM! Well-structured metadata system.The dataclasses (ToolMeta, ResourceMeta, PromptMeta) provide clear type-safe metadata storage. The FSMeta union type and helper functions (
get_fs_meta,has_fs_meta) offer a clean API for metadata access.
101-214: LGTM! Flexible tool decorator with proper overloads.The decorator supports multiple invocation patterns (@tool, @tool(), @tool("name"), @tool(name="...")) with appropriate type hints. The defensive conversion of dict to ToolAnnotations (lines 180-181) handles both input formats gracefully.
222-287: LGTM! Resource decorator with proper URI validation.The decorator correctly enforces URI requirements and provides clear error messaging. The defensive conversion of dict to Annotations (lines 269-270) maintains flexibility while ensuring type safety.
Note: The static analysis hint (TRY003) about the error message on lines 264-267 can be safely ignored—the inline message is clear and appropriate for this validation error.
295-394: LGTM! Consistent prompt decorator implementation.The decorator follows the same flexible invocation patterns as @tool, maintaining API consistency across all three decorators. The implementation is clean and well-documented.
src/fastmcp/fs/discovery.py (4)
35-66: LGTM! Robust file discovery with proper filtering.The function correctly excludes
__init__.pyand__pycache__directories, and returns a sorted list for deterministic ordering. The handling of both directory and file roots (lines 49-53) adds useful flexibility.
74-109: LGTM! Package detection and module naming logic is sound.The helper functions correctly:
- Detect package boundaries by walking up the directory tree
- Compute dotted module names from file paths
- Handle the package structure appropriately
112-172: LGTM! Comprehensive module import with proper cleanup.The function handles both package and non-package imports correctly. Key strengths:
- Package root detection for relative import support
- sys.path manipulation with proper ordering
- Cleanup of sys.modules on failure (lines 169-170)
- Clear error messages for debugging
Note: The TRY003 static analysis hints about error messages can be ignored—the detailed context in ImportError messages aids debugging.
207-239: Broad exception handling is intentional here.The bare
Exceptioncatch on line 231 is appropriate for this use case. The function's purpose is to discover and collect components while tracking failures for later reporting, so catching all exceptions ensures one broken file doesn't stop the entire discovery process. The error is properly recorded inresult.failed_filesfor the caller to handle.The static analysis hint (BLE001) can be ignored in this context.
src/fastmcp/fs/provider.py (5)
1-31: Docstring + imports look consistent with the feature scope.
No concerns here; the module-level docstring and dependency set are clear.
124-138: Tool registration path is straightforward and matches the meta shape.
183-195: Prompt registration path looks consistent with the meta contract.
243-244:__repr__is helpful for debugging.
74-112: No action needed; the suggestion misapplies async exception handling to synchronous code.The
_load_components()method is synchronous with noawaitstatements. In Python,asyncio.CancelledErroris raised only atawaitpoints by the asyncio runtime. Addingexcept asyncio.CancelledError: raiseto synchronous code would be dead code that never executes, regardless of whether the method is called from an async context.The bare
Exceptioncatch here is appropriate for defensive programming—it prevents one malformed component from breaking the entire load. The exception is logged, and execution continues to process remaining components, which is the correct behavior.Likely an incorrect or invalid review comment.
Test Failure AnalysisSummary: The test Root Cause: The test uses a simple substring check ( The filename "bad.py" is split as "ba" and "d.py" on separate lines, breaking the substring assertion. Suggested Solution: Modify the test assertions in Files to modify:
Changes needed:
Example fix: # Before:
assert "bad.py" in captured.err
# After (option 1 - normalize whitespace):
import re
assert "bad.py" in re.sub(r'\s+', ' ', captured.err)
# Or (option 2 - check for error message instead):
assert "Failed to import" in captured.err and str(bad_file) in re.sub(r'\s+', ' ', captured.err)Detailed AnalysisTest behavior:
Actual error output (parallel mode):The filename is present but wrapped: Related tests with same issue:
All of these tests are susceptible to the same issue, though the failure may be intermittent depending on path lengths and terminal width. Why this happens:
Related Files
🤖 This analysis was generated by the FastMCP test failure triage bot |
Test Failure AnalysisSummary: Three tests in Root Cause: In logger.warning(f"Failed to import {file_path}: {error}")This produces log output like:
The tests check for the substring Suggested Solution: Modify line 96 in logger.warning(f"Failed to import {file_path.name}: {error}")Or if you want to keep the full path but make tests more robust, update the test assertions to use assert bad_file.name in captured.err # Instead of assert "bad.py" in captured.errThe first approach (changing the logger) is cleaner since warning messages with just the filename are more readable for users, while still providing the error context. The full absolute path is less helpful in warning messages and can clutter logs. Detailed AnalysisFailed Tests:
All three tests create temporary files and check for the filename in Log Evidence (Windows failure): The test does Related Files
|
- Reload cached package modules using importlib.reload() - Add async lock and to_thread for non-blocking reload - Clear tool transformations on reload - Remove unused file_path parameter
274b617 to
5e1a280
Compare
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
src/fastmcp/fs/discovery.py (1)
137-160: Accumulatedsys.pathentries may grow unbounded.Each call to
import_module_from_fileinserts directories intosys.pathwithout ever removing them. In long-running processes with frequent reloads, this could lead to an ever-growingsys.path. Consider tracking added paths and either reusing existing entries or cleaning up on provider reset.src/fastmcp/fs/provider.py (1)
143-185: LGTM!Smart heuristic for distinguishing templates from static resources. The logic correctly identifies templated resources by checking both URI placeholders and function parameters.
The inline import of
without_injected_parametersat line 151 is slightly unusual—consider moving it to the top of the file if it doesn't cause circular import issues.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
tests/fs/test_decorators.pyis excluded by none and included by nonetests/fs/test_discovery.pyis excluded by none and included by nonetests/fs/test_provider.pyis excluded by none and included by none
📒 Files selected for processing (11)
docs/docs.jsondocs/servers/providers/filesystem.mdxexamples/filesystem-provider/mcp/prompts/assistant.pyexamples/filesystem-provider/mcp/resources/config.pyexamples/filesystem-provider/mcp/tools/calculator.pyexamples/filesystem-provider/mcp/tools/greeting.pyexamples/filesystem-provider/server.pysrc/fastmcp/fs/__init__.pysrc/fastmcp/fs/decorators.pysrc/fastmcp/fs/discovery.pysrc/fastmcp/fs/provider.py
🚧 Files skipped from review as they are similar to previous changes (6)
- docs/docs.json
- src/fastmcp/fs/init.py
- examples/filesystem-provider/server.py
- examples/filesystem-provider/mcp/prompts/assistant.py
- docs/servers/providers/filesystem.mdx
- examples/filesystem-provider/mcp/tools/calculator.py
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
src/fastmcp/**/*.py: Python ≥ 3.10 with full type annotations required
Prioritize readable, understandable code - clarity over cleverness. Avoid obfuscated or confusing patterns even if shorter
Follow existing patterns and maintain consistency in code implementation
Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Never use bare except - be specific with exception types
Files:
src/fastmcp/fs/discovery.pysrc/fastmcp/fs/provider.pysrc/fastmcp/fs/decorators.py
🧠 Learnings (1)
📚 Learning: 2025-12-25T15:53:07.656Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.656Z
Learning: Applies to src/fastmcp/**/*.py : Be intentional about re-exports - don't blindly re-export everything to parent namespaces. Core types defining a module's purpose should be exported. Specialized features can live in submodules. Only re-export to fastmcp.* for most fundamental types
Applied to files:
src/fastmcp/fs/discovery.py
🧬 Code graph analysis (3)
examples/filesystem-provider/mcp/tools/greeting.py (2)
src/fastmcp/fs/decorators.py (4)
tool(102-102)tool(106-117)tool(121-131)tool(134-214)src/fastmcp/server/server.py (1)
name(419-420)
examples/filesystem-provider/mcp/resources/config.py (1)
src/fastmcp/fs/decorators.py (1)
resource(222-287)
src/fastmcp/fs/discovery.py (2)
src/fastmcp/fs/decorators.py (1)
get_fs_meta(86-88)src/fastmcp/utilities/logging.py (1)
get_logger(14-26)
🪛 Ruff (0.14.10)
src/fastmcp/fs/discovery.py
149-151: Avoid specifying long messages outside the exception class
(TRY003)
163-163: Avoid specifying long messages outside the exception class
(TRY003)
173-173: Avoid specifying long messages outside the exception class
(TRY003)
234-234: Do not catch blind exception: Exception
(BLE001)
src/fastmcp/fs/provider.py
107-107: Do not catch blind exception: Exception
(BLE001)
src/fastmcp/fs/decorators.py
264-267: Avoid specifying long messages outside the exception class
(TRY003)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
- GitHub Check: Run tests: Python 3.10 on windows-latest
- GitHub Check: Run tests: Python 3.13 on ubuntu-latest
- GitHub Check: Run tests: Python 3.10 on ubuntu-latest
- GitHub Check: Run tests with lowest-direct dependencies
🔇 Additional comments (19)
examples/filesystem-provider/mcp/tools/greeting.py (1)
1-28: LGTM!Clean example demonstrating the filesystem-based tool discovery pattern. The decorated
greetandfarewellfunctions have proper type annotations and docstrings, and the undecorated_format_messagehelper correctly illustrates that private functions are ignored by the discovery mechanism.examples/filesystem-provider/mcp/resources/config.py (1)
1-55: LGTM!Excellent example coverage demonstrating static resources, templated resources with URI parameters, and resources with custom metadata. The code is well-documented and correctly uses the
@resourcedecorator API.src/fastmcp/fs/discovery.py (6)
27-33: LGTM!Well-structured dataclass for encapsulating discovery results with proper field defaults.
35-66: LGTM!Solid implementation with good edge-case handling for non-existent paths and single-file inputs. The sorted output ensures deterministic discovery order.
69-109: LGTM!Package detection logic is well-structured. The upward traversal in
_find_package_rootcorrectly handles nested packages, and_compute_module_nameproperly computes the dotted module name.
168-175: Broad exception catch is acceptable here.The
except Exceptionis justified sinceexec_moduleexecutes arbitrary user code that can raise any exception type. The cleanup ofsys.modulesprevents stale partial modules from lingering.
178-207: LGTM!Clean implementation that correctly filters private attributes and gracefully handles edge cases with the
AttributeErrorcatch.
210-241: LGTM!The main entry point correctly orchestrates discovery, import, and component extraction. Catching both
ImportErrorand broaderExceptionis reasonable since user module code can fail in arbitrary ways, and failures are properly recorded rather than silently swallowed.src/fastmcp/fs/decorators.py (5)
39-83: LGTM!Well-designed discriminated union using literal type fields. The dataclasses provide clean metadata storage for all three component types.
86-93: LGTM!Clean helper functions for metadata access.
134-214: LGTM!Comprehensive decorator implementation supporting all common calling patterns. The overloads provide excellent type hints, and the recursive call for the
@tool("name")pattern is elegant.
263-267: Good error handling for common misuse.The explicit
TypeErrorwith a helpful message correctly guides users who accidentally use@resourcewithout the required URI argument. The message length is justified for user clarity.
324-394: LGTM!Consistent implementation following the same patterns as
@tool. The simpler metadata structure appropriately reflects prompt requirements.src/fastmcp/fs/provider.py (6)
59-75: LGTM!Well-designed initialization with eager loading for early error detection. The lazy lock creation correctly handles the case where no event loop is running during
__init__, and mtime-based warning deduplication is a nice touch.
77-115: LGTM!Robust loading logic with good error handling. The warning deduplication based on file mtime prevents log spam during development, and clearing warnings for successfully fixed files provides good developer experience. The broad exception catch during registration is appropriate for resilience—individual component failures shouldn't prevent other components from loading.
117-126: LGTM!Clean type-based dispatch to specific registration handlers.
128-141: LGTM!Clean delegation to
Tool.from_functionwith all metadata fields properly forwarded.
200-216: LGTM!Correctly implemented double-checked locking pattern with lazy lock creation. Using
asyncio.to_threadappropriately offloads the blocking filesystem I/O from the event loop.
220-261: LGTM!Consistent override pattern ensuring reload mode works for all access methods. The
__repr__provides useful debugging information.
Adds
FileSystemProvider, a new provider that scans a directory for Python files and automatically registers functions decorated with@tool,@resource, or@promptfromfastmcp.fs.The main benefit is eliminating coordination between files. Traditional servers require either tool files to import the server (to call
@server.tool()) or the server to import all tool modules.FileSystemProviderremoves this coupling—each file is self-contained with decorators that don't need a server instance.Features:
reload=Truemode for development (re-scans on every request)__init__.pyexistsCloses #2688