Tasks belong in capabilities.tasks (first-class field) per SEP-1686,
not capabilities.experimental.tasks. This fixes VS Code Copilot 1.107+
integration which checks capabilities.tasks?.requests?.tools?.call.
Changes:
- Update get_task_capabilities() to return ServerTasksCapability types
- Override get_capabilities() in LowLevelServer to set tasks field
- Remove experimental_capabilities parameter usage
- Update test to verify correct location
Fixes#2870
Removes all the verbose debug logging added during diagnosis while
preserving the essential fix: Context.__aenter__ sets _current_docket
and _current_worker from server instance attributes. This ensures
ContextVars work in ASGI environments where lifespan and request
handlers run in sibling async contexts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
All three handlers (tool, prompt, resource) now have identical patterns:
- Debug logging for docket access, Redis writes, docket.add, subscriptions
- Try/except with traceback logging around Redis and docket operations
- Consistent error messages with instance_id
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Remove redundant ContextVar handling:
- _lifespan_manager no longer re-sets ContextVars in early-return branch
- Handler fallback logic removed (no more `if docket is None: docket = server._docket`)
The authoritative place for request-context ContextVars is now Context.__aenter__,
which sets _current_docket and _current_worker from server instance attributes.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
pydocket 0.16.5 fixes an issue where worker_group_name was passed as
a KEY instead of ARGV in Lua scripts, causing ACL failures when Redis
users are restricted to key patterns.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Tracing where the Redis ACL error occurs - the initial Redis writes
succeed but error happens somewhere after.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When Redis operations fail, log the full traceback to help diagnose
ACL and permission issues in production environments.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Adds detailed logging to Context.__aenter__ and __aexit__ to track:
- When Context is entered/exited
- Values of server._docket and server._worker
- ContextVar values before and after setting
- Token values for debugging reset issues
This will help diagnose why ContextVars might not propagate in Lambda.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Instead of relying on ContextVar propagation from lifespan (which fails
in Lambda), set _current_docket and _current_worker when entering a
Context for each request. This ensures user dependencies like
CurrentDocket() and CurrentWorker() work in all environments.
The values come from server._docket and server._worker which are always
available after lifespan initialization.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ContextVars set during lifespan don't propagate to request handlers
in Lambda (works fine locally). As a workaround, fall back to using
server._docket when the ContextVar returns None.
This is a Lambda-specific issue - possibly related to how Lambda Web
Adapter or Lambda's asyncio runtime handles context propagation.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When FastMCP runs with uvicorn, the lifespan is entered twice:
1. FastMCP's outer context (during http_app setup)
2. Starlette's ASGI lifespan (which request handlers inherit from)
The second call was skipping ContextVar setup because _lifespan_result_set
was already True. This caused _current_docket.get() to return None in
request handlers even though server._docket was correctly set.
Fix: Always set ContextVars when entering _lifespan_manager, using the
already-initialized values from self._docket and self._worker.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
pydocket 0.16.3 fixes a race condition in `_worker_loop` where cancellation
arriving between `_worker_done.clear()` and the try block would cause
`_worker_done.set()` to never run, blocking `Worker.__aexit__` forever.
Also fixes:
- Simplified `_docket_lifespan` cleanup (timeout wrapper no longer needed)
- Fixed `nested_server` test fixture to use graceful uvicorn shutdown
- Fixed uv transport tests to use local fastmcp in dev mode
Closes#2679🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When a dependency raises ToolError or other FastMCPError subclasses, they
were getting wrapped in RuntimeError with a generic "Failed to resolve
dependency" message. This made it hard to use ToolError for validation
in dependencies.
Now FastMCPError subclasses propagate unchanged, matching the pattern
used elsewhere in the codebase.
Closes#2633🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Adopt streamable_http_client API from MCP SDK
- Update import to use new streamable_http_client function
- Convert httpx_client_factory to httpx.AsyncClient before passing to new API
- Maintain backward compatibility by continuing to accept factories
- Add deprecation warning for sse_read_timeout parameter
The new API accepts httpx.AsyncClient directly instead of factories.
We continue accepting factories for OAuth compatibility, converting
them to clients at the boundary with the MCP SDK.
* Fix timeout type conversion for streamable_http_client
Convert read_timeout_seconds from timedelta to float before passing
to httpx, matching the pattern used in the SSE transport.
* Enable redirect following in httpx client
* Fix httpx client resource leak