Refactor prompt behavior and add meta support#2610
Conversation
WalkthroughIntroduces a canonical Possibly related PRs
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (3)
🧰 Additional context used📓 Path-based instructions (1)**/*.py📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (1)📚 Learning: 2025-12-13T19:58:20.851ZApplied to files:
🧬 Code graph analysis (3)src/fastmcp/server/server.py (1)
src/fastmcp/server/proxy.py (4)
src/fastmcp/prompts/prompt.py (2)
⏰ 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)
🔇 Additional comments (13)
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: 0
🧹 Nitpick comments (1)
src/fastmcp/prompts/prompt.py (1)
207-230: Verify stacklevel for deprecation warning.The
stacklevel=2may not point to the user's code when_render()is called throughPromptManager.render_prompt(). The call chain is:
user code → PromptManager.render_prompt() → prompt._render() → warnings.warn()With
stacklevel=2, the warning will point torender_prompt()rather than the user's prompt function definition. Considerstacklevel=3or dynamically calculating based on context if you want the warning to be more actionable.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (5)
AGENTS.mdis excluded by none and included by nonetests/prompts/test_prompt.pyis excluded by none and included by nonetests/prompts/test_prompt_manager.pyis excluded by none and included by nonetests/server/test_server.pyis excluded by none and included by nonetests/server/test_server_interactions.pyis excluded by none and included by none
📒 Files selected for processing (8)
docs/servers/prompts.mdx(1 hunks)src/fastmcp/prompts/__init__.py(1 hunks)src/fastmcp/prompts/prompt.py(8 hunks)src/fastmcp/prompts/prompt_manager.py(4 hunks)src/fastmcp/server/middleware/caching.py(4 hunks)src/fastmcp/server/middleware/middleware.py(2 hunks)src/fastmcp/server/proxy.py(4 hunks)src/fastmcp/server/server.py(4 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
**/*.py
📄 CodeRabbit inference engine (AGENTS.md)
**/*.py: Write Python code with Python ≥3.10 and include full type annotations
Use specific exception types in error handling - never use bareexcept
Prioritize readable, understandable code - clarity over cleverness; avoid obfuscated or confusing patterns even if they're shorter
Files:
src/fastmcp/prompts/__init__.pysrc/fastmcp/server/middleware/middleware.pysrc/fastmcp/server/proxy.pysrc/fastmcp/server/middleware/caching.pysrc/fastmcp/prompts/prompt_manager.pysrc/fastmcp/server/server.pysrc/fastmcp/prompts/prompt.py
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/prompts.mdx
🧠 Learnings (1)
📚 Learning: 2025-12-13T19:58:20.851Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-13T19:58:20.851Z
Learning: Applies to tests/**/*.py : Pass FastMCP servers directly to clients using in-memory transport for testing; only use HTTP transport when explicitly testing network features
Applied to files:
src/fastmcp/server/proxy.py
🧬 Code graph analysis (7)
src/fastmcp/prompts/__init__.py (1)
src/fastmcp/prompts/prompt.py (3)
Message(33-41)Prompt(113-230)PromptResult(68-110)
src/fastmcp/server/middleware/middleware.py (1)
src/fastmcp/prompts/prompt.py (2)
Prompt(113-230)PromptResult(68-110)
src/fastmcp/server/proxy.py (3)
src/fastmcp/prompts/prompt.py (4)
Prompt(113-230)PromptResult(68-110)render(195-205)render(397-460)src/fastmcp/server/server.py (2)
get_prompt(1042-1046)name(369-370)src/fastmcp/client/client.py (3)
get_prompt(974-980)get_prompt(983-991)get_prompt(993-1022)
src/fastmcp/server/middleware/caching.py (2)
src/fastmcp/prompts/prompt.py (2)
Prompt(113-230)PromptResult(68-110)src/fastmcp/server/middleware/middleware.py (1)
CallNext(42-43)
src/fastmcp/prompts/prompt_manager.py (2)
src/fastmcp/prompts/prompt.py (4)
FunctionPrompt(233-460)Prompt(113-230)PromptResult(68-110)_render(207-230)src/fastmcp/exceptions.py (1)
PromptError(22-23)
src/fastmcp/server/server.py (1)
src/fastmcp/prompts/prompt.py (2)
PromptResult(68-110)to_mcp_prompt_result(104-110)
src/fastmcp/prompts/prompt.py (2)
src/fastmcp/utilities/types.py (1)
FastMCPBaseModel(38-41)src/fastmcp/server/proxy.py (1)
render(531-541)
⏰ 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 ubuntu-latest
- GitHub Check: Run tests: Python 3.10 on windows-latest
- GitHub Check: Run tests: Python 3.13 on ubuntu-latest
- GitHub Check: Run tests with lowest-direct dependencies
🔇 Additional comments (19)
src/fastmcp/prompts/__init__.py (1)
1-10: LGTM!The
PromptResultis correctly added to both the import and__all__export, making it available at the package level consistent with other public types likeMessageandPrompt.src/fastmcp/prompts/prompt_manager.py (3)
9-14: LGTM!Import changes correctly bring in
PromptResultand_PromptFnReturntype alias, aligning with the new type system introduced in this PR.
30-34: LGTM!The refactored
mask_error_detailsassignment correctly respects explicit parameter overrides while falling back to global settings whenNoneis provided. The ternary expression is clear and idiomatic.
104-124: LGTM!The
render_promptchanges are correct:
- Return type properly updated to
PromptResult- Calls internal
_render()which always returnsPromptResultPromptErroris caught and re-raised directly without double-wrapping, while general exceptions are still wrapped with appropriate maskingsrc/fastmcp/prompts/prompt.py (3)
46-53: LGTM!The type aliases clearly document the allowed return types for prompt functions.
_SyncPromptFnReturncovers synchronous returns while_PromptFnReturnextends to includeAwaitablevariants.
68-111: LGTM!The
PromptResultclass is well-designed:
- Fields are properly typed with descriptive Field annotations
from_value()correctly handles bothPromptResultandlist[PromptMessage]inputs with proper meta mergingto_mcp_prompt_result()correctly maps to the MCP protocol'sGetPromptResult
397-457: LGTM!
FunctionPrompt.render()correctly constructs and returns aPromptResultwith messages, description, and meta. The conversion logic for various return types (strings, dicts, PromptMessage) is preserved.src/fastmcp/server/middleware/middleware.py (1)
170-175: LGTM!The
on_get_promptsignature is correctly updated to usePromptResultfor both thecall_nextreturn type and the method return type, maintaining consistency with the new canonical prompt result type.docs/servers/prompts.mdx (2)
198-211: LGTM!The return values section is updated to include
PromptResultas a documented option, and the example correctly demonstrates returninglist[Message]with the simplified import.
213-249: LGTM!The new
PromptResultsection is well-structured:
- Version badge (2.14.1) clearly indicates when this feature was added
- Code example is complete and runnable
- Field descriptions are clear and concise
- The
<Note>appropriately distinguishes runtime meta from static decorator metaOne minor observation: the example on line 239 states
messagesaccepts "a list ofPromptMessageorMessageobjects", which is accurate sinceMessageis a constructor that returnsPromptMessage.src/fastmcp/server/server.py (3)
63-63: LGTM!Import correctly added for the new
PromptResulttype which is now used throughout the prompt rendering pipeline.
1742-1768: Clean separation of concerns in prompt middleware layer.The refactor introduces a two-tier approach:
_get_prompt_middlewarehandles MCP protocol conversion viato_mcp_prompt_result()_get_prompt_content_middlewarereturns the canonicalPromptResultfor internal useThis enables mounted servers to obtain
PromptResultdirectly without redundant conversions.
1770-1808: LGTM!The
_get_promptmethod correctly updated to returnPromptResult. The mounted server resolution now properly delegates to_get_prompt_content_middlewareto maintain type consistency throughout the call chain.src/fastmcp/server/proxy.py (3)
30-30: LGTM!Import correctly updated to use
PromptResultfrom the publicfastmcp.promptsmodule.
531-541: LGTM with clarification on type override.The
type: ignore[override]is appropriate here sinceProxyPrompt.renderreturns onlyPromptResult(narrowing the return type from the base class'slist[PromptMessage] | PromptResult). The comment helpfully explains that runtime meta from the remote server is preserved rather than static prompt metadata.
255-274: No action needed. Theresult.metaaccessor is correct.The MCP
GetPromptResulttype uses the standard Python pattern of a private_metafield with a public.metaproperty accessor. The constructor takes_metaas a parameter (as seen intasks/handlers.pyandtasks/converters.py), but accessingresult.metaon an instance is the correct way to retrieve the metadata. This pattern is used consistently throughout the codebase (e.g.,proxy.pylines 273, 525, 540).Likely an incorrect or invalid review comment.
src/fastmcp/server/middleware/caching.py (3)
20-20: LGTM!Import correctly includes
PromptResultfor use in the caching middleware.
223-227: Cache type migration consideration.The cache now stores
PromptResultinstead ofGetPromptResult. For deployments upgrading to this version with persistent cache storage, existing cached prompt entries may fail deserialization.Consider whether cache invalidation guidance should be documented for users with persistent cache backends, or if the schema difference is compatible (both have
messages,description,metafields).
416-440: LGTM!The
on_get_promptmethod is cleanly updated with consistentPromptResulttyping throughout. The caching logic remains unchanged - only the stored/retrieved type is updated to match the new canonical prompt result type.
Important: this was already merged in #2598 and reverted in #2609 because I want to hold it for 2.15.0. This is the new PR with the same logic.
Merge this AFTER #2611
Applies the same pattern as the new
ResourceContent(#2598) user-facing class and internal refactor, but to prompts.PromptResultwraps messages with description and metadata, providing full control over prompt responses. Internally, prompts are refactored around a new canonical representation.Key changes:
PromptResultcanonical type withmessages,description, andmetafieldsrender()acceptslist[PromptMessage] | PromptResult(backwards compatible)_render()always returnsPromptResultwith deprecation warning for old return typeGetPromptResult._metafield