For agent users

Your agent is guessing at your domain.

It does not have to. factum-mcp hands it the conceptual schema — as facts, with every rule stated.

A coding agent working in your repository has access to your code, your migrations and your table names. What it does not have is the reasoning that produced them: which rules are enforced because the business demands it, which columns are nullable for a real reason and which by accident, what a row in enrolment actually means. So it reconstructs. It is very good at reconstructing. It is also unfalsifiable, because nothing on disk disagrees with it.

Every prompt you write that begins “in our system, a customer can have several accounts, but…” is a fact type you are re-typing because it was never written down.

8tools over the model
1line of config
7read-only, one guarded write
0network calls, all local

One line of config

Install the extension (which bundles the CLI and the server), then point any MCP client at it. It speaks stdio, runs locally, and reads files you already have.

{ "mcpServers": { "factum": { "command": "factum-mcp" } } }

That is the whole integration. There is no account, no index to build, no embedding step and no daemon — the model is a file, and the server reads it when asked.

works with Claude Code Copilot Cursor any MCP client over stdio

What the agent gets

Seven read tools and one guarded write. Nothing here is a chat wrapper around a diagram — each tool answers a question the agent would otherwise answer by inference.

ToolWhat it returnsWhy the agent needs it
read_modelAn outline of object types, fact types, readings and subtypesThe shape of the domain, before answering anything about it
verbalize_modelThe FORML sentences for every fact type and constraintThe rules, in the format the model reasons best in
read_populationSample facts read back through the readingsGrounded examples — few-shot data you did not have to write
validate_modelWell-formedness problems, and samples that contradict constraintsTo check its own work instead of asserting it is fine
generate_schemaSQL DDL or LadybugDB Cypher DDL, with mapping notesTo get from concepts to a migration without inventing the middle
diff_modelsWhat changed, as sentences rather than a JSON diffTo explain a change in a review a human will read
detect_driftWhere a pg_dump and the model disagree, with reconciling statementsTo notice that production moved on without the model
apply_modelA validated write of the whole documentTo record a decision — and to be refused when the result is broken
apply_model validates before it writes and refuses a model with blocking errors unless explicitly overridden. This is the load-bearing part: an agent can be wrong, but it cannot quietly commit an incoherent schema.

The difference in one session

Same repository, same prompt, same model. The only variable is whether the fact layer exists.

Without the model

> add support for contractors who
  work for more than one company

// Looked at: schema.sql, Person.ts
- I'll add a `company_id_2` column
- ...or a join table, if you prefer?
- Note: existing rows assume one
  company; I can't tell whether that
  was a rule or just the data.

With factum-mcp

> add support for contractors who
  work for more than one company

// verbalize_model, read_population
- "Each Person works for exactly one
  Company" is a mandatory role plus a
  uniqueness constraint — a stated rule,
  not an accident of the data.
- Contractor and Employee are already
  subtypes of Person, so I moved the
  uniqueness onto Employee rather than
  relaxing it for everyone.
  validate_model passes.
- Diff for review:
  - Each Person works for at most
    one Company.
  + Each Employee works for at most
    one Company.

The second answer is not a smarter model. It is the same model with the constraint in front of it — and, just as importantly, with a validator that would have caught it if it had relaxed the rule for everyone.

Where it pays off

Onboarding an agent to a legacy schema

Run factum derive on a table export, confirm the notes, and the agent has a conceptual schema for a database nobody documented — in an afternoon rather than never.

Migrations that respect the rules

The agent maps from the model rather than editing DDL by hand, so a mandatory role stays NOT NULL and a value constraint stays a CHECK.

Pull requests a human can approve

The bundled Action comments with what the model now says. Reviewing an agent's schema change becomes reading one sentence.

Catching the confident wrong answer

validate_model checks constraints against your recorded sample facts. An invented rule that your own data contradicts is reported, not believed.

Graph and relational from one source

Ask for either target. The n-ary fact type no edge can hold gets reified into a node, because the mapping knows what the fact type is.

Context that fits

The whole domain, verbalized, is small enough to put in a prompt. The agent reasons over all of it, not the three chunks a retriever returned.

It is not an AI feature

Nothing on this page calls a language model. Factum has no chat panel, no API key, no telemetry and no inference of its own — the verbalizer, the validator and the mappers are deterministic code that would work exactly the same in 2005.

That is the point. The agent is your agent, running where you already run it, reading a file you own. Factum's job is to make sure the file says something true.