Skip to main content
notifications/cancelled is a client → server notification (no response expected). The client sends it when the user wants to abort an in-flight request — for example, hitting “Stop” while a long-running tools/call is mid-execution. GetMCP records the cancellation against session_id + request_id in an in-process registry. Code paths that opt into cancellation can poll the flag and bail early.

Wire-level Shape

{
  "jsonrpc": "2.0",
  "method":  "notifications/cancelled",
  "params": {
    "requestId": 42,
    "reason":    "User pressed Stop"
  }
}
params.requestId
integer | string
required
The id of the in-flight request the client wants to cancel.
params.reason
string
Optional human-readable explanation. Logged but not propagated to the upstream API.

Polling the Flag

Once the cancellation lands, any code on the server can check:
use GetMCP\Protocol\CancellationHandler;

if ( CancellationHandler::is_cancelled( $session_id, $request_id ) ) {
    // Abort the loop, close connections, return early.
}
is_cancelled() is O(1) — cheap enough to poll inside a loop iterating over large datasets or pre-flight before each upstream HTTP call.

Caveats

  • The built-in ToolExecutor is synchronous. It does not yet poll is_cancelled() mid-flight, so an in-flight tools/call will run to completion regardless. The hook is in place — wiring it into the executor’s loops is a future change.
  • Custom tools authored via the getmcp_after_tool_call / getmcp_before_tool_call hooks can poll the flag manually.
  • Cancellation state is cleared automatically when the request completes (success or error) so re-using the same request id later doesn’t carry a stale cancel.

Cancellation is “best effort” per the spec. The server is not required to honour every cancel signal — it may simply finish the in-flight work and return the result. GetMCP follows this contract.