What is TaskStatus?
TaskStatus is a string enum that represents the discrete lifecycle states a Task object can occupy within the MCP task management system. Rather than exposing raw string comparisons throughout client and server code, MCP formalizes these states so that both sides of a connection can unambiguously interpret a task's current condition. The five values — working, input_required, completed, failed, cancelled — form a small but expressive state machine that covers every meaningful phase from active processing through all terminal outcomes. In the MCP message flow, TaskStatus appears inside Task objects that are returned by task-related methods and pushed via task update notifications. A server transitions a task from working to input_required when it needs the client to supply additional data before it can proceed; the client responds and the task moves back to working. This bidirectional loop can repeat as many times as needed before the task eventually resolves. Servers are responsible for enforcing transition validity — moving directly from input_required to completed without re-entering working is legal, but a server must never emit a status transition out of a terminal state. The enum was introduced alongside the task management capability in a single revision and has remained stable, with no deprecated values. Because the values are plain strings in the wire format, older clients that do not recognise a future status value should treat unrecognised strings as an unknown non-terminal state rather than crashing, preserving forward compatibility. SDK bindings typically generate a typed enum or union so that exhaustive switch statements produce compile-time warnings when new values are added.
When to use
On every Task and every TaskStatusNotificationParams.
When NOT to use
Never invent statuses — clients only understand these five.
Notes
Terminal states are irreversible by spec
Once a task reaches completed, failed, or cancelled, no conforming server may emit a subsequent status update for that task. Clients that cache task state should treat any post-terminal notification as a protocol error rather than silently overwriting the final state. This makes it safe to clean up local resources — timers, UI indicators, queued retries — as soon as a terminal status is received.
input_required pauses billing and timeouts
Many server implementations suspend elapsed-time accounting while a task sits in input_required, because the task is blocked on the client rather than consuming server compute. If your server imposes a wall-clock deadline, make sure the timer is also paused; failing to do so can cause tasks to be marked failed while the client is still composing its response, which is a common production surprise. Check your SDK's task lifecycle hooks to see whether this pause is automatic.
Wire format is a plain string
TaskStatus values are serialised as bare JSON strings, not integers or objects, which means a typo in a custom server implementation produces a silently invalid status that clients may misinterpret as an unknown value rather than raising a parse error. Use the SDK-provided enum constants rather than string literals to avoid this class of bug. Some SDKs add strict validation on deserialisation and will throw on unrecognised values — verify your SDK's behaviour before relying on forward-compatible unknown-value handling.
Distinguish failed from cancelled semantically
failed signals that the server attempted the task and encountered an error it could not recover from, while cancelled signals that the task was deliberately stopped — either by a client cancellation request or by a server policy decision — before a natural conclusion. Clients should surface these differently in UI and logging: failed warrants an error message and possible retry logic, whereas cancelled is an expected outcome that usually requires no user-facing alert.
SDK exhaustiveness checks on new values
Because TaskStatus is a closed enum today, TypeScript and Python SDK bindings typically use exhaustive union types or Python Literal types. If Anthropic adds a new status value in a future MCP revision, existing compiled clients will fail their exhaustive checks at build time rather than silently handling the new state incorrectly. Pin your MCP SDK dependency and review the changelog before upgrading across a major revision boundary.
Fields
| Field | Type | Required | Purpose |
|---|---|---|---|
| working | 'working' | no | Task is executing. |
| input_required | 'input_required' | no | Task is paused waiting for user input. |
| completed | 'completed' | no | Task finished successfully (terminal). |
| failed | 'failed' | no | Task errored (terminal). |
| cancelled | 'cancelled' | no | Task cancelled via tasks/cancel (terminal). |
Examples
Status values
'working' | 'input_required' | 'completed' | 'failed' | 'cancelled'
Common mistakes
❌ Transitioning from completed back to working
✅ Terminal statuses are sticky — create a new task instead.