77WARNING: These APIs are experimental and may change without notice.
88"""
99
10+ import warnings
1011from collections .abc import Awaitable , Callable
1112from dataclasses import dataclass , field
12- from typing import Any
13+ from typing import Any , overload
14+
15+ from typing_extensions import deprecated
1316
1417from mcp .server .experimental .task_context import ServerTaskContext
18+ from mcp .server .experimental .task_scope import scoped_task_id
1519from mcp .server .experimental .task_support import TaskSupport
1620from mcp .server .session import ServerSession
1721from mcp .shared .exceptions import McpError
2933 Tool ,
3034)
3135
36+ EXPLICIT_TASK_ID_DEPRECATION = (
37+ "Passing an explicit task_id to run_task is deprecated. A task created with an "
38+ "explicit ID is not associated with the session that created it: any requestor "
39+ "that presents the ID can read its status and result or cancel it, and it never "
40+ "appears in tasks/list. Omit task_id to let the SDK generate an ID associated "
41+ "with the creating session."
42+ )
43+
3244
3345@dataclass
3446class Experimental :
@@ -143,6 +155,25 @@ def can_use_tool(self, tool_task_mode: TaskExecutionMode | None) -> bool:
143155 return False
144156 return True
145157
158+ @overload
159+ async def run_task (
160+ self ,
161+ work : Callable [[ServerTaskContext ], Awaitable [Result ]],
162+ * ,
163+ task_id : None = None ,
164+ model_immediate_response : str | None = None ,
165+ ) -> CreateTaskResult : ...
166+
167+ @overload
168+ @deprecated (EXPLICIT_TASK_ID_DEPRECATION )
169+ async def run_task (
170+ self ,
171+ work : Callable [[ServerTaskContext ], Awaitable [Result ]],
172+ * ,
173+ task_id : str ,
174+ model_immediate_response : str | None = None ,
175+ ) -> CreateTaskResult : ...
176+
146177 async def run_task (
147178 self ,
148179 work : Callable [[ServerTaskContext ], Awaitable [Result ]],
@@ -167,9 +198,17 @@ async def run_task(
167198 When work() returns a Result, the task is auto-completed with that result.
168199 If work() raises an exception, the task is auto-failed.
169200
201+ Generated task IDs embed the session's task scope so that the default
202+ task handlers only serve the task to the session that created it. An
203+ explicitly provided `task_id` is used verbatim and is not associated
204+ with the session, so any session can access it through the default
205+ handlers; passing one is deprecated for that reason.
206+
170207 Args:
171208 work: Async function that does the actual work
172- task_id: Optional task ID (generated if not provided)
209+ task_id: Deprecated. Optional task ID, used verbatim and not
210+ associated with the creating session. Omit it to let the SDK
211+ generate one.
173212 model_immediate_response: Optional string to include in _meta as
174213 io.modelcontextprotocol/model-immediate-response
175214
@@ -196,6 +235,8 @@ async def work(task: ServerTaskContext) -> CallToolResult:
196235
197236 WARNING: This API is experimental and may change without notice.
198237 """
238+ if task_id is not None :
239+ warnings .warn (EXPLICIT_TASK_ID_DEPRECATION , DeprecationWarning , stacklevel = 2 )
199240 if self ._task_support is None :
200241 raise RuntimeError ("Task support not enabled. Call server.experimental.enable_tasks() first." )
201242 if self ._session is None :
@@ -210,6 +251,11 @@ async def work(task: ServerTaskContext) -> CallToolResult:
210251 # Access task_group via TaskSupport - raises if not in run() context
211252 task_group = support .task_group
212253
254+ if task_id is None :
255+ session_scope = self ._session .experimental .task_session_scope
256+ if session_scope is not None :
257+ task_id = scoped_task_id (session_scope )
258+
213259 task = await support .store .create_task (self .task_metadata , task_id )
214260
215261 task_ctx = ServerTaskContext (
0 commit comments