Skip to main content
Version: 1.1.0 (latest)

Tasks

MCP Tasks allow the server to run long operations that the client can poll for status.

Enabling Task Supportโ€‹

Configure a task store and advertise the tasks capability when creating the server:

use std::sync::Arc;
use rust_mcp_sdk::{
schema::{
ServerCapabilities, ServerTaskRequest, ServerTaskTools, ServerTasks,
schema_utils::{ClientJsonrpcRequest, ResultFromServer},
},
task_store::InMemoryTaskStore,
};

let task_store =
Arc::new(InMemoryTaskStore::<ClientJsonrpcRequest, ResultFromServer>::new(None));

// In your InitializeResult:
capabilities: ServerCapabilities {
tasks: Some(ServerTasks {
// required for task-augmented tools/call requests
requests: Some(ServerTaskRequest {
tools: Some(ServerTaskTools {
call: Some(Default::default()),
}),
..Default::default()
}),
..Default::default()
}),
..Default::default()
},

Then pass the store to server_runtime::create_server via McpServerOptions (see Quickstart for the full setup):

let server = server_runtime::create_server(McpServerOptions {
server_details,
transport,
handler: handler.to_mcp_server_handler(),
task_store: Some(task_store),
client_task_store: None,
message_observer: None,
});

Task-Capable Toolsโ€‹

Mark a tool with task_support:

#[mcp_tool(
name = "process_data",
execution(task_support = "optional"),
)]
pub struct ProcessDataTool {
pub dataset: String,
}

When a client sends a task-augmented tools/call, you must override handle_task_augmented_tool_call - the default implementation returns an error. Create the task with the provided task_creator, run the work, and return a CreateTaskResult immediately:

async fn handle_task_augmented_tool_call(
&self, params: CallToolRequestParams, task_creator: ServerTaskCreator,
runtime: Arc<dyn McpServer>,
) -> Result<CreateTaskResult, CallToolError> {
let ttl = params.task.as_ref().and_then(|t| t.ttl);
let task = task_creator
.create_task(CreateTaskOptions { ttl, poll_interval: None, meta: None })
.await;

// Run the operation in the background and store the outcome with
// task_store.store_task_result(...) once it reaches a terminal state.

Ok(CreateTaskResult { meta: None, task })
}

The client polls tasks/get until the task completes, then fetches the result via tasks/result.

Server-side Task Storeโ€‹

Access the task store from within any handler:

if let Some(store) = runtime.task_store() {
// create_task(options, request_id, request, session_id)
let task = store
.create_task(
CreateTaskOptions { ttl: Some(60_000), poll_interval: None, meta: None },
request_id,
request,
session_id,
)
.await;
}

Note that the tasks capability must be advertised (shown above); otherwise the SDK rejects task-augmented requests before they reach your handler.