Skip to content

Conversation

@chrisguidry
Copy link
Collaborator

We've migrated FastMCP off temporary shim types and onto the MCP SDK's native task protocol implementation. The SDK's SEP-1686 branch now provides all the types we were defining ourselves, so we can use them directly.

Key changes:

  • Replace shim types with SDK types: Import task protocol types (GetTaskRequest, ListTasksRequest, CancelTaskRequest, TaskStatusNotification) directly from mcp.types instead of our temporary definitions
  • Delete redundant monkeypatching: SDK's RequestParams base class already includes the task field, so our extensions were unnecessary (~60 lines removed)
  • Consolidate remaining shims: Moved TasksResponse result parser to client shim, deleted entire server shim file, kept only FastMCP-specific helpers
  • Fix SDK integration issues: Handle SDK's datetime objects in task responses, remove _meta duplication in favor of spec-compliant params.task field
  • Update SDK reference: Switch from local file:// to GitHub git reference for the SEP-1686 branch

What's gone:

  • ~520 lines of temporary type definitions
  • Redundant param class extensions
  • Union monkeypatching (SDK unions already complete)
  • Server shim file entirely

What remains (~150 lines):

  • task_capable_initialize() - SDK doesn't support capability injection yet
  • TasksResponse - FastMCP's result parser for polymorphic responses
  • CallToolResult - FastMCP's existing typed result wrapper (moved back from shims)
  • TaskStatusResponse - Snake_case ergonomic wrapper
  • TaskNotificationHandler - Notification routing to Task objects

All 3269 tests passing. Examples validated.

Related: modelcontextprotocol/python-sdk#1645

🤖 Generated with Claude Code

chrisguidry and others added 9 commits November 21, 2025 11:18
Switched to local SDK path to test against maxisbey/SEP-1686_Tasks branch.
Updated taskHint from bool to Literal['never', 'optional', 'always'] to match
SDK's new type definition. This fixes 19 task tests.

Remaining issue: 94 task tests still fail with "Method not found" - the SDK's
task protocol methods (tasks/get, tasks/result, etc.) need to be registered
with the session. That's next.

Test results: 76/170 task tests passing (44.7%)

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

Co-Authored-By: Claude <[email protected]>
Successfully migrated from FastMCP's custom task protocol registration to use
the SDK's built-in types and request handling. All 165 task tests now passing.

Changes:
- Use SDK types directly: GetTaskResult, CancelTaskResult, ListTasksResult from mcp.types
- Register task handlers with SDK's request_handlers (tasks/get, tasks/result, tasks/list, tasks/cancel)
- Remove setup_task_protocol_handlers() - no longer needed
- Remove tasks/delete entirely (not in SEP-1686 spec, only tasks/cancel exists)
- Remove DeleteTaskRequest, Task.delete(), Client.delete_task()
- Remove 4 delete-related tests

Test results: 165/165 task tests passing (100%), up from 76/170 (44.7%)

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

Co-Authored-By: Claude <[email protected]>
The SDK's monkeypatched CallToolRequestParams now includes the spec-compliant
'task' field, which appears in serialized payloads. Updated inline snapshots to
reflect this change:

- payload JSON now includes "task":null
- payload_length: 98 → 110 bytes (+12 characters)
- payload_tokens: 24 → 27 (+3 tokens)

All logging middleware tests now pass.
The SDK expects `TaskMetadata` instances but FastMCP was passing raw dicts like `{"ttl": 60000}`, causing 179 Pydantic serialization warnings across the test suite.

Fixed by:
- Importing TaskMetadata from mcp.types in shims
- Updating extended param classes to use `TaskMetadata | None` instead of `dict[str, Any] | None`
- Converting task metadata dicts to TaskMetadata instances in client code before passing to request params

All 3269 tests passing, zero warnings.

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

Co-Authored-By: Claude <[email protected]>
Removed defensive _meta duplication from client requests. Task metadata now sent only via spec-compliant params.task field.

