DEV Community

Bracketly
Bracketly

Posted on

MCP's Tasks Extension Lets a Tool Call Run in the Background — If You Get the Object Shape Right

MCP's Tasks Extension Lets a Tool Call Run in the Background — If You Get the Object Shape Right

Model Context Protocol has quietly grown an answer to a problem every MCP server hits eventually: what do you do when a tool call takes thirty seconds, or thirty minutes? A CI pipeline, a batch export, a step that's waiting on a human to click approve — none of that fits the request-response model MCP started with, where the client just sits on the connection until a result comes back.

The Tasks extension is the fix. Instead of blocking, a server can hand back a task handle immediately: a taskId, a status, and enough metadata for the client to poll intelligently. The client checks in with tasks/get (or gets pushed a notifications/tasks/status update), waits for the status to land on completed, failed, or cancelled, and then — this is the part that trips people up — fetches the actual output with a separate tasks/result request. The task object itself never carries the result. It's pure status metadata: taskId, status, a required-but-nullable ttl, timestamps, and a couple of optional fields. If your mental model says "the completed task has the result attached," you'll write code that works in your own test and breaks against a spec-following client.

I went looking for how solid this corner of MCP actually is before building anything, and the honest answer is: still moving. I pulled two versions of the official TypeScript SDK — one from March, one from July — and diffed the actual type definitions. The request-side ttl field (the one you send when asking for a task to be created) changed what values it accepts between those releases. A new extensions field showed up elsewhere in the same schema family. The SDK's own source comments say plainly that these APIs are experimental and may change without notice. That's not a knock on the feature — it's useful and shipping in real servers — but it means a validator has to be built against what's actually in the SDK right now, not against a spec page that might be stating something aspirational.

So that's what I built: paste a Task/status object, a tasks/get/tasks/cancel/tasks/list request or response, a notifications/tasks/status push, a request that's asking for task-backed execution, or a capabilities negotiation object, and it checks the shape against the current SDK — including the required-but-nullable ttl gotcha, the "no result field here" mistake, and the common slip of passing true instead of an empty object {} for a capability flag (MCP's own convention for "yes, I support this").

Free, runs entirely in your browser, nothing you paste leaves your machine: bracketly.pages.dev/tools/mcp-tasks-validator

Top comments (0)