Commit graph

2,571 commits

Author SHA1 Message Date
Jeremiah Lowin
c3ffef677b
SEP-1330 enum schema support (#2549)
* SEP-1330 enum schema support for elicitation

* Add version badges for 2.14.0 elicitation features

* Fix Context.elicit() to handle SEP-1330 enum syntaxes

* Guard against empty list in elicit response_type

* Add guards for empty dict/list edge cases in elicit

* Refactor elicit: extract parsing and response handling to elicitation.py
2025-12-09 12:22:30 -05:00
Chris Guidry
9ea57f9ef8
Merge pull request #2578 from jlowin/remove-enable-tasks
Remove enable_tasks setting, enable task protocol by default
2025-12-09 10:16:52 -05:00
Chris Guidry
46965d2d80
Merge branch 'main' into remove-enable-tasks 2025-12-09 10:04:39 -05:00
Chris Guidry
dc00f5c2bb Centralize task capabilities, add component filtering
Addresses code review feedback:
- Extract `get_task_capabilities()` to avoid duplicating the SEP-1686
  capability structure across transports
- Add `_should_enable_component()` check before task routing for tools,
  resources, and prompts to respect enable/tag filtering
- Simplify tasks/__init__.py to avoid circular import issues

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 10:02:38 -05:00
Jeremiah Lowin
a39b3534e4
SEP-1699: Add SSE polling support with EventStore (#2564)
* Add EventStore and SSE polling support (SEP-1699)

* Add close_sse_stream() method to Context

* Add SSE polling documentation

* Fix missing Context import in docs example

* Remove EventStore from root __init__.py, update docs imports

- Removed EventStore import and export from src/fastmcp/__init__.py
- Updated docs to import EventStore from fastmcp.server.event_store
- Resolves merge conflict by not exporting EventStore from root package
2025-12-09 09:55:51 -05:00
Jeremiah Lowin
cf67152616
Update test workflow to conditionally run pytest on Windows. Added logic to handle test execution differently for Windows and other OS environments, ensuring compatibility and performance optimization. (#2579) 2025-12-09 09:50:20 -05:00
Jeremiah Lowin
413a5a1319
Fix OAuth client to preserve full URL path for metadata discovery (#2577) 2025-12-09 09:47:07 -05:00
Chris Guidry
350f723592 Remove enable_tasks setting, enable task protocol by default
The task protocol (SEP-1686) is now always enabled - server always
registers task handlers and advertises task capabilities. Users still
opt into background execution at the server level (tasks=True) or
component level (task=True on tools, prompts, resources).

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-09 09:34:42 -05:00
Chris Guidry
515e8e832c
Merge pull request #2576 from jlowin/tool-execution-field
Add execution field to base Tool class
2025-12-08 17:11:33 -05:00
Chris Guidry
17520ec5d5 Add execution field to base Tool class
The base Tool class now has an optional `execution` field for storing
task execution metadata (SEP-1686). This lets gateways/proxies preserve
execution info when forwarding tools from backends - previously this
metadata was lost because Tool had no way to store it.

FunctionTool continues to derive execution from task_config as before.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 17:07:49 -05:00
Chris Guidry
659ec38d01
Merge pull request #2575 from jlowin/multi-mount-docket-isolation
Prefix Docket function names to avoid collisions in multi-mount setups
2025-12-08 16:10:28 -05:00
Chris Guidry
4a6f8730f5 Prefix Docket function names to avoid collisions in multi-mount setups
When multiple servers with task-enabled tools are mounted into a parent,
their functions were all registered with Docket using `fn.__name__`. This
meant two mounted servers each having a function named `add` would both
register under `"add"`, with the second overwriting the first.

Now mounted functions use prefixed names matching their client-facing tool
names (e.g., `c1_add`, `c2_add`). Root server functions still use their
original names with no prefix.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 15:12:40 -05:00
Chris Guidry
11ae63807a
Merge pull request #2574 from jlowin/task-proxy-mount-tests
Forbid task execution through proxies, add mount/proxy task tests
2025-12-08 13:46:49 -05:00
Chris Guidry
a335a9dd89 Fix race condition with mounted server task results
When a server is mounted on another, both were creating their own
Docket and Worker instances. With memory:// URLs they share the same
FakeServer queue but have separate result_storage instances. This
caused a race condition where results could be stored in one Docket's
storage but looked up in another's, returning None.

The fix marks mounted servers with `_is_mounted=True` flag so they
skip creating their own Docket/Worker. The parent's Docket handles
all task execution for mounted servers.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 13:33:57 -05:00
Chris Guidry
54fcdad85f Fix ruff isinstance style (X | Y instead of tuple)
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 11:48:23 -05:00
Chris Guidry
82301773cf Proxy tasks forbidden, mount tasks working
Simplifies the task support story for proxies and mounts:
- Mounts get full SEP-1686 task support (unchanged)
- Proxies explicitly forbid task execution

The cross-session task forwarding for proxies turned out to be complex
since each client connection creates a new server lifespan with a new
Docket context, and task keys include session_id. Rather than introduce
that complexity, proxies now explicitly refuse task-augmented execution.

Key changes:
- All proxy components (ProxyTool, ProxyPrompt, ProxyResource,
  ProxyTemplate) now have task_config.mode="forbidden"
- Proxy tests verify forbidden behavior (sync execution works,
  task=True returns error/raises McpError)
- Fixed prompt task handler to check hasattr(prompt, "task_config")
  instead of isinstance(prompt, FunctionPrompt) so it applies to
  ProxyPrompt too
- Added test suites for both proxy and mount task behavior

Also includes minor fixes:
- Fixed result.meta_ -> result.meta in ProxyTool.run()
- Fixed client handling of returned_immediately without taskId
- Bumped pydocket>=0.15.2

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-08 11:44:28 -05:00
Chris Guidry
61108a0bba
Merge pull request #2570 from jlowin/add-task-config-modes
Add TaskConfig for SEP-1686 execution modes
2025-12-08 09:41:59 -05:00
Chris Guidry
5d04b3a217
Merge branch 'main' into add-task-config-modes 2025-12-08 09:38:00 -05:00
Jeremiah Lowin
597286a633
Update VersionBadge to use Mintlify native Badge component (#2571)
Replace custom VersionBadge implementation with Mintlify's native Badge component while preserving custom color and border styling via CSS. This leverages Mintlify's built-in sizing, typography, and icon support while maintaining the original visual design.
2025-12-06 21:23:53 -05:00
Jeremiah Lowin
b291abb460 Fix inline snapshots for task_config rename 2025-12-06 21:05:11 -05:00
Jeremiah Lowin
a231ea4c3c Add TaskConfig for SEP-1686 execution modes
Expose the full MCP task execution modes (forbidden/optional/required)
via TaskConfig instead of just boolean task=True/False.
2025-12-06 21:01:11 -05:00
Jeremiah Lowin
8771f290bd
Rewrite background tasks documentation (#2567)
- Lead with concepts instead of code
- Explain MCP background tasks vs general Python concurrency
- Document Docket's Prefect origins and battle-tested infrastructure
- Add sections on graceful degradation and embedded workers
- Fix version badge to 2.14.0
- Link to SEP-1686 spec
2025-12-06 19:28:14 -05:00
Chris Egersdoerfer
6147c27995
add client kwargs to proxy clients and meta to proxy tool calls (#2520)
* add client kwargs to proxy clients and meta to proxy tool calls

* Update src/fastmcp/client/transports.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update src/fastmcp/server/proxy.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* Update src/fastmcp/utilities/mcp_config.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* update formats and fix lint errors

* remove client callback passthrough

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-12-06 16:21:59 -05:00
Jeremiah Lowin
0cf12fa30c
Add regression tests for functools.wraps + Context (#2524) (#2566)
Follow-up to PR #2563 which fixed the signature handling in
create_function_without_params. These tests ensure the fix
works end-to-end for all object types that support Context injection.
2025-12-06 12:32:39 -05:00
alex
bc5c1bfbd7
docs: document stateless_http for horizontal scaling (#2547) 2025-12-06 11:59:01 -05:00
Aidan Allchin
b9cde3bdb6
Fix: Include signature modification in create_function_without_params (#2563)
* Fix: Include signature modification in create_function_without_params

When excluding parameters via create_function_without_params(), only
__annotations__ was being updated but not __signature__. This caused
Pydantic's _arguments_schema() to fail when it iterated over signature
parameters that didn't exist in the type hints dictionary.

The fix adds proper signature reconstruction matching the pattern used
in without_injected_parameters().
Fixes KeyError: 'ctx' when using @mcp.tool() with Context parameters.

* fix: add regression tests for create_function_without_params

The test_pydantic_typeadapter_compatibility test specifically reproduces the issue from #2562 and verifies the fix.

* fix: linter for test function

---------

Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
2025-12-06 11:57:36 -05:00
Jeremiah Lowin
8d3deeecc9
Add v2.14.0 upgrade guide (#2565)
* Add v2.14.0 upgrade guide section

* Update upgrade guide to use CodeGroup tabs for all migration examples
2025-12-06 11:40:42 -05:00
Jeremiah Lowin
07750efaab
Fix type errors for ty 0.0.1-alpha.31 upgrade (#2561)
* Fix type errors for ty 0.0.1-alpha.31 upgrade

Add type ignores and fixes for ty's stricter checking:
- Path(None) guards in cli.py
- isinstance checks for ElicitRequestFormParams (URL elicitation support)
- TODO(ty) comments for match/isinstance narrowing bugs
- Method override type ignores for generic covariance
- Starlette Middleware typing workarounds
- Dynamic type construction ignores in json_schema_type.py

* Fix remaining type errors for ty 0.0.1-alpha.31

- Add asserts for optional attribute access in tests
- Add type ignores for dynamic httpx transport internals
- Add TODO(ty) comments for `in` operator on str|bytes
- Add TODO(ty) comments for Starlette Middleware typing
- Use cast for prompt.fn async validation in server.py

* Upgrade ty to 0.0.1-alpha.31

Fixes additional test file type errors discovered after upgrade.
2025-12-05 21:29:14 -05:00
Jeremiah Lowin
1ed976b1d9
refactor: move task attribute to function-based variants only [SEP-1686] (#2560)
* refactor: move task attribute to function-based variants only

* fix: update snapshot test for ResourceTemplate without task field
2025-12-05 21:05:42 -05:00
Chris Guidry
960ce77c7e
Merge pull request #2558 from jlowin/unify-enable-tasks
Remove enable_docket setting; Docket is now always on
2025-12-05 12:40:04 -05:00
Chris Guidry
e63855ccf3 fix: use simple sleep for server readiness, restore Windows parallelism 2025-12-05 12:36:20 -05:00
Chris Guidry
bc587208aa fix: wait for HTTP server readiness via httpx request 2025-12-05 12:33:29 -05:00
Chris Guidry
7e4c854625 fix: use simple sleep instead of _wait_for_port on Windows 2025-12-05 12:32:49 -05:00
Chris Guidry
faa897b7d7 fix: skip wait_closed() on Windows to avoid socket shutdown hang 2025-12-05 12:30:27 -05:00
Chris Guidry
0d96f88d59 test: skip redis connection pool disconnect to fix Windows hangs 2025-12-05 12:27:53 -05:00
Chris Guidry
cf101c2a82 test: run Windows tests without xdist parallelism 2025-12-05 12:23:37 -05:00
Chris Guidry
c02c73f556 Use fresh FakeServer per test to prevent shared state issues
Docket stores a shared FakeServer as a class attribute (_memory_server).
When many tests run in parallel, shared state can cause issues on Windows.

Add autouse fixture to reset the shared server before each test.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:18:42 -05:00
Chris Guidry
55297a06a3 Disable Docket strike monitoring in tests (fakeredis busy-loop fix)
Fakeredis doesn't implement blocking xread properly - it returns
immediately instead of waiting. This causes Docket._monitor_strikes
to busy-loop, overwhelming pytest-xdist workers on Windows.

Mock the method to just sleep, since strike coordination isn't useful
with in-memory backends anyway.

See: https://github.com/cunla/fakeredis-py/issues/274

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:12:11 -05:00
Chris Guidry
bcd2e594f0 Use SelectorEventLoop on Windows to fix pytest crashes
Windows ProactorEventLoop has known memory corruption issues that cause
pytest-xdist worker crashes with "node down: Not properly terminated".

Setting WindowsSelectorEventLoopPolicy in conftest.py avoids this issue.

See: https://github.com/python/cpython/issues/116773

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 12:03:05 -05:00
Chris Guidry
53efaeba5b Add timeout to worker cleanup to prevent hanging on Windows
When pytest-xdist terminates worker processes on Windows, the event loop
may close before cleanup can complete. Adding a 2-second timeout to the
worker cancellation prevents indefinite hanging.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:52:43 -05:00
Chris Guidry
a34b680bb4 Add missing asyncio import
Lost during rebase conflict resolution.

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:42:09 -05:00
Chris Guidry
47d3044b06 Remove enable_docket setting; Docket is now always on
Docket provides background task execution and is now always available
for all FastMCP servers. Only `enable_tasks` remains to control the
SEP-1686 task protocol support.

Changes:
- Remove `enable_docket` setting and related validation
- Docket/Worker lifecycle is always active in server lifespan
- CurrentDocket and CurrentWorker dependencies work without config
- Add server readiness signaling via `_started` event
- Fix test timing issues with proper port probing

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

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-05 11:40:04 -05:00
Jeremiah Lowin
e47abb4bd7
[SEP-1686] Raise ValueError when sync functions have task=True (#2554)
* Raise ValueError when sync functions have task=True

Move validation from server.py decorators to the from_function() class
methods on FunctionTool, FunctionPrompt, FunctionResource, and
FunctionResourceTemplate. This ensures the check runs regardless of how
the objects are created.

* Fix async check for callable classes and staticmethods

Move the task=True async validation to run AFTER callable classes and
staticmethods are unwrapped, preventing false positives for async
callable classes with sync-looking signatures.
2025-12-05 11:31:28 -05:00
Chris Guidry
66aaf420c9
[2.14] SEP-1686 tasks (#2378)
* Implement MCP background tasks (SEP-1686) using Docket

Adds support for background task execution via the MCP task protocol,
powered by Docket for task queue management.

- Tools, resources, and prompts can be marked with `task=True` to run async
- Progress dependency for tracking task progress
- CurrentDocket and CurrentWorker dependencies for advanced use cases
- Client API with `.call_tool(..., task=True)` returns task handles
- Task status notifications via subscriptions
- CLI worker command for distributed task processing

Configuration via environment:
- FASTMCP_ENABLE_DOCKET=true
- FASTMCP_ENABLE_TASKS=true
- FASTMCP_DOCKET_URL=redis://... (or memory:// for single-process)

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

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix tasks example import (TaskStatusResponse → GetTaskResult)

The example was using a non-existent TaskStatusResponse type.
Updated to use mcp.types.GetTaskResult which is what the
on_status_change callback actually receives.

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

Co-Authored-By: Claude <noreply@anthropic.com>

* Fix env var name in Docket error messages

The error messages referenced FASTMCP_EXPERIMENTAL_ENABLE_DOCKET but the
actual setting is FASTMCP_ENABLE_DOCKET.

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

Co-Authored-By: Claude <noreply@anthropic.com>

* Remove deprecated code re-added from pre-#2329 branch

- Remove ExtendedEnvSettingsSource (FASTMCP_SERVER_ prefix support)
- Remove dependencies parameter from FastMCP.__init__

* Replace fakeredis git pin with PyPI release

* Remove redundant fakeredis dev dep (pulled via pydocket)

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
2025-12-04 20:10:35 -05:00
SEONG SEOB KIM
b109cf05cb
Update FastMCP server documentation link (#2529)
The link to FastMCP Server Documentation was pointing to /servers/fastmcp which returns 404. Changed to /servers/server.

Co-authored-by: Jeremiah Lowin <153965+jlowin@users.noreply.github.com>
2025-12-04 19:22:26 -05:00
William Easton
ffb8607e24
Reduce Marvin Test Failure noise
Reduce Marvin Test Failure noise
2025-12-04 18:01:47 -06:00
William Easton
b130c0161e
Small additional changes 2025-12-04 17:57:08 -06:00
William Easton
5838e90105
Purposefully fail the workflow 2025-12-04 17:40:58 -06:00
William Easton
8c2675447f
Update martian-test-failure.yml 2025-12-04 17:39:51 -06:00
William Easton
177eeaee50
Less noise 2025-12-04 17:37:41 -06:00