Fix task capabilities location (issue #2870)#2874
Conversation
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
|
Warning Rate limit exceeded
⌛ 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 selected for processing (1)
WalkthroughThe PR refactors task capabilities handling to expose tasks as a first-class field in ServerCapabilities rather than through experimental_capabilities. It removes experimental_capabilities construction from client and server initialization paths, updates Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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 |
Test Failure AnalysisSummary: The integration test Root Cause: Two issues:
Critical Bug in PR Code: # In src/fastmcp/server/low_level.py:186
capabilities.tasks = get_task_capabilities()The problem: {"tasks": {"list": {}, "cancel": {}, "requests": {...}}}But
The current code assigns a dict with a nested "tasks" key, creating the wrong structure. Suggested Solution: 1. Fix the capabilities bug (CRITICAL - blocks the PR goal):# In src/fastmcp/server/tasks/capabilities.py
from mcp.types import ServerTasksCapability
def get_task_capabilities() -> ServerTasksCapability | None:
if not _is_docket_available():
return None
# Return a ServerTasksCapability object directly
return ServerTasksCapability(
list={},
cancel={},
requests={
"tools": {"call": {}},
"prompts": {"get": {}},
"resources": {"read": {}},
},
)OR (simpler - remove the outer "tasks" key): # In src/fastmcp/server/tasks/capabilities.py
def get_task_capabilities() -> dict[str, Any] | None:
if not _is_docket_available():
return None
# Return dict WITHOUT outer "tasks" key - Pydantic will coerce it
return {
"list": {},
"cancel": {},
"requests": {
"tools": {"call": {}},
"prompts": {"get": {}},
"resources": {"read": {}},
},
}2. Address the flaky test (prevents CI from passing):Option A - Add retry with backoff: # In tests/integration_tests/test_github_mcp_remote.py
@pytest.mark.integration
@pytest.mark.flaky(reruns=2, reruns_delay=5)
async def test_call_tool_list_commits(...):
...Option B - Skip on rate limit: import httpx
async def test_call_tool_list_commits(...):
try:
async with streamable_http_client:
...
except httpx.HTTPStatusError as e:
if e.response.status_code == 429:
pytest.skip("GitHub API rate limit exceeded")
raiseDetailed AnalysisError Log Excerpt:The 429 error occurs during test teardown: The test successfully calls Type Verification:# From MCP SDK:
ServerCapabilities.tasks: ServerTasksCapability | None
ServerTasksCapability.model_fields: ['list', 'cancel', 'requests']The current implementation assigns Related FilesFiles requiring changes:
Verification needed:
Note: This comment has been edited to include type verification and refined solution. |
Task capabilities were being set in
capabilities.experimental.tasksinstead ofcapabilities.tasks, which broke VS Code Copilot 1.107+ integration. Copilot checkscapabilities.tasks?.requests?.tools?.callto detect task support—when it doesn't find it, it falls back to synchronous calls with a 5-minute timeout.The fix overrides
get_capabilities()inLowLevelServerto setcapabilities.tasksas a first-class field per SEP-1686, rather than passing it through theexperimental_capabilitiesparameter. FastMCP's existing Docket-based task infrastructure remains unchanged.FastMCP continues to support prompts and resources for task execution (ahead of the spec) via the SDK's
**extra_datamechanism.Closes #2870