MCL Developer Documentation
The Matrix Communication Layer (MCL) is the compiler and protocol backbone of Matrix. Every user interaction starts here: natural language goes in, a typed signed Intent IR comes out.
The Matrix Communication Layer (MCL) is the compiler and protocol backbone of Matrix. Every user interaction starts here: natural language goes in, a typed signed Intent IR comes out, and the executor picks it up from there.
This documentation is written for people working on MCL itself, extending the language, adding skills, touching the pipeline, or understanding how the wire protocol works.
Contents
| Document | What it covers |
|---|---|
| MatrixScript Language | The .mtx DSL, syntax, constructs, grammar, all the details |
| Compiler Pipeline | The 6-stage pipeline from intent.draft to intent.compiled |
| Intent IR | The ir package: Intent, Frame, PlanTree, all the Go types |
| Envelope & Wire Protocol | The 15 message kinds, CBOR encoding, ed25519 signing |
| LLM Client | Provider abstraction, grammar-constrained decoding, seeding, model router |
| Writing a SKILL.mtx | Practical guide to authoring and validating skill files |
| mclc CLI Reference | compile, validate, hash, parse commands |
Repository layout
MCL/
├── cmd/mclc/ standalone compiler CLI (Go)
├── core/ compiler-core .mtx modules
│ ├── pipeline.mtx 6-stage pipeline wiring
│ ├── verb.mtx D7 closed vocabulary + classifier prompt
│ ├── frame.mtx Frame type schema
│ ├── confidence.mtx confidence scoring formula
│ └── ...
├── envelope/ wire codec: 15 message kinds, CBOR, ed25519
│ ├── envelope.go Envelope struct, Sign, Verify, SelfHash
│ ├── kinds.go 15 closed message kind constants
│ ├── body.go Typed body structs for all 15 kinds
│ ├── json.go On-disk JSON representation (journal/logs)
│ └── keyresolver.go KeyResolver interface for principal->pubkey
├── ir/ Intent IR Go types + PlanTree
│ ├── intent.go Intent, Frame, SlotEntry, Constraint, Predicate, Unknown, Budget, CompileMetadata
│ ├── plan.go PlanTree, PlanNode, StepPayload, ToolCallPayload, SubDispatchPayload, GatePayload
│ ├── encode.go Canonical JSON encoding + sha256 hashing
│ └── plan_validate.go PlanTree structural validation (8 invariants)
├── llm/ LLM client: 6 providers, 3 API shapes, model router
│ ├── llm.go Client (chat-completions), New(), Config, Decode, Stream
│ ├── messages_api.go messagesClient (Anthropic Messages API)
│ ├── responses_api.go responsesClient (OpenAI Responses API)
│ ├── model.go ModelSlot, StepKind, ModelRegistry, DefaultRegistry
│ └── identity.go IdentityPreamble injection (Forge Phase 1)
└── mtx/ MatrixScript runtime
├── grammar.bnf formal EBNF
├── spec.md language specification
├── token/ token types
├── lexer/ scanner
├── parser/ recursive-descent parser -> AST
├── ast/ AST node types
├── validator/ semantic validation
├── canonical/ deterministic AST hash (D11)
└── interpreter/ AST walker + LLM/Cortex interface
The one-sentence contract
MCL takes intent.draft (prose + optional slot pre-fills) and produces intent.compiled (a fully-typed, signed, deterministically-hashed Intent IR). Everything downstream, executors, walkers, auditors, replays, operates on the IR, never on prose again.
That is the whole point. It is the boundary between the natural-language world and the executable world.
Key locked decisions
These decisions are frozen. Do not re-litigate them without an explicit protocol version bump.
| ID | Decision |
|---|---|
| D7 | Closed verb vocabulary: exactly 10 verbs (find, acquire, build, modify, deliver, analyze, negotiate, schedule, monitor, delegate) plus x: extension namespace |
| D8 | Typed SlotPatch compiles to RFC 6902 JSON Patch on the wire (intent.answer, intent.correct) |
| D9 | Plan-diff materiality classifier (materiality/) determines whether a correction triggers a new plan |
| D11 | Compiler determinism: `seed = sha256(intent.id |
| D13 | Mandatory pre-resolution: all NL entity references resolved to matrix:// URIs before user sign-off. Unresolvable references become Unknown |
| D18 | Compiler/executor split: compiler = small seedable grammar-constrained model. Executor = frontier model. They are never the same slot |
| A9 | Compiler model slot must be seedable and grammar-constrained |
What MCL does
- User types natural language ->
intent.draft - MCL compiler (small seedable grammar-constrained LLM) converts it -> typed
Intent IR - User reviews + signs the IR ->
intent.accept - Executor (main frontier LLM) walks the plan inside skills
- Completion ->
intent.attest(signed, optionally chain-anchored)
No free-form side channels. No prose-only messages. Every input produces a typed artifact.
