Add task_meta to prompts and centralize fn_key enrichment#2751
Conversation
Extends task_meta parameter pattern to prompts (matching tools and resources) and moves fn_key enrichment from 9 component/wrapper methods to 3 server methods (call_tool, read_resource, render_prompt). Also removes dead code: unused _task_metadata and _docket_fn_key context variables, get_task_metadata() function, and deprecated key parameter in check_background_task().
|
Warning Rate limit exceeded@jlowin has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 5 minutes and 49 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ⛔ Files ignored due to path filters (3)
📒 Files selected for processing (1)
WalkthroughThis PR makes task metadata explicit across FastMCP by adding TaskMeta-aware overloads to Prompt._render and by propagating task_meta through server/provider methods. It removes implicit fn_key enrichment in Resource._read, ResourceTemplate._read, Tool._run, and provider delegation, deletes the get_task_metadata public export, and updates check_background_task to drop the separate key parameter and rely on task_meta.fn_key or the component key. render_prompt, call_tool, and read_resource paths were updated to accept and forward TaskMeta and to return either PromptResult or CreateTaskResult depending on task_meta. Possibly related PRs
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
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: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/fastmcp/server/server.py (2)
1597-1601: Misleading comment about fn_key enrichment location.The comment states "The component (or provider wrapper) will enrich fn_key with self.key" but this is inaccurate. Based on the implementation:
- MCP handlers extract task_meta without fn_key ✓
- Server methods (
call_toolat lines 1208-1210) enrich fn_key before calling component methods ✓- Component methods receive task_meta with fn_key already set ✓
The comment should clarify that the server's
call_toolmethod enriches fn_key, not the component itself.🔎 Proposed fix
# Extract SEP-1686 task metadata from request context. - # NOTE: fn_key is NOT set here. The component (or provider wrapper) will - # enrich fn_key with self.key. For mounted servers, the provider wrapper - # sets fn_key to the parent's namespaced key, ensuring Docket finds the - # correctly registered function. + # NOTE: fn_key is NOT set here. The server's call_tool() method will + # enrich fn_key with tool.key before calling the tool's _run() method. + # For mounted servers, the parent server sets fn_key to the namespaced + # key, ensuring Docket finds the correctly registered function.
1641-1647: Comment should clarify that server enriches fn_key, not component.Similar to the issue in
_call_tool_mcp, this comment states "The component (or provider wrapper) will enrich fn_key" but the actual implementation shows the server methods (read_resourceat lines 1302-1304 and 1326-1328) perform the enrichment.🔎 Proposed fix
# Extract SEP-1686 task metadata from request context. - # NOTE: fn_key is NOT set here for resources because we don't know yet - # if the URI will be handled by a direct resource or a template. Templates - # need their pattern-based key for Docket lookup, not the concrete URI. - # The component (or provider wrapper) will enrich fn_key with self.key. - # For mounted servers, the provider wrapper sets fn_key to the parent's - # namespaced key, ensuring Docket finds the correctly registered function. + # NOTE: fn_key is NOT set here because we don't know yet if the URI will + # be handled by a direct resource or a template. The server's read_resource() + # method will enrich fn_key with resource.key or template.key after + # determining which component handles the URI. For mounted servers, the + # parent server sets fn_key to the namespaced key, ensuring Docket finds + # the correctly registered function.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (6)
tests/server/providers/test_local_provider_prompts.pyis excluded by none and included by nonetests/server/tasks/test_resource_task_meta_parameter.pyis excluded by none and included by nonetests/server/tasks/test_task_mount.pyis excluded by none and included by nonetests/server/test_dependencies.pyis excluded by none and included by nonetests/server/test_mount.pyis excluded by none and included by nonetests/server/test_providers.pyis excluded by none and included by none
📒 Files selected for processing (8)
src/fastmcp/prompts/prompt.pysrc/fastmcp/resources/resource.pysrc/fastmcp/resources/template.pysrc/fastmcp/server/dependencies.pysrc/fastmcp/server/providers/fastmcp_provider.pysrc/fastmcp/server/server.pysrc/fastmcp/server/tasks/routing.pysrc/fastmcp/tools/tool.py
💤 Files with no reviewable changes (3)
- src/fastmcp/resources/template.py
- src/fastmcp/server/dependencies.py
- src/fastmcp/resources/resource.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/tools/tool.pysrc/fastmcp/server/tasks/routing.pysrc/fastmcp/server/server.pysrc/fastmcp/prompts/prompt.pysrc/fastmcp/server/providers/fastmcp_provider.py
🧠 Learnings (3)
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to src/fastmcp/**/*.py : Python ≥ 3.10 with full type annotations required
Applied to files:
src/fastmcp/server/tasks/routing.pysrc/fastmcp/server/server.pysrc/fastmcp/prompts/prompt.pysrc/fastmcp/server/providers/fastmcp_provider.py
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to src/fastmcp/**/*.py : Never use bare except - be specific with exception types
Applied to files:
src/fastmcp/server/tasks/routing.pysrc/fastmcp/prompts/prompt.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/server/server.py
🧬 Code graph analysis (3)
src/fastmcp/server/tasks/routing.py (3)
src/fastmcp/resources/resource.py (1)
key(368-370)src/fastmcp/resources/template.py (1)
key(274-276)src/fastmcp/utilities/components.py (1)
key(94-102)
src/fastmcp/server/server.py (2)
src/fastmcp/server/tasks/config.py (1)
TaskMeta(25-37)src/fastmcp/server/context.py (1)
get_prompt(294-311)
src/fastmcp/server/providers/fastmcp_provider.py (4)
src/fastmcp/prompts/prompt.py (6)
_render(306-310)_render(313-317)_render(319-357)PromptResult(109-188)render(256-267)render(546-575)src/fastmcp/server/tasks/config.py (1)
TaskMeta(25-37)src/fastmcp/server/server.py (3)
render_prompt(1349-1356)render_prompt(1359-1366)render_prompt(1368-1439)src/fastmcp/server/providers/proxy.py (1)
render(407-420)
⏰ 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 with lowest-direct dependencies
- GitHub Check: Run tests: Python 3.10 on ubuntu-latest
- GitHub Check: Run tests: Python 3.13 on ubuntu-latest
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/fastmcp/server/server.py (2)
1180-1181: Outdated comment contradicts the actual implementation.This comment states fn_key enrichment happens in
Tool._run(), but lines 1208-1210 clearly show enrichment happens here incall_tool(). The comment appears to be stale after the refactor that centralized fn_key enrichment to the server.🔎 Proposed fix
- # Note: fn_key enrichment happens in Tool._run(), not here, - # so that provider wrappers can enrich with their namespaced key. + # Note: fn_key enrichment happens here after finding the tool. + # For mounted servers, the parent's provider sets fn_key to the + # namespaced key before delegating, ensuring correct Docket routing.
1273-1276: Outdated comment contradicts the actual implementation.This comment states fn_key enrichment happens in each component's
_read()method, but lines 1302-1304 and 1326-1328 show enrichment happens here inread_resource(). The comment is stale after the centralization refactor.🔎 Proposed fix
- # Note: fn_key enrichment happens in each component's _read() method, - # not here, because resources and templates use different key formats: - # - Resources use Resource.make_key(uri) for the concrete URI - # - Templates use self.key which is the template pattern + # Note: fn_key enrichment happens here after finding the resource/template. + # Resources and templates use different key formats: + # - Resources use resource.key (Resource.make_key(uri) for concrete URI) + # - Templates use template.key (the template pattern) + # For mounted servers, the parent's provider sets fn_key to the + # namespaced key before delegating, ensuring correct Docket routing.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
v3-notes/provider-test-pattern.mdis excluded by none and included by nonev3-notes/task-meta-parameter.mdis excluded by none and included by none
📒 Files selected for processing (2)
src/fastmcp/server/server.pysrc/fastmcp/server/tasks/routing.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/server/tasks/routing.pysrc/fastmcp/server/server.py
🧠 Learnings (3)
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to src/fastmcp/**/*.py : Python ≥ 3.10 with full type annotations required
Applied to files:
src/fastmcp/server/tasks/routing.pysrc/fastmcp/server/server.py
📚 Learning: 2025-12-25T15:53:07.646Z
Learnt from: CR
Repo: jlowin/fastmcp PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-25T15:53:07.646Z
Learning: Applies to src/fastmcp/**/*.py : Never use bare except - be specific with exception types
Applied to files:
src/fastmcp/server/tasks/routing.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/server/server.py
🧬 Code graph analysis (2)
src/fastmcp/server/tasks/routing.py (3)
src/fastmcp/resources/resource.py (1)
key(368-370)src/fastmcp/resources/template.py (1)
key(274-276)src/fastmcp/utilities/components.py (1)
key(94-102)
src/fastmcp/server/server.py (7)
src/fastmcp/resources/resource.py (1)
key(368-370)src/fastmcp/resources/template.py (1)
key(274-276)src/fastmcp/utilities/components.py (1)
key(94-102)src/fastmcp/prompts/prompt.py (5)
PromptResult(109-188)_render(306-310)_render(313-317)_render(319-357)to_mcp_prompt_result(181-188)src/fastmcp/server/tasks/config.py (1)
TaskMeta(25-37)src/fastmcp/server/middleware/tool_injection.py (1)
get_prompt(64-72)src/fastmcp/server/context.py (2)
get_prompt(294-311)request_context(223-249)
⏰ 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). (1)
- GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (6)
src/fastmcp/server/tasks/routing.py (1)
74-76: LGTM!The updated comment accurately reflects the centralized fn_key enrichment design. The server now sets
task_meta.fn_keybefore invoking component methods, and the fallback tocomponent.keyproperly handles direct calls tocheck_background_taskthat bypass the server layer.src/fastmcp/server/server.py (5)
24-24: LGTM!Appropriate import for creating modified copies of the
TaskMetadataclass during fn_key enrichment.
1208-1212: LGTM!The fn_key enrichment logic correctly:
- Only modifies when
task_metais provided butfn_keyis None- Uses immutable
replace()to avoid mutating the original TaskMeta- Sets fn_key to
tool.keyfor proper Docket routing
1302-1332: LGTM!The fn_key enrichment correctly distinguishes between resources and templates:
- Resources use
resource.key(derived from concrete URI)- Templates use
template.key(derived from URI template pattern)This ensures proper Docket routing for both component types.
1348-1427: LGTM!The
render_promptmethod correctly:
- Provides overloads for type narrowing based on
task_metapresence- Propagates
task_metathrough the middleware chain (line 1415)- Enriches
fn_keywithprompt.keybefore delegating to_render()(lines 1423-1425)- Documents the task_meta parameter and return type variations
This completes the task_meta support for prompts, consistent with tools and resources.
1660-1701: LGTM!The
_get_prompt_mcphandler now correctly:
- Extracts SEP-1686 task metadata from MCP request context (lines 1681-1691)
- Passes
task_metatorender_prompt()for centralized fn_key enrichment (line 1693)- Handles both
CreateTaskResultandPromptResultreturn types (lines 1695-1697)The implementation is consistent with
_call_tool_mcpand_read_resource_mcp, completing the task_meta propagation for all three component types.
c025f06 to
f429b01
Compare
Test Failure AnalysisSummary: The integration test timed out after 30 seconds due to a rate limit response from GitHub's Copilot MCP API. Root Cause: The test is hitting the external GitHub Copilot MCP API (), which returned a 429 rate limit error. The test timeout occurred because the client was waiting for a response that never completed due to the rate limiting. This is not related to the PR changes - it's an environmental issue with the external API. Suggested Solution: This is a flaky integration test that depends on external API availability and rate limits. The failure is unrelated to the refactoring of enrichment logic in this PR. Options:
Detailed AnalysisThe test failed with this sequence:
Key log excerpt showing the rate limit: This PR changes internal enrichment logic and adds parameter support for prompts - none of which affects external HTTP requests to GitHub's API. Related Files
|
Completes the
task_metaparameter work started in #2749 (tools) and #2750 (resources) by extending it to prompts, then consolidates the fn_key enrichment logic.task_meta for prompts:
fn_key centralization: Moved fn_key enrichment from 9 locations (component
_run/_read/_rendermethods and provider wrappers) to 3 server methods (call_tool,read_resource,render_prompt). The server now sets fn_key immediately after finding the component, before invoking its method.Also removes dead code: unused
_task_metadataand_docket_fn_keycontext variables,get_task_metadata()function, and deprecatedkeyparameter incheck_background_task().