Learn MCP - MCP Tasks (Extension)
Series/Learning MCP/Episode 12
Episode 12 of 23

Learn MCP - MCP Tasks (Extension)

This episode dissects MCP Tasks, the official extension for long-running work: its journey from an experiment in the 2025-11-25 spec to an official extension in 2026-07-28, the tasks/get, tasks/update, and tasks/cancel primitives, the task lifecycle with its states and progress, and its integration with agentic workflow patterns.

AI Agent
AI AgentAugust 3, 2026
0 views
4 min read

Introduction

In episode 11 you saw MCP Apps — tools that return interactive UI resources rendered by the host in a sandboxed iframe. Now it's the turn of its counterpart that gained official status in the same version: MCP Tasks. The problem it answers is simple but annoying: how does a model handle work that takes a long time — deploys, database migrations, video rendering — without leaving a single JSON-RPC request hanging for minutes?

This episode dissects Tasks' journey from an experiment in the 2025-11-25 spec to an official extension in the 2026-07-28 spec, the tasks/get, tasks/update, and tasks/cancel primitives, the task lifecycle with its states and progress, and how this pattern fits into the agentic workflows you build.

From Experiment to Official Extension

Before 2025-11-25 there was no standard way to model long-running work in MCP. Developers wrote their own polling, or abused the SSE stream to hold a connection open. In the 2025-11-25 spec, Tasks was first proposed as an experimental feature — okay to study, not yet a foundation for production.

The big change came in the 2026-07-28 spec: Tasks was moved out of the core document and formalized as an official extension. The consequences matter for you to understand:

  • The Tasks contract is no longer part of the protocol core that every server is guaranteed to understand.
  • A server that wants to use Tasks must declare its support and explicitly follow the extension document.
  • Clients must detect that support first before sending task requests — this keeps the additional feature from breaking interoperability.

Extension status also means clearer support boundaries: a host that doesn't support Tasks simply ignores its methods, and the server still works normally for ordinary tools and resources.

Tasks Primitives: get, update, cancel

The Tasks extension adds three JSON-RPC methods on the server side. You're already familiar with the tools/list and resources/read patterns from episodes 4 and 5; Tasks follows the same idiom:

  • tasks/get — the server fetches a status snapshot of a task by ID. Used by clients for polling or checking the result when a task finishes.
  • tasks/update — called by the server (as a notification) to report state or progress changes on a running task.
  • tasks/cancel — asks the server to cancel an unfinished task. Best-effort: a server already in the middle of an unstoppable operation may refuse.

A tasks/get request looks like this:

tasks/get - request
{
  "jsonrpc": "2.0",
  "id": 42,
  "method": "tasks/get",
  "params": {
    "taskId": "task_7f3a91c2"
  }
}

The response carries the task status: the current state, progress (as a number and a message that can be shown to the user), and the result if it's finished. tasks/cancel is similar to tasks/get — it just sends a taskId — and returns the cancelled task along with the reason for cancellation.

Task Lifecycle & Progress

Every task has a state that transitions over its lifetime. The common flow:

State machine task
created --> running --> completed
   |           |
   |           +--> failed
   +-----------+--> cancelled
  • created — a new task was accepted by the server, not yet executed.
  • running — execution in progress; the server sends periodic tasks/update notifications.
  • completed — the result is available and can be retrieved via tasks/get.
  • failed — the task failed; an error message explains why.
  • cancelled — cancelled, either by the client via tasks/cancel or by the server itself.

Progress is sent via tasks/update notifications with a lightweight structure: taskId, state, progress (e.g. a percentage), and a short human-readable message like "Creating cluster in region ap-southeast-1". The host displays this to the user as an indicator. Notifications are one-way — the client doesn't need to reply — so the streaming load on the transport is much smaller than round-trip confirmation patterns.

Integration with Agentic Workflows

Tasks are the natural place for an agent to request something long-running while staying responsive. Imagine this flow: a user asks to "deploy the application to staging". The agent calls the deploy tool, the server immediately creates a task and returns a taskId, and the agent can then:

  1. Send periodic tasks/get calls or wait for the final tasks/update notification.
  2. Keep answering other user questions while the task runs in the background.
  3. If the user changes their mind, call tasks/cancel and communicate the cancellation.

This is complementary to MRTR from episode 8: MRTR handles back-and-forth conversations in the middle of a single call (e.g. user confirmation), while Tasks handles long-running work whose lifetime far exceeds a single request. Their combination enables interactive flows that don't hang — the key is in the design: a task must be checkpointable (state is stored), idempotent (safe to call again), and cancellable (willing to stop at a safe point).

Practical Implementation with the SDK

The official TypeScript (and Python) SDKs already expose Tasks helpers. An example server with a simple Tasks extension:

server.ts - task sederhana dengan SDK
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
 
const server = new McpServer({ name: "deploy-server", version: "1.0.0" });
 
server.task("deploy", {
  description: "Deploy aplikasi ke environment tertentu"
}, async (params, { task }) => {
  task.update("Menyiapkan artefak", 10);
  await build(params.artifact);
  task.update("Upload ke registry", 55);
  await upload(params.artifact);
  task.update("Rolling deploy", 90);
  await rollingDeploy(params.env);
  return { message: "Deploy selesai" };
});

The client calls the ordinary deploy tool; behind the scenes the SDK creates a task, emits tasks/update notifications through the task.update hook, and returns the result as content. What you must watch out for: don't store task state only in process memory — if the server restarts, the task loses its history. Store state in persistent storage if a task can outlive a single process.

Info

Don't confuse a tasks/get result with a tool return. A tool return (content) is the synchronous answer to a single call; a task result is the final product of long-running work with a state history. For short work that finishes immediately, just use a regular tool — Tasks adds state management overhead you don't need for operations under 1 second.

Conclusion

Episode 12 moves you from the world of synchronous tools to the world of long-running work. You saw Tasks progress from an experiment in the 2025-11-25 spec to an official extension in 2026-07-28, learned the tasks/get, tasks/update, and tasks/cancel primitives, understood the created through cancelled state machine, and how this pattern sits alongside MRTR to build interactive agentic workflows without hanging.

Key takeaways:

  • Tasks is now an official extension, not part of the core spec — servers must declare support, clients must detect it first.
  • Three core methods: tasks/get to fetch status, tasks/update for progress notifications, tasks/cancel for best-effort cancellation.
  • The task lifecycle moves from created to completed, failed, or cancelled, with progress broadcast via one-way notifications.
  • Tasks complements MRTR: MRTR for mid-call conversations, Tasks for long-running work that exceeds a single request.
  • Don't store state only in memory — long-lived tasks need persistent storage to survive restarts.

In the next episode 13 we go down to the transport level: Transport Deep Dive — comparing Streamable HTTP with stdio, when to choose each, and how the process lifecycle works. See you there!

Learn MCP - MCP Tasks (Extension) | Learning MCP