Skip to content

Use CreateTaskResult for background task creation#2660

Merged
jlowin merged 3 commits intomainfrom
create-task-result-refactor
Dec 21, 2025
Merged

Use CreateTaskResult for background task creation#2660
jlowin merged 3 commits intomainfrom
create-task-result-refactor

Conversation

@jlowin
Copy link
Copy Markdown
Member

@jlowin jlowin commented Dec 20, 2025

Background tasks previously returned manually-constructed dicts with _meta fields. This refactor properly uses the MCP SDK's CreateTaskResult type and moves result conversion logic to the components where it belongs.

The SDK's handler decorators have asymmetric capabilities: call_tool supports both CreateTaskResult returns and validate_input, while read_resource and get_prompt don't support CreateTaskResult. We now use the SDK's call_tool decorator (which gives us strict input validation) and custom request handlers only for resources/prompts (with documentation explaining this SDK asymmetry).

# Components now have convert_result() for converting raw Docket values
tool = await server.get_tool(component_id)
fastmcp_result = tool.convert_result(raw_value)  # raw → ToolResult
sdk_result = fastmcp_result.to_mcp_result()       # ToolResult → SDK type

This deletion of converters.py (-204 lines) and consolidation of handler logic makes the task pipeline match the non-background execution path.

Move result conversion logic to components (convert_result methods) and
return proper CreateTaskResult SDK type from task handlers. Consolidates
MCP protocol handler overrides into server.py with documentation.
@marvin-context-protocol marvin-context-protocol Bot added the enhancement Improvement to existing functionality. For issues and smaller PR improvements. label Dec 20, 2025
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 20, 2025

Walkthrough

This PR refactors SEP-1686 task support across client and server flows. Clients now send TaskMetadata TTL and use RootModel unions (CreateTaskResult | specific-result) to either register server_task_id or return synthetic immediate-result tasks; arguments are serialized to strings (non-strings JSON-encoded). Tool/prompt/resource classes gain convert_result methods to centralize result normalization. The server removes the converters module, adds custom read/get handlers, registers task protocol endpoints, and updates task handlers to consistently emit mcp.types.CreateTaskResult with structured Task fields and ISO timestamps.

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main refactor: replacing manual dict construction with the MCP SDK's CreateTaskResult type for background task creation.
Description check ✅ Passed The description is mostly complete with clear explanation of changes, rationale, and code examples, but the Contributors Checklist items are unchecked and some documentation updates are not explicitly confirmed.
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 create-task-result-refactor

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 (1)
src/fastmcp/server/tasks/handlers.py (1)

237-255: Add type annotation for resource parameter.

The resource parameter lacks a type annotation, relying only on a comment. Per coding guidelines, Python 3.10+ type annotations are required throughout.

🔎 Proposed fix
+from fastmcp.resources.resource import Resource
+from fastmcp.resources.template import ResourceTemplate
+
 async def handle_resource_as_task(
     server: FastMCP,
     uri: str,
-    resource,  # Resource or ResourceTemplate
+    resource: Resource | ResourceTemplate,
     task_meta: dict[str, Any],
 ) -> mcp.types.CreateTaskResult:

Note: The imports may already exist elsewhere or need adjustment based on actual module structure. The import at line 306 suggests ResourceTemplate is imported locally, so you may need to move that import to the top level.

🧹 Nitpick comments (2)
src/fastmcp/client/client.py (2)

909-930: Consider moving RootModel import to module level.

RootModel is imported inside multiple methods (_read_resource_as_task, _get_prompt_as_task, _call_tool_as_task). Moving it to the top-level imports would avoid repeated import overhead and improve code clarity.

🔎 Proposed fix at module level

Add to the existing pydantic imports near the top of the file:

-from pydantic import AnyUrl
+from pydantic import AnyUrl, RootModel

Then remove the local imports from lines 909-910, 1126-1127, and 1480.


1129-1147: Argument serialization is duplicated.

The argument serialization logic (lines 1129-1139) is duplicated from get_prompt_mcp (lines 1020-1030). Consider extracting to a helper method for DRY compliance, though this is minor given the limited scope.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9f486e5 and d31363f.

⛔ Files ignored due to path filters (1)
  • tests/server/tasks/test_task_config_modes.py is excluded by none and included by none