Server now accesses task metadata through SDK's request_context.experimental.task_metadata instead of trying to extract from req.params directly. This is the canonical SDK pattern per the simple-task example.

Changes:
- Client: removed _meta=meta from call_tool, get_prompt, read_resource requests
- Server: updated _call_tool_mcp to use request_context.experimental.is_task
- Server: custom handlers for read_resource and get_prompt to support CreateTaskResult returns
- Task routing moved to custom handlers since SDK decorators for read_resource/get_prompt don't support CreateTaskResult yet

All 3269 tests passing.

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

Co-Authored-By: Claude <[email protected]>
The SDK now includes all task protocol types we were shimming, so we can replace our temporary definitions with SDK imports. This reduces code duplication and ensures we stay aligned with SDK changes.

Changes:
- Import task protocol types from mcp.types: GetTaskRequest, GetTaskPayloadRequest, ListTasksRequest, CancelTaskRequest, TaskStatusNotification
- Hoist task imports to top of client.py (removed inline imports)
- Remove redundant monkeypatch code that extended RequestParams classes - SDK's RequestParams base class already includes the task field
- Remove 60 lines of now-redundant type definitions

What stays:
- TasksResponse wrapper (FastMCP-specific result parser)
- Union patching to register task methods with SDK
- task_capable_initialize and ClientMessageHandler (client capability helpers)

All 3269 tests passing.

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

Co-Authored-By: Claude <[email protected]>
The SDK now provides all task protocol types, so we can remove our temporary definitions. Consolidated remaining SDK workarounds into the client shim.

Deleted:
- Server shim file entirely (was nearly empty after removing protocol types)
- Protocol type definitions (GetTaskRequest, ListTasksRequest, etc.) - SDK has these
- Union monkeypatching (SDK unions already include task types)
- TaskCapableClientSession class (unused)
- Legacy type names (TasksGetRequest, TasksResultRequest, etc.)

Moved:
- TasksResponse from server shim to client shim (FastMCP result parser)
- Renamed ClientMessageHandler to TaskNotificationHandler (clearer naming)

Fixed:
- TaskStatusResponse.created_at now accepts datetime (SDK passes datetime objects in-process)

What remains in client shim:
- task_capable_initialize() - SDK doesn't support capability injection yet
- TasksResponse - FastMCP's result parser for polymorphic task results
- CallToolResult - FastMCP's enhanced wrapper with .data field
- TaskStatusResponse - FastMCP's snake_case ergonomic wrapper
- TaskNotificationHandler - Notification routing to Task objects

All 3269 tests passing. Examples/tasks client validated (both background and immediate modes work).

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

Co-Authored-By: Claude <[email protected]>
CallToolResult is not SEP-1686 specific - it's existing FastMCP functionality for typed tool results that was on main. It got moved to the shims file during cleanup but belongs in its permanent home.

Moved:
- CallToolResult from _temporary_sep_1686_shims.py to client.py (after ClientSessionState, matching main branch structure)
- Updated tasks.py to import via TYPE_CHECKING to avoid circular imports
- Added __future__ annotations to tasks.py for forward reference support

All 3269 tests passing.

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

Co-Authored-By: Claude <[email protected]>
Changed from local file:// reference to GitHub git reference pointing at the SEP-1686 task implementation branch. This allows CI and other developers to build without needing a local SDK checkout.

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

Co-Authored-By: Claude <[email protected]>
@marvin-context-protocol marvin-context-protocol bot added enhancement Improvement to existing functionality. For issues and smaller PR improvements. server Related to FastMCP server implementation or server-side functionality. client Related to the FastMCP client SDK or client-side functionality. labels Nov 21, 2025
@chrisguidry chrisguidry merged commit b036360 into sep-1686 Nov 24, 2025
9 checks passed
@chrisguidry chrisguidry deleted the sep-1686-testing-low-level branch November 24, 2025 14:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

client Related to the FastMCP client SDK or client-side functionality. enhancement Improvement to existing functionality. For issues and smaller PR improvements. server Related to FastMCP server implementation or server-side functionality.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants