The MCP server
The CRAYON-C4 MCP server puts the model where the code is. Instead of you generating a model and then curating it in the app, your coding agent — Claude Code, Claude Desktop, Cursor, VS Code, Zed, anything that speaks the Model Context Protocol — can create it, understand it, keep it current as the code changes, and hand it to you already valid.
It works in any repository. The CLI and the VS Code extension scan Next.js, React, .NET and Java; the MCP server scans those too, and for everything else your agent authors the model by hand through tools that enforce the rules as it goes.
How it works
Your MCP client starts the server itself and talks to it over the process's own
input and output. There is no service to run, no port, and no account: the client spawns
npx @crayon-c4/mcp when you open the project and stops it when you close it.
What the server then offers your agent is three things:
- Tools — the actions it can take: create elements, add relationships, build diagrams, scan the repository, validate, write the file.
- Resources — what it should read first: the rules of C4 in machine-readable form, the authoring guide, worked examples, and the current model.
- Prompts — guided workflows your client lists as commands, so you can say "author a model" rather than describing the whole procedure.
The server holds the model in memory while your agent works on it, validating the whole thing after every single edit, and only writes to disk when you say so. That is what makes the file always importable: a bad edit is rejected before it exists, not discovered later.
Set it up, step by step
Step 1 — check you have Node 18 or newer.
node --version
If that prints anything below v18, install a newer Node first. You do not need to install
CRAYON-C4 itself — npx fetches it the first time your client starts it.
Step 2 — find your client's MCP config file.
| Client | Where |
|---|---|
| Claude Code | run claude mcp add (below), or edit .mcp.json in the project |
| Claude Desktop | Settings → Developer → Edit Config |
| Cursor | .cursor/mcp.json in the project, or Settings → MCP |
| VS Code (Copilot) | .vscode/mcp.json in the project |
| Zed | Settings → Context Servers |
Step 3 — add the server.
In Claude Code, one command does it:
claude mcp add crayon-c4 -- npx -y @crayon-c4/mcp .
Everywhere else, add this block to the config file from step 2:
{
"mcpServers": {
"crayon-c4": {
"command": "npx",
"args": ["-y", "@crayon-c4/mcp", "."]
}
}
}
The "." is the folder the server is allowed to work in — normally your project root.
Every path a tool is given is resolved inside it and cannot escape it. That matters: your
agent is relaying paths it inferred from a conversation, and this is the boundary you
agreed to.
Step 4 — restart your client so it picks up the config, then check it connected. Ask your agent:
What CRAYON-C4 tools do you have?
You should get a list of around twenty — create_model, upsert_nodes, validate_model
and so on. If you get nothing, see troubleshooting.
Step 5 — add a licence key, if you have one. Scanning a repository and AI enrichment need one; everything else does not. Add it to the same block:
{
"mcpServers": {
"crayon-c4": {
"command": "npx",
"args": ["-y", "@crayon-c4/mcp", "."],
"env": { "CRAYON_C4_LICENSE_KEY": "crayon-c4.…" }
}
}
}
Prefer not to put a key in a file you might commit? Put it in .crayon/license in the
project instead and add that path to .gitignore — the server checks there too.
Step 6 — try it. Ask your agent:
Model this repository with CRAYON-C4, down to the container level. Validate before writing anything.
Then read a first run for what to expect back.
The guarantee: it cannot write an invalid model
This is the reason to use it rather than asking an agent to write JSON.
Every edit is applied to a copy, the whole model is validated, and the change is kept
only if it holds — so a rejected edit leaves everything exactly as it was and your agent is
told what it broke. write_model checks again before anything reaches disk and refuses if
it does not pass.
Validation is two passes, because they catch different things:
- the published JSON Schema says whether the file is the right shape;
- the app's own validator says whether it means anything — a connection pointing at an element that is not there, a Component parented to a System, a deployment naming a container that has been deleted.
No schema can express the second kind, and they are exactly what makes an import look empty. Errors come back pointing at the field, with the rule behind them, so your agent fixes and re-tries rather than guessing.
Ask it to understand before it writes
The commonest problem with a generated model is not that it is invalid. It is that every diagram shows the same thing at a different zoom, or that a Context diagram is full of containers.
So the server publishes what C4 means, not just what shape it has: a machine-readable
capability map, the authoring guide, worked examples, and an explain_c4 tool that answers
what each level is for, who reads it, and what belongs on it. It also ships five guided
workflows your client will offer as prompts:
| Prompt | What it walks through |
|---|---|
| author-c4-model | Understand the system first, then build it bottom-up so the levels agree with each other |
| add-deployment-view | Where the containers actually run, linked back to them |
| add-flow | What happens during one interaction, across the elements that perform it |
| tune-config | Make the generated diagrams readable — measure before changing anything |
| enrich-descriptions | Write what a scan could not infer, without rewriting what a person did |
Start with author-c4-model. In Claude Code that is /crayon-c4:author-c4-model; other
clients list prompts in their own way.
A first run
Ask your agent, in its own words:
Read the CRAYON-C4 capability map, then model this repository down to the container level. Scan the code first, tell me what you could not determine, and validate before writing anything.
What you get back is crayon-c4-project.json in the repository, plus two sidecars. Open
the app, choose New project → From file, and pick it.
Keeping it current
When the code has moved on, ask for an update. The server re-scans and reconciles rather than replacing:
- descriptions and names a person wrote are kept;
- a name that changed on both sides is reported as a conflict and left alone until you choose;
- an element the code no longer has is removed only if you ask for it by name — and never if it was hand-authored in the first place.
That promise depends on the sidecars, so commit all three files:
| File | Why |
|---|---|
crayon-c4-project.json | The model itself |
crayon-c4-provenance.json | Lets a later run tell a name you wrote from the one the code last had |
crayon-c4-enrichment.json | The source file each missing description should be written from |
Without crayon-c4-provenance.json, a re-run cannot see which text is yours, and the
server says so rather than quietly doing something weaker.
Steering it
Two places, and the more specific one wins, field by field:
- The repository —
.crayon/config.json, sectionauthoring: bidirectional connections or not, the default line style,conciseordetaileddescriptions, the language to write prose in. It applies to everyone working in the repo. - The session — your agent can set the same things for one conversation.
A setting nobody chose stays at its default rather than being written into your file, and asking the server for its settings tells you the value and where it came from — so "why did it draw arrows at both ends" always has an answer.
Configuration only ever affects things being created. It never rewrites a connection whose direction you already decided.
What needs a key
| Free | Licensed | |
|---|---|---|
| Read the schema, capability map, guide and examples | ✓ | ✓ |
| Validate a model | ✓ | ✓ |
| Create, edit and write a model by hand | ✓ | ✓ |
| Scan a repository — C4, deployment, flows, merge | ✓ | |
| AI enrichment of missing descriptions | ✓ |
Keys are verified offline — the public key is in the download, so it works on a plane, and the offline tier makes no network requests at all.
It also fails open. No key, an unreadable one, an expired one: you get a working free-tier session and a sentence saying why, never a crash. Ask your agent for the licence status at any time to see what the session can do.
Keys are at pricing.
Which tool for which job
| Where it runs | Best for | |
|---|---|---|
| MCP server | Your agent, in the repo | Building and maintaining the model as you code, in any language |
| VS Code extension | Your editor | Generating and reading a model beside your code, with the full viewer |
| CLI | Your terminal or CI | Regenerating on a schedule, drift checks in a pipeline |
| The app | Your browser | Curating, laying out, sharing and exporting |
They are one engine with four faces — the same extractor, the same validator, the same schema — so a model produced by any of them is the same model everywhere else.
Troubleshooting
Your client shows no CRAYON-C4 tools. Check the client's MCP log. The server prints
its diagnostics to stderr, which the client shows as server logs; npx -y @crayon-c4/mcp --help in a terminal confirms it downloads and runs.
Everything works except scanning. That needs a key. Ask for the licence status: it says where it looked and what it found.
A tool says it has no filesystem access. You are connected to the hosted server, which
deliberately cannot read your machine. Use the local one — npx -y @crayon-c4/mcp . — for
anything that touches the repository.
An import into the app rejects the file. Have your agent run its validator and paste the errors: they name the field and the rule. The web import and the server run the same checks, so anything it calls valid will import.
Where next
- Document from code — the CLI, the
.crayon/config.jsonreference, and the update-and-merge loop in the web app. - The three views of a system — what the C4, deployment and F4 slices your agent writes actually mean.
- C4 structure — the element types and containment rules the server enforces on every edit.
- Manage projects — bring the generated model into the app as a new project, or update an existing one.