📒 Files selected for processing (8)
  • src/fastmcp/client/client.py (4 hunks)
  • src/fastmcp/prompts/prompt.py (2 hunks)
  • src/fastmcp/resources/resource.py (1 hunks)
  • src/fastmcp/server/server.py (4 hunks)
  • src/fastmcp/server/tasks/converters.py (0 hunks)
  • src/fastmcp/server/tasks/handlers.py (12 hunks)
  • src/fastmcp/server/tasks/protocol.py (1 hunks)
  • src/fastmcp/tools/tool.py (3 hunks)
💤 Files with no reviewable changes (1)
  • src/fastmcp/server/tasks/converters.py
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/prompts/prompt.py
  • src/fastmcp/resources/resource.py
  • src/fastmcp/client/client.py
  • src/fastmcp/server/server.py
  • src/fastmcp/tools/tool.py
  • src/fastmcp/server/tasks/handlers.py
  • src/fastmcp/server/tasks/protocol.py
🧠 Learnings (1)
📚 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
  • src/fastmcp/server/tasks/handlers.py
🧬 Code graph analysis (4)
src/fastmcp/prompts/prompt.py (3)
src/fastmcp/resources/resource.py (1)
  • convert_result (381-387)
src/fastmcp/tools/tool.py (2)
  • convert_result (243-248)
  • convert_result (405-443)
src/fastmcp/exceptions.py (1)
  • PromptError (22-23)
src/fastmcp/resources/resource.py (2)
src/fastmcp/prompts/prompt.py (3)
  • convert_result (211-216)
  • convert_result (447-485)
  • from_value (88-106)
src/fastmcp/tools/tool.py (2)
  • convert_result (243-248)
  • convert_result (405-443)
src/fastmcp/server/server.py (1)
src/fastmcp/server/tasks/handlers.py (3)
  • handle_tool_as_task (27-131)
  • handle_resource_as_task (237-340)
  • handle_prompt_as_task (134-234)
src/fastmcp/tools/tool.py (4)
src/fastmcp/prompts/prompt.py (2)
  • convert_result (211-216)
  • convert_result (447-485)
src/fastmcp/resources/resource.py (1)
  • convert_result (381-387)
src/fastmcp/client/tasks.py (4)
  • result (202-207)
  • result (336-393)
  • result (427-458)
  • result (497-551)
src/fastmcp/utilities/types.py (1)
  • Audio (307-362)
🪛 Ruff (0.14.8)
src/fastmcp/prompts/prompt.py

445-445: Avoid specifying long messages outside the exception class

(TRY003)


479-479: 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.13 on ubuntu-latest
  • GitHub Check: Run tests: Python 3.10 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (15)
src/fastmcp/resources/resource.py (1)

379-387: LGTM! Clean centralization of conversion logic.

The convert_result method correctly delegates to ResourceContent.from_value with the resource's mime_type, enabling consistent handling of raw values from Docket background execution.

Note: Unlike Tool and Prompt base classes which define abstract convert_result() methods, the base Resource class doesn't. This seems intentional since base Resource.read() doesn't call convert_result() and only FunctionResource needs it for the Docket path.

src/fastmcp/prompts/prompt.py (2)

211-216: LGTM! Consistent abstract method pattern.

The base Prompt class now defines an abstract convert_result() that subclasses must implement, matching the pattern in Tool. This ensures a consistent interface for the task-based execution flow.


447-485: Well-structured conversion logic.

The convert_result method properly handles all expected input types:

  • PromptMessage instances pass through
  • Strings are wrapped with TextContent
  • Other types are JSON-serialized with pydantic_core.to_json

The error handling correctly wraps conversion failures in PromptError for consistent exception propagation.

src/fastmcp/tools/tool.py (2)

243-248: LGTM! Abstract method defines the contract.

Consistent with the base Prompt class pattern, forcing subclasses to implement their specific conversion logic.


405-443: Correct conversion flow with proper schema handling.

The implementation correctly handles all cases:

  • Pass-through for existing ToolResult instances
  • Unstructured-only for MCP content types (ContentBlock, Audio, Image, File)
  • Attempts dict serialization for structured content when no schema
  • Respects x-fastmcp-wrap-result flag for non-object return types

