On this page5 sections
Derivation overview
This is the chapter’s primer. Before you read the five guides below, this page is the one-page map of what gets derived — automatically, no extra wiring — from your Model declaration. Skim the table, then come back to it as you read each guide so you can see what each piece of a declaration unlocks.
Everything below is what makes the “Model is the single source of truth” claim concrete.
Try it — see derivation in action before reading the map
Verified against rune CLI 0.11.0 · @mcp-rune/mcp-rune 0.107.0 · Node 24.
If you finished the Quickstart you already have everything you need: the scaffolded bookshelf-tour project, the MCP Inspector connected to it, and a Book model declared in src/models/book.ts. Before you scan the derivation table, observe two surfaces deriving from that one declaration.
1. Tool list — derived from MODEL_CLASSES
In the Inspector, call list_models with {}. Expect:
[
{
"name": "book",
"endpoint": "books",
"description": "A Book record",
"attributes": ["name", "description"],
"required_attributes": ["name"],
"read_only": false
}
]
Three things on this row are derived: endpoint from static api.endpoint, attributes from the static attributes map, and required_attributes from the required: true flag on name. You didn’t write any of them into a registry — list_models reads the class itself.
2. Prompt guide text — derived from description + attributes
Call get_prompt_guide with { "guide_name": "book" }. The response is a multi-section Markdown guide whose Attribute reference table at the bottom looks like this:
| Attribute | Type | Required | Valid Values |
|---------------|--------|----------|--------------|
| name | string | Yes | |
| description | text | No | |
No template lives in src/prompts/book-prompt.ts for this table — it’s synthesised from the same static attributes block.
Observe: one declaration, two surfaces, zero glue code. Multiply that across every row in the table below and you have the chapter’s argument: the Model is one place, and everything else points back to it. As you read each guide, return to this table to remember which row you’re filling in.
What gets derived
| Surface | Driven by | Covered in |
|---|---|---|
| Prompt schema | attributes + associations (via derivePromptSchema) | Prompt derivation |
| Prompt guide text | description + attributes + examples | Prompt creation |
| 9 polymorphic tools | MODEL_CLASSES registry — every model gets all 9 | Polymorphic tools |
| Form validation | required, default, validation, enumValues | Validation and defaults |
| App forms | attributes + kinds → <input> type per field | Model form |
| Picker / multi-picker | belongsTo / hasMany → recommended picker app | MCP apps, Associations |
| Display rendering | displayValue + per-kind render | Attributes and kinds |
| Search filters | attributes + the search request shaper | Search filters |
| API payload shape | api.convention (defaults to the server-wide one) | API convention |
| Foreign-key columns | associations.belongsTo → {key}_id attribute | Associations |
| Graph edges | associations → (record → target) edges | Retrieval & GraphRAG |
| Embedding text | attributes (text/string fields concatenated) | Analysis quickstart |
| Auto-generated docs | description + attributes + associations | Polymorphic tools (the get_prompt_guide tool) |
What you write vs what derives
What you write What the framework derives
┌────────────────────────┐ ┌────────────────────────────────────┐
│ static description │ │ Prompt guide intro │
│ static api │───▶│ DataLayer endpoint + convention │
│ static attributes │ │ Form fields + validation + kinds │
│ { type, required, │ │ Prompt schema + LLM-facing labels │
│ default, │ │ Search filter surface │
│ validation, │ │ App display rendering │
│ enumValues, … } │ │ Embedding text (analysis layer) │
│ static associations │ │ FK columns + pickers │
│ { belongsTo, │ │ Graph edges (analysis layer) │
│ hasMany } │ │ Required-FK checks at form time │
│ get displayValue() │ │ Picker labels + summary rendering │
└────────────────────────┘ └────────────────────────────────────┘
What you still have to write yourself
Derivation covers the uniform parts. The places where you reach back in and write actual code:
- Custom kinds — when
'string:isbn'needs more than what the built-instringkind does. See Attributes and kinds. - Prompt content — the actual
promptContentgetter on yourPromptclass. The framework providesPromptContentBuilderas a fluent helper, but you decide what goes into the guide text. See Prompt creation. - Custom tools — anything beyond CRUD. The nine polymorphic tools cover the data-plane uniformly; bespoke verbs (cancel a subscription, recompute a score) are
BaseToolsubclasses you write. See Tool creation. - Custom apps — when the default 7 apps don’t fit your UX. See Custom app.
- Domain knowledge — concepts, business rules, workflows. The framework doesn’t synthesize these from your model — they’re a separate declaration set. See Domain knowledge.
The dividing line is: structural derives, semantic doesn’t. The framework can derive that status is an enum with three values; it cannot derive that status: 'completed' should require rating to be set (that’s a business rule). The next several chapters walk through both halves in detail.
What’s next in this chapter
The table above is the map. The rest of chapter II walks every cell:
- Defining a model — the smallest realistic declaration and the four static fields the framework reads.
- Attributes and kinds — the
type:taxonomy and how one value moves through three representations. - Associations —
belongsToandhasMany, the foreign keys they infer, and what derivation unlocks from them. - Validation and defaults —
required,default, and the validation pass that fires before any write. - Definition vs consumption — why the model code is the only place to declare these things, and the architectural seam the next chapter builds on.
After chapter II, Chapter 3 — The Prompt picks up with the first major consumer of the Model: the prompt that teaches an LLM how to fill the form your model defines.