@@ -2177,6 +2177,36 @@ if __name__ == "__main__":
21772177_ Full example: [ examples/snippets/clients/stdio_client.py] ( https://github.com/modelcontextprotocol/python-sdk/blob/main/examples/snippets/clients/stdio_client.py ) _
21782178<!-- /snippet-source -->
21792179
2180+ #### Cancelling Long-Running Tool Calls
2181+
2182+ For regular ` session.call_tool() ` requests, the high-level client waits for the tool result and does not expose
2183+ the generated JSON-RPC request ID. The server-side ` ctx.request_id ` is useful for server logs, progress
2184+ notifications, and low-level protocol handlers, but it is not a client-side cancellation handle unless the client
2185+ already owns the original request ID.
2186+
2187+ For long-running work that a client needs to cancel, prefer the experimental task API when the server supports it:
2188+
2189+ ``` python
2190+ from mcp.types import CallToolResult
2191+
2192+ # Start the tool as a task instead of blocking on call_tool().
2193+ task_result = await session.experimental.call_tool_as_task(
2194+ " long_running_tool" ,
2195+ {" input" : " data" },
2196+ )
2197+ task_id = task_result.task.task_id
2198+
2199+ # Later, cancel cooperatively by task ID.
2200+ await session.experimental.cancel_task(task_id)
2201+
2202+ # When a task completes normally, retrieve the normal tool result.
2203+ final = await session.experimental.get_task_result(task_id, CallToolResult)
2204+ ```
2205+
2206+ Protocol-level cancellation with ` CancelledNotification ` is for low-level client implementations that can track the
2207+ in-flight request ID they sent. Avoid relying on private session internals such as ` _request_id ` ; those details are not
2208+ part of the public API.
2209+
21802210Clients can also connect using [ Streamable HTTP transport] ( https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#streamable-http ) :
21812211
21822212<!-- snippet-source examples/snippets/clients/streamable_basic.py -->
0 commit comments