The raw_value usage at line 442 is safe because schema validation (lines 373-377) ensures output_schema is an object type, and non-object types get the wrap_result flag set, forcing the {"result": raw_value} wrapper.

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

228-278: Clean per-type result conversion with proper metadata injection.

The refactored handler correctly routes to component-specific conversion:

  • Tools: Uses tool.convert_result()to_mcp_result() with proper handling of all three result shapes (CallToolResult, tuple, or content list)
  • Prompts: Uses prompt.convert_result()to_mcp_prompt_result()
  • Resources: Direct ResourceContent.from_value() for raw values

The related-task metadata is consistently injected across all paths, aligning with SEP-1686 requirements.

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

566-599: Clear documentation of SDK asymmetry.

The docstring at lines 567-579 explains the design decision well: tools use the SDK decorator for input validation and CreateTaskResult support, while resources and prompts require custom handlers due to SDK limitations. This is a pragmatic approach to work around SDK constraints.


1258-1347: Well-structured task routing for tools.

The handler correctly:

  1. Extracts task metadata from the SDK request context
  2. Enforces mode="required" by raising McpError when task metadata is missing
  3. Routes to handle_tool_as_task when task support is enabled
  4. Returns an error CallToolResult with isError=True when mode="forbidden" but task was requested
  5. Falls through to synchronous execution otherwise

The returned_immediately: True metadata (line 1337) correctly signals to clients that no background task was created.


1349-1411: Consistent task-aware handlers for resources and prompts.

Both handlers follow the same pattern:

  1. Extract task metadata from request context
  2. Check component's task_config.mode
  3. Route to background execution or raise appropriate errors
  4. Fall through to synchronous execution

Minor inconsistency to verify: When mode="forbidden" but task is requested:

  • Tools return an error CallToolResult with isError=True (lines 1326-1339)
  • Resources/Prompts raise McpError (lines 1399-1404, 1466-1472)

This difference may be intentional since CallToolResult has an isError field while resource/prompt results don't have an equivalent. Please confirm this asymmetry is expected.

Also applies to: 1413-1476

src/fastmcp/server/tasks/handlers.py (3)

27-46: LGTM!

The handler signature and return type are properly updated to use mcp.types.CreateTaskResult. The docstring accurately reflects the new return type.


120-131: LGTM!

The CreateTaskResult construction properly initializes the Task with status="working" and correct timestamp handling. The TTL conversion to milliseconds and pollInterval are appropriate.


134-151: LGTM!

The handler follows the same pattern as handle_tool_as_task with proper return type annotation and documentation.

src/fastmcp/client/client.py (3)

932-950: LGTM!

The branching logic correctly handles both CreateTaskResult (background task accepted) and ReadResourceResult (graceful degradation). Task registration and synthetic ID generation are properly implemented.


1303-1310: LGTM!

The simplified implementation correctly delegates to session.call_tool with all relevant parameters, removing the previous conditional path for task metadata handling.


1469-1507: LGTM!

The implementation correctly constructs the request with TaskMetadata, handles the union response type, and appropriately parses the result for graceful degradation using _parse_call_tool_result.

@jlowin jlowin added this to the MCP 11/25/25 milestone Dec 20, 2025
- Add type annotation for resource parameter in handle_resource_as_task
- Move RootModel import to module level in client.py
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 (1)
src/fastmcp/server/tasks/handlers.py (1)

29-133: Remove unused task_meta parameter or respect client-requested TTL.

The handle_tool_as_task function receives task_meta (containing client-requested TTL) but ignores it, instead using docket.execution_ttl exclusively (lines 78–80, 130). Either remove the unused parameter or implement client TTL support. If server-side TTL policy is intentional, document the override behavior.

🧹 Nitpick comments (2)
src/fastmcp/client/client.py (1)

1125-1136: Consider extracting argument serialization to reduce duplication.

The argument serialization logic (lines 1125-1136) is duplicated from get_prompt_mcp (lines 1017-1028). Consider extracting a helper method like _serialize_prompt_arguments() to maintain DRY.

