Cadmpeg.Mcp (ExCadmpeg v0.1.0)

Copy Markdown View Source

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

Types

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

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

state()

@type state() :: %{documents: %{optional(String.t()) => Cadmpeg.Document.t()}}

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

Functions

fresh()

@spec fresh() :: state()

The state a new server starts with.

handle(line, state)

@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()

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

The protocol revisions this server speaks, newest first.

serve()

@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.