Skip to main content

Async Tasks (2025) — Advanced Features

← Back to Dashboard
1. Sampling & Roots2. Async Tasks (2025)3. Elicitation & HITL4. Structured Content & Tool Annotations5. Completions & Metadata

Async Tasks (2025)

📚 Advanced Features⏱ 8 min⭐ 100 XP⌨ Hands-on lab

Long-Running Operations & the Tasks Extension (SEP-1686)

Standard MCP tools are synchronous: the host issues a tools/call request and waits for the response. When an agent triggers operations requiring minutes or hours (such as building container images, fine-tuning a model, or running large database migrations), synchronous execution risks proxy timeouts and dropped HTTP connections. Introduced experimentally in 2025-11-25 (SEP-1686) and formalized in 2026-07-28 as the official io.modelcontextprotocol/tasks extension, Tasks standardize durable background operations.

The MCP Task Lifecycle
  1. Immediate Handle Return: A task-augmented request initializes background work and immediately returns a unique taskId with status "working" / "running".
  2. Progress Notifications: For streaming requests, servers can emit notifications/progress containing a progressToken, current progress, and total units.
  3. Non-Blocking Polling & Updates: In 2026-07-28, blocking tasks/result calls were replaced by stateless polling via tasks/get (plus tasks/update and tasks/list).
  4. Cooperative Cancellation: The client can issue tasks/cancel if the user aborts the workflow, cleanly reclaiming compute resources.
import { McpServer } from "@modelcontextprotocol/server";
import { z } from "zod";

const server = new McpServer({ name: "cloud-builder", version: "1.0.0" });

server.registerTool(
  "run_container_build",
  {
    description: "Start an asynchronous container build job",
    inputSchema: z.object({ repoUrl: z.string().url(), tag: z.string() })
  },
  async ({ repoUrl, tag }, extra) => {
    const taskId = "build_" + Date.now();
    
    // Spawn background worker process
    spawnBuildWorker(taskId, repoUrl, tag, async (current, total) => {
      // Stream real-time progress back to the host client
      if (extra._meta?.progressToken) {
        await extra.sendNotification({
          method: "notifications/progress",
          params: {
            progressToken: extra._meta.progressToken,
            progress: current,
            total: total
          }
        });
      }
    });

    return {
      content: [{ type: "text", text: "Build started asynchronously. Task ID: " + taskId }]
    };
  }
);
⌨ HANDS-ON LABQuery Async Background Task Status
⭐ +150 XP

Query the execution status of an asynchronous background task on the MCP server.

1Send tasks/get method for a long-running task.
lab-sandbox — simulated environment
INFINITY LAB SANDBOX v2.6 — simulated shell
Type the command for the current objective. Helpers: "hint", "solution", "clear".
$
OBJECTIVE 1 / 1 — type "hint" if stuck
🧪 Knowledge Check
Press 1-4 to select1 of 3
Why were Tasks introduced into the MCP spec in 2025?
To replace JSON with XML.
To handle long-running tool executions asynchronously without blocking the client connection.
To improve text rendering.
To manage memory garbage collection.