# `ExMCP.ACP.Adapters.ZCode.Protocol`
[🔗](https://github.com/azmaveth/ex_mcp/blob/v1.3.0/lib/ex_mcp/acp/adapters/zcode/protocol.ex#L1)

Pure helpers for ZCode's `app-server` stdio protocol.

ZCode Protocol v1 is NDJSON over stdio. Messages are JSON-RPC-shaped but
omit the `jsonrpc` field — the envelope is `{id?, method?, params?, result?,
error?}`. IDs may be strings or integers.

This module owns only wire-shape construction and parsing. Translation
between ACP and ZCode message semantics lives in `ZCode.Mapper`.

# `cli_path`

```elixir
@spec cli_path(keyword()) :: String.t()
```

Returns the ZCode executable path.

# `command`

```elixir
@spec command(keyword()) :: {String.t(), [String.t()]}
```

Returns the ZCode command line used by app-server sessions.

# `encode_error`

```elixir
@spec encode_error(String.t() | integer(), integer(), String.t()) :: map()
```

Builds a ZCode error response.

# `encode_notification`

```elixir
@spec encode_notification(String.t(), map() | nil) :: map()
```

Builds a ZCode notification (no id).

# `encode_request`

```elixir
@spec encode_request(String.t() | integer(), String.t(), map() | nil) :: map()
```

Builds a ZCode request message.

# `encode_response`

```elixir
@spec encode_response(String.t() | integer(), map() | nil) :: map()
```

Builds a ZCode success response.

# `env`

```elixir
@spec env(keyword()) :: map()
```

Environment required for ZCode app-server.

# `line`

```elixir
@spec line(map()) :: String.t()
```

Encodes one ZCode message as an NDJSON line.

# `model_ref`

```elixir
@spec model_ref(map()) :: map() | nil
```

Extracts the model reference from a ZCode session/snapshot.

# `permission_options`

```elixir
@spec permission_options([map()]) :: [map()]
```

Converts ZCode permission options into ACP permission options.

ZCode options carry a pre-resolved `response` field (the decision that
selecting each option produces). We map the ZCode decision vocabulary
(`allow`/`deny`/`escalate`/`modify`) to ACP permission option kinds.

# `permission_result`

```elixir
@spec permission_result(map(), [map()]) :: map()
```

Converts an ACP permission outcome back into a ZCode permission response
(`Nv` shape: decision/reason/modifiedInput/permissionUpdates).

The ACP client responds with `{outcome: "selected", optionId: ...}` or
`{outcome: "cancelled"}`. We find the matching ZCode option's pre-resolved
`response` and return it, falling back to a deny.

# `permission_tool_call`

```elixir
@spec permission_tool_call(map(), String.t() | nil) :: map()
```

Maps a ZCode `interaction/requestPermission` request into an ACP tool call
suitable for `session/request_permission`.

# `prompt_content`

```elixir
@spec prompt_content(list() | String.t() | nil) ::
  {:ok, String.t()} | {:error, String.t()}
```

Converts ACP prompt blocks into ZCode session/send content.

ZCode's `session/send` accepts a `content` string. In v1 we support
text-only prompts. Image/embedded-context support is a follow-up.

# `session_id`

```elixir
@spec session_id(map()) :: String.t() | nil
```

Extracts the session ID from a ZCode session snapshot.

# `stop_reason`

```elixir
@spec stop_reason(String.t() | nil) :: String.t()
```

Maps a ZCode turn.completed resultType to an ACP stopReason.

ZCode result types: success, cancelled, error_max_turns,
error_max_budget, error_during_execution, error_max_tool_calls.

# `workspace_ref`

```elixir
@spec workspace_ref(String.t()) :: map()
```

Builds the workspace descriptor required by the ZCode Protocol.

---

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