# `Cadmpeg.Mcp`
[🔗](https://github.com/d-led/ex.cadmpeg/blob/main/lib/cadmpeg/mcp.ex#L1)

A Model Context Protocol server over stdio: a CAD file, for an assistant.

One JSON-RPC message per line in, one out — the stdio transport, which is what
a client launches as a process. No sessions, no server-sent events, no batches:
every request is self-contained, which is what lets a client treat it as a
pipe.

## What the tools are for

cadmpeg answers "what is in this file, and can I have it as something else?" and
this server exposes that:

  * **what can this build do?** — `cadmpeg_formats`: the formats it reads and
    the formats it writes;
  * **what is in this file, and how faithfully was it read?** —
    `cadmpeg_inspect`: the document and its decode report, which is where the
    losses are;
  * **give me another format** — `cadmpeg_convert`: write the document out as
    STEP or as its own JSON.

## Documents are opened once

Calls name a path; the server keeps the opened document, so a second question
about the same file does not read it again. The cache is this process's —
restarting the server costs a re-read, and nothing on disk depends on it.

A tool that cannot answer answers: a refusal is text saying what was wrong and
what to try, never a dropped connection.

# `state`

```elixir
@type state() :: %{documents: %{optional(String.t()) =&gt; Cadmpeg.Document.t()}}
```

What the server remembers between messages: the documents it has read.

# `fresh`

```elixir
@spec fresh() :: state()
```

The state a new server starts with.

# `handle`

```elixir
@spec handle(String.t() | nil, state()) :: {String.t() | nil, state()}
```

One message: the reply (or `nil` for a notification) and the state after it.

`nil` for a blank line, and for a line that is not JSON — a transport that
crashes on garbage is a transport nobody can debug.

# `protocol_versions`

```elixir
@spec protocol_versions() :: [String.t()]
```

The protocol revisions this server speaks, newest first.

# `serve`

```elixir
@spec serve() :: :ok
```

Reads JSON-RPC messages from stdin and writes answers to stdout until stdin
closes.

Notifications are answered with nothing, which is what the transport says.

---

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