The MCP server
nexus mcp is a Model Context Protocol server for an AI
assistant that writes flows. Through it the assistant validates and compiles a flow and gets
the compiler’s own diagnostics, and asks what the language allows. The answers come from the
compiler in the same binary, so a flow the server accepts is a flow nexus validate accepts.
Configuring a client
The client starts the server itself, as a child process, and talks to it on stdin and stdout.
The command is nexus, with the single argument mcp. For a client configured in JSON:
{ "mcpServers": { "nexusfabric": { "command": "nexus", "args": ["mcp"] } }}Use the full path to nexus if it is not on the client’s PATH. The server needs no
installation, database, tenant or key: the binary alone is enough.
The tools
All three tools are read-only and idempotent, and touch nothing outside the server. Each answer carries its result twice: as structured content, and as the same JSON in one text block, for clients that read only text.
validate_flow
Input:
| Field | Type | Meaning |
|---|---|---|
source |
string, required | The text of the .flow.md file |
libraries |
array of { "source": string } |
The flows the main flow includes, as text |
Output:
| Field | Meaning |
|---|---|
valid |
true exactly when nexus validate would accept the flow |
flow, tenant |
From the frontmatter, when it parsed |
steps |
The number of steps, when it parsed |
diagnostics |
What the parser and the compiler found, below |
compile_flow
Same input as validate_flow. Output:
| Field | Meaning |
|---|---|
valid |
Whether the flow compiled |
hash |
The artifact’s hash, the one nexus compile -o prints; only when valid |
artifact |
The compiled flow, the JSON nexus compile writes; only when valid |
diagnostics |
As for validate_flow |
describe_language
Input: an optional topic, one of frontmatter, steps, effects, functions. Without a
topic, all four come back. The answer is read from the compiler’s own tables: the
flowmarkdown_version it supports and the frontmatter keys, the step keys and fence languages,
the effects with the keys each one takes, and the names of the built-in functions.
Diagnostics
Each diagnostic has a severity (error or warning), a phase and a message. The message
is the line nexus validate prints for the same problem. The other fields appear when the
compiler knows them:
| Field | Meaning |
|---|---|
phase |
parse, compile, or library (a library left out, a warning) |
line, column, end_line, end_column |
1-based, column in characters. For a step’s error, the step’s header line |
step |
The step the error concerns |
key |
The step key the error concerns |
hint |
The parser’s suggestion |
An error that concerns the whole flow, such as an unsupported flowmarkdown_version, has no
position.
Libraries
A flow’s include steps are resolved only against the libraries passed with the call. A
library that does not parse is left out with a library warning. The server never looks for a
library on disk: an include that names a path is not found, like any other name not passed.
Protocol revisions
The server answers initialize for the revisions 2024-11-05, 2025-03-26, 2025-06-18 and
2025-11-25, and offers 2025-11-25 to a client that asks for any other. It also serves
2026-07-28, which needs no initialize: each request names the revision in its _meta.
Limits
| What | Limit |
|---|---|
source of a flow or of a library |
1 048 576 bytes |
libraries in one call |
64 |
A call over a limit is answered as a tool error that names the field and the limit. A line
that is not JSON is answered -32700, an unknown tool or a missing argument -32602. The
server keeps serving after each.
What it does not touch
The server works only on what the requests carry. It reads no file, not even a .env in the
directory it starts in, and no installation: no registry, no secret, no tenant. No environment
variable reaches a flow: a secret_read step or an env. reference is checked, never
resolved. The one variable it reads is RUST_LOG, the level of its own log, which goes to
stderr. It opens no socket, and its stdout carries only protocol messages. It stops when its
stdin closes.