🔎 Suggested helper extraction
def _serialize_prompt_arguments(
    self, arguments: dict[str, Any] | None
) -> dict[str, str] | None:
    """Serialize prompt arguments for MCP protocol."""
    if not arguments:
        return None
    serialized: dict[str, str] = {}
    for key, value in arguments.items():
        if isinstance(value, str):
            serialized[key] = value
        else:
            serialized[key] = pydantic_core.to_json(value).decode("utf-8")
    return serialized

Then use in both methods:

serialized_arguments = self._serialize_prompt_arguments(arguments)
src/fastmcp/server/tasks/handlers.py (1)

239-244: Consider removing unused server parameter or documenting future intent.

Static analysis correctly flags that server is unused in handle_resource_as_task. Unlike handle_tool_as_task and handle_prompt_as_task which use server.get_tool()/server.get_prompt() to look up components, this handler receives resource directly.

If keeping for signature consistency, prefix with underscore (_server) to suppress the warning and signal intentional non-use. Same applies to task_meta.

🔎 Suggested fix to suppress lint warnings
 async def handle_resource_as_task(
-    server: FastMCP,
+    _server: FastMCP,  # Unused, kept for signature consistency
     uri: str,
     resource: Resource | ResourceTemplate,
-    task_meta: dict[str, Any],
+    _task_meta: dict[str, Any],  # TTL policy from docket.execution_ttl
 ) -> mcp.types.CreateTaskResult:
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d31363f and 7746456.

