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:

  1. Tools — the actions it can take: create elements, add relationships, build diagrams, scan the repository, validate, write the file.
  2. Resources — what it should read first: the rules of C4 in machine-readable form, the authoring guide, worked examples, and the current model.
  3. 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.

ClientWhere
Claude Coderun claude mcp add (below), or edit .mcp.json in the project
Claude DesktopSettings → Developer → Edit Config
Cursor.cursor/mcp.json in the project, or Settings → MCP
VS Code (Copilot).vscode/mcp.json in the project
ZedSettings → 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:

PromptWhat it walks through
author-c4-modelUnderstand the system first, then build it bottom-up so the levels agree with each other
add-deployment-viewWhere the containers actually run, linked back to them
add-flowWhat happens during one interaction, across the elements that perform it
tune-configMake the generated diagrams readable — measure before changing anything
enrich-descriptionsWrite 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:

FileWhy
crayon-c4-project.jsonThe model itself
crayon-c4-provenance.jsonLets a later run tell a name you wrote from the one the code last had
crayon-c4-enrichment.jsonThe 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, section authoring: bidirectional connections or not, the default line style, concise or detailed descriptions, 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

FreeLicensed
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 runsBest for
MCP serverYour agent, in the repoBuilding and maintaining the model as you code, in any language
VS Code extensionYour editorGenerating and reading a model beside your code, with the full viewer
CLIYour terminal or CIRegenerating on a schedule, drift checks in a pipeline
The appYour browserCurating, 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.json reference, 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.