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.
Summary
Functions
The state a new server starts with.
One message: the reply (or nil for a notification) and the state after it.
The protocol revisions this server speaks, newest first.
Reads JSON-RPC messages from stdin and writes answers to stdout until stdin closes.
Types
@type state() :: %{documents: %{optional(String.t()) => Cadmpeg.Document.t()}}
What the server remembers between messages: the documents it has read.
Functions
@spec fresh() :: state()
The state a new server starts with.
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.
@spec protocol_versions() :: [String.t()]
The protocol revisions this server speaks, newest first.
@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.