# `ConduitMcp.Client.Task`
[🔗](https://github.com/nyo16/conduit_mcp/blob/v0.11.0/lib/conduit_mcp/client/task.ex#L1)

A server-side task a tool call was turned into.

`ConduitMcp.Client.call_tool/4` with `task: :return` returns one when the
server ran the call as a task:

  * **modern** (`2026-07-28`, the `io.modelcontextprotocol/tasks`
    extension): the server answered `resultType: "task"`;
  * **legacy** (`2025-11-25`): the client task-augmented the call (the
    tool's `execution.taskSupport` allowed it and the server declared
    `tasks.requests.tools.call`) and the server answered
    `CreateTaskResult`.

Poll it with `ConduitMcp.Client.get_task/3`, wait for its result with
`ConduitMcp.Client.await_task/3`, or cancel it with
`ConduitMcp.Client.cancel_task/3`.

## Fields

  * `id` - the server's task id. Task ids are bound to the credential that
    created them and may act as bearer tokens: never log them.
  * `status` - `:working`, `:input_required`, `:completed`, `:failed`,
    `:cancelled`, or `:unknown` for a value this client does not know.
  * `status_message`, `created_at`, `last_updated_at` (ISO 8601 strings).
  * `ttl_ms` - how long the server keeps it (`nil` for unlimited).
  * `poll_interval_ms` - the server's suggested polling interval, or `nil`.
  * `input_requests` - modern `input_required` only: the outstanding
    requests, keyed as the server keyed them.
  * `result` - modern `completed` only: the final result map.
  * `error` - modern `failed` only: the JSON-RPC error object.
  * `era`, `server_id` - where it lives; the poll functions use them.
  * `raw` - the server's string-keyed task map.

# `status`

```elixir
@type status() ::
  :working | :input_required | :completed | :failed | :cancelled | :unknown
```

# `t`

```elixir
@type t() :: %ConduitMcp.Client.Task{
  created_at: String.t() | nil,
  era: :modern | :legacy,
  error: map() | nil,
  id: String.t(),
  input_requests: map() | nil,
  last_updated_at: String.t() | nil,
  poll_interval_ms: non_neg_integer() | nil,
  raw: map(),
  result: map() | nil,
  server_id: String.t(),
  status: status(),
  status_message: String.t() | nil,
  ttl_ms: non_neg_integer() | nil
}
```

# `from_wire`

```elixir
@spec from_wire(String.t(), :modern | :legacy, term()) ::
  {:ok, t()} | {:error, ConduitMcp.Client.Error.t()}
```

Builds a task from a wire `Task` map: the modern `CreateTaskResult` /
`tasks/get` result, or a legacy `Task` (legacy keys `ttl` and
`pollInterval` are read as well). A map without a string `taskId` is a
`:protocol` error with reason `:invalid_task`.

    iex> {:ok, task} =
    ...>   ConduitMcp.Client.Task.from_wire("files", :modern, %{
    ...>     "taskId" => "t1",
    ...>     "status" => "working",
    ...>     "pollIntervalMs" => 500
    ...>   })
    iex> {task.status, task.poll_interval_ms}
    {:working, 500}

# `terminal?`

```elixir
@spec terminal?(t()) :: boolean()
```

Whether `task` reached a terminal status.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
