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

The outcome of a `tools/call` that the server completed.

A tool that fails reports it in-band: `is_error: true` with the failure in
`content`. That is still `{:ok, %ToolResult{is_error: true}}`;
`{:error, %ConduitMcp.Client.Error{}}` is reserved for protocol, transport
and policy failures.

  * `content` - the `content` blocks, string-keyed, as sent.
  * `structured` - `structuredContent`, or `nil`.
  * `is_error` - `true` when the server sent `isError: true` (or, for a
    synthetic result, when a post-call hook failed and the result was
    withheld; see `ConduitMcp.Client.Hooks`).
  * `meta` - the result's `_meta`, or `%{}`.
  * `extra` - every other wire key (minus `resultType`), never atomized.
  * `provenance` - `nil`, or, for a result shaped for a model
    (`ConduitMcp.Client.Pipeline`, `shape: :llm`), `%{server_id: id,
    truncated: boolean, flags: [atom]}`.

# `t`

```elixir
@type t() :: %ConduitMcp.Client.ToolResult{
  content: [map()],
  extra: map(),
  is_error: boolean(),
  meta: map(),
  provenance:
    %{server_id: String.t(), truncated: boolean(), flags: [atom()]} | nil,
  structured: term()
}
```

# `from_wire`

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

Builds a result from a wire `CallToolResult` map.

`content` must be a list when present (a missing `content` reads as `[]`)
and `isError` a boolean or `null` when present (`null` reads as `false`);
otherwise the result is a `:protocol` error with reason
`:invalid_tool_result`. `resultType` is not checked here: an MRTR interim
result never reaches this function.

    iex> {:ok, result} =
    ...>   ConduitMcp.Client.ToolResult.from_wire(%{
    ...>     "content" => [%{"type" => "text", "text" => "boom"}],
    ...>     "isError" => true
    ...>   })
    iex> result.is_error
    true

---

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