📒 Files selected for processing (2)
  • src/fastmcp/client/client.py (5 hunks)
  • src/fastmcp/server/tasks/handlers.py (12 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/client/client.py
  • src/fastmcp/server/tasks/handlers.py
🧠 Learnings (2)
📚 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/tasks/handlers.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: When implementing changes that affect MCP object types (Tools, Resources, Resource Templates, or Prompts), such as adding tags or importing, ensure changes are adopted, applied, and tested on all four object types

Applied to files:

  • src/fastmcp/server/tasks/handlers.py
🧬 Code graph analysis (1)
src/fastmcp/client/client.py (1)
src/fastmcp/client/tasks.py (8)
  • ResourceTask (461-551)
  • task_id (105-107)
  • PromptTask (396-458)
  • result (202-207)
  • result (336-393)
  • result (427-458)
  • result (497-551)
  • ToolTask (294-393)
🪛 Ruff (0.14.8)
src/fastmcp/server/tasks/handlers.py

240-240: Unused function argument: server

(ARG001)


243-243: Unused function argument: task_meta

(ARG001)

⏰ 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 with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.13 on ubuntu-latest
🔇 Additional comments (7)
src/fastmcp/client/client.py (4)

33-33: LGTM: RootModel import for union response handling.

The RootModel import from Pydantic enables discriminated union handling for SEP-1686 task responses, allowing the client to distinguish between CreateTaskResult and immediate results.


910-948: LGTM: Clean refactor to RootModel union for resource task handling.

The pattern correctly:

  1. Builds a request with TaskMetadata(ttl=ttl)
  2. Uses RootModel union to handle both CreateTaskResult and ReadResourceResult
  3. Properly extracts server_task_id from raw_result.task.taskId for background tasks
  4. Falls back to synthetic task ID with immediate result for graceful degradation

1299-1306: LGTM: Simplified call_tool_mcp implementation.

Clean consolidation that properly forwards the meta parameter to session.call_tool(), aligning with the SDK's native task support.


1465-1501: LGTM: Consistent task handling pattern for tools.

The implementation correctly:

  1. Builds CallToolRequest with embedded TaskMetadata
  2. Uses RootModel union for discriminated response handling
  3. Parses CallToolResult via _parse_call_tool_result before creating ToolTask with immediate result
  4. Maintains consistency with resource and prompt task handlers
src/fastmcp/server/tasks/handlers.py (3)

21-24: LGTM: Updated TYPE_CHECKING imports for widened type support.

The imports correctly support the widened resource parameter type (Resource | ResourceTemplate) in handle_resource_as_task.


136-236: LGTM: Consistent prompt task handler implementation.

The handler follows the same pattern as handle_tool_as_task with proper CreateTaskResult construction. The same TTL consideration from the tool handler applies here.


331-342: LGTM: Correct CreateTaskResult construction per SEP-1686.

The Task object includes all required fields:

  • status="working" as mandated by spec
  • createdAt and lastUpdatedAt both set to creation time
  • ttl properly converted to milliseconds
  • pollInterval set to reasonable 1000ms default

Prefix with underscore to suppress lint warnings. Client TTL will be
configurable via TaskConfig in the future; keeping parameter for API stability.
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

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 (1)
src/fastmcp/server/tasks/handlers.py (1)

61-62: Remove redundant get_context() call.

The context is retrieved on line 61 and used to get session_id. On line 102, get_context() is called again unnecessarily. The ctx variable from line 61 should be reused for sending the notification on line 105.

This pattern is repeated in all three handler functions (also at lines 170/210 and 276/313).

🔎 Proposed fix
-    ctx = get_context()
-    with suppress(Exception):
+    with suppress(Exception):
         # Don't let notification failures break task creation
         await ctx.session.send_notification(notification)  # type: ignore[arg-type]

Apply the same fix to handle_prompt_as_task and handle_resource_as_task.

Also applies to: 102-105

🧹 Nitpick comments (1)
src/fastmcp/server/tasks/handlers.py (1)

29-137: Consider extracting common task handling logic.

The three handler functions share ~80% of their code (task ID generation, timestamp handling, Redis storage, notification sending, subscription spawning, and result construction). Only the component-specific retrieval and docket queueing differ.

Consider extracting the common logic into a shared helper function to improve maintainability and reduce the risk of inconsistent updates.

Potential refactor approach

A shared helper could handle the common workflow:

async def _execute_as_task(
    component_type: Literal["tool", "prompt", "resource"],
    component_id: str,
    add_to_docket_fn: Callable[..., Awaitable[None]],
) -> mcp.types.CreateTaskResult:
    """Common task execution workflow for all component types."""
    # Task ID generation
    # Timestamp creation
    # Redis storage
    # Notification sending
    # Docket queueing (via callback)
    # Subscription spawning
    # Return CreateTaskResult
    ...

Then each handler would be simplified to component-specific logic + call to the helper.

Also applies to: 140-243, 246-352

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7746456 and fc30d2e.

📒 Files selected for processing (1)
  • src/fastmcp/server/tasks/handlers.py (8 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/fastmcp/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

src/fastmcp/**/*.py: Write Python code with ≥3.10 type annotations required throughout
Never use bare except - be specific with exception types

Files:

  • src/fastmcp/server/tasks/handlers.py
🧠 Learnings (2)
📚 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/tasks/handlers.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: When implementing changes that affect MCP object types (Tools, Resources, Resource Templates, or Prompts), such as adding tags or importing, ensure changes are adopted, applied, and tested on all four object types

Applied to files:

  • src/fastmcp/server/tasks/handlers.py
🧬 Code graph analysis (1)
src/fastmcp/server/tasks/handlers.py (3)
src/fastmcp/server/server.py (2)
  • resource (2072-2215)
  • FastMCP (158-2952)
examples/tasks/client.py (1)
  • task (83-128)
src/fastmcp/client/tasks.py (2)
  • Task (47-291)
  • status (171-199)
⏰ 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.13 on ubuntu-latest
  • GitHub Check: Run tests with lowest-direct dependencies
  • GitHub Check: Run tests: Python 3.10 on windows-latest
🔇 Additional comments (2)
src/fastmcp/server/tasks/handlers.py (2)

21-22: LGTM: Clean type imports and signature updates.

The TYPE_CHECKING imports avoid circular dependencies, and the _task_meta parameter is correctly marked as unused while maintaining signature consistency. The docstring clearly explains that server-side TTL policy takes precedence.

Also applies to: 33-34, 40-51


126-137: LGTM: Correct CreateTaskResult implementation.

The Task object is properly constructed with all required fields per SEP-1686:

  • Server-generated taskId
  • Initial "working" status
  • Timezone-aware timestamps
  • TTL correctly converted to milliseconds
  • Reasonable pollInterval

The return type aligns with the PR's objective to use the MCP SDK's CreateTaskResult type.

@jlowin jlowin merged commit fc8ba72 into main Dec 21, 2025
12 checks passed
@jlowin jlowin deleted the create-task-result-refactor branch December 21, 2025 01:19
@coderabbitai coderabbitai Bot mentioned this pull request Jan 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Improvement to existing functionality. For issues and smaller PR improvements.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant