Version: draft-01
Status: pre-implementation
Author: haitch
Date: 2026-06-11
Repository: github.com/ha1tch/molu
molu is an MCP sidecar for xolu. It connects to a running xolu instance, reads its live schema, and exposes the operational model of that xolu instance as MCP tools that an AI agent can use to perform business operations in natural language.
xolu (github.com/ha1tch/xolu) is the storage engine molu drives.
It provides a multi-model embedded database — documents, graph, timeseries,
blobs, FSMs, events, sequences — accessible over a REST API. xolu is the
system of record. molu never stores anything; all persistent state lives
in xolu.
nolu (github.com/ha1tch/nolu) is the distributed coordination layer
for xolu. It manages multi-instance topology, replication, and load
balancing across a partially-known network of xolu nodes. molu connects
to a single xolu instance; in a nolu-coordinated deployment, nolu decides
which xolu instance molu talks to.
MCP (Model Context Protocol, modelcontextprotocol.io) is the open
protocol that defines how AI models communicate with external tools and
data sources. MCP standardises the tool call and resource access patterns
that Claude and other models use to interact with the world. molu
implements the MCP server role using the official Go SDK
(github.com/modelcontextprotocol/go-sdk), making xolu's operational
model available to any MCP-compatible agent.
The three projects form a stack:
AI agent ←→ MCP ←→ molu ←→ xolu ←→ nolu (optional)
understand store coordinate
and act
molu is the layer that understands what the data means and knows how to act on it. xolu stores it. nolu coordinates it across nodes.
Claude / AI agent
│ MCP protocol (stdio or SSE)
▼
molu
│ HTTP (xolu REST API)
▼
xolu
│
▼
SQLite + graph + timeseries + blobs + FSMs
molu is stateless. All persistent state lives in xolu. molu holds no database, no knowledge base, no vector index. Its operational knowledge is derived entirely from the live xolu instance it is connected to.
Traditional RAG: corpus → chunk → embed → rank → inject → generate. The corpus is static or slow-moving. The retrieval is read-only. The agent consumes knowledge.
molu is different on every axis:
-
No corpus. The xolu schema is a live executable specification, not a document collection. Entity types, REF relationships, FSM definitions, sequences, event subscriptions — these describe exactly what exists and exactly what can happen to it.
-
No chunking or ranking. The schema is complete and precise. molu reads it in full at startup and refreshes it on change. There is no relevance ranking problem because the schema is structured, not unstructured.
-
Read-write. molu executes writes, commits, FSM walks, sequence increments. "Prepare a new invoice for John Doe" causes real mutations with real consequences.
-
Live ETL. molu translates natural language intent into structured xolu operations in real time. The schema changing is immediately reflected in molu's behaviour.
-
Agentic. A single natural language request may require multi-step planning: entity lookup, REF resolution, FSM state assessment, commit construction, result verification. molu plans and executes that sequence autonomously.
The grounding that makes this reliable is structural: xolu's schema is formal and machine-readable. molu doesn't infer the operational model from documentation — it reads it directly from the running system.
molu/
├── cmd/molu/ — entry point, config, startup
├── pkg/xolu/ — xolu HTTP client (typed, generated from xolu API)
├── pkg/schema/ — live schema reader and semantic map builder
├── pkg/planner/ — natural language → operation plan
├── pkg/executor/ — operation plan → xolu API calls
├── pkg/mcp/ — MCP server (tools, resources, prompts)
└── pkg/config/ — configuration
- Connect to xolu instance (
OLU_URL,OLU_API_KEY) - Read all registered schemas from
GET /api/v1/schemas - Read FSM definitions from
GET /api/v2/fsm/def - Read sequences from
GET /api/v2/gen/seq - Read event subscriptions from
GET /api/v2/event - Build semantic map (entity types, field names, REF graph, FSM topology, generator names)
- Register MCP tools derived from the semantic map
- Begin serving MCP connections
molu subscribes to xolu's entity.updated and schema-change events
via /api/v2/event to receive push notifications when the schema
changes. On notification, it re-reads the affected schema and rebuilds
the relevant parts of the semantic map. MCP tool definitions are
updated without requiring a restart.
If xolu's event system is not yet available (pre-v2), molu falls back
to polling GET /api/v1/schemas on a configurable interval
(MOLU_SCHEMA_POLL_INTERVAL, default 30s).
The semantic map is molu's internal representation of the xolu instance it is connected to. It is built from the live schema and held in memory.
type SemanticMap struct {
// Entity types indexed by name and by likely natural language aliases
Entities map[string]*EntityDef
// REF graph: which entities reference which
RefGraph *RefGraph
// FSM definitions by entity type
Machines map[string][]*MachineDef
// Generator definitions
Generators map[string]*GeneratorDef
// Event subscriptions
Events map[string]*EventDef
// Tenant context
Tenant string
}
type EntityDef struct {
Name string
Schema map[string]interface{} // raw JSON Schema
Fields []*FieldDef
REFFields []*REFFieldDef // fields with format:ref
FSMs []*MachineDef // machines bound to this type
Sequences []*GeneratorDef // sequences used by this type
}The semantic map enables:
- Entity resolution: "customer" →
customerentity type - Field resolution: "name" →
namefield, "date" →invoice_date - REF resolution: "for customer John Doe" → lookup
customerwhere name = "John Doe", return{"type":"REF","entity":"customer","id":42} - FSM resolution: "prepare" → FSM initial state or
draftinput, "approve" →approvedtransition input - Generator resolution: "invoice number" →
invoice_numbersequence
molu exposes a small set of high-level tools rather than a thin mechanical mapping of every xolu endpoint. The tools are shaped for agent use — they accept intent, not API parameters.
find
Find entities matching a natural language description.
{
"name": "find",
"description": "Find entities in xolu matching a description",
"inputSchema": {
"query": "string — natural language description of what to find",
"entity_type": "string? — optional hint for entity type",
"limit": "integer? — max results, default 10"
}
}Example: find("customer named John Doe") →
resolves to GET /api/v1/customer?name=John+Doe or an OQL query.
get
Retrieve a specific entity by type and ID.
{
"name": "get",
"description": "Retrieve a specific entity",
"inputSchema": {
"entity_type": "string",
"id": "integer"
}
}create
Create a new entity, optionally with an FSM machine.
{
"name": "create",
"description": "Create a new entity in xolu",
"inputSchema": {
"entity_type": "string",
"data": "object — field values for the new entity",
"start_machine": "string? — FSM definition name to bind"
}
}update
Update an existing entity.
{
"name": "update",
"description": "Update an existing entity",
"inputSchema": {
"entity_type": "string",
"id": "integer",
"changes": "object — fields to update",
"version": "integer? — for optimistic concurrency"
}
}perform
The primary agentic tool. Accepts a natural language description of
a business operation and executes it. molu plans and executes the
full sequence of xolu calls required.
{
"name": "perform",
"description": "Perform a business operation described in natural language",
"inputSchema": {
"instruction": "string — natural language description of what to do",
"context": "object? — additional context (current entity, tenant, etc.)"
}
}Example: perform("prepare a new invoice for customer John Doe")
molu's planner:
- Identifies intent: create invoice
- Identifies subject: customer John Doe → calls
find("John Doe", "customer") - Determines initial state: invoice FSM has initial state
draft - Determines sequence:
invoice_numbersequence exists - Constructs commit payload: new invoice entity + FSM machine creation
- Executes:
POST /api/v1/commitwith entity data and machine binding - Returns: created invoice with ID, invoice number, and initial FSM state
walk
Advance an FSM machine by input name or natural language description
of the desired transition.
{
"name": "walk",
"description": "Advance an entity's state machine",
"inputSchema": {
"entity_type": "string",
"id": "integer",
"transition": "string — input name or natural language description",
"payload": "object? — transition payload"
}
}query
Execute an OQL or Sulpher query directly for cases where natural
language grounding is insufficient.
{
"name": "query",
"description": "Execute an OQL or Sulpher query against xolu",
"inputSchema": {
"language": "oql | sulpher",
"query": "string"
}
}describe
Return molu's current understanding of the xolu schema — useful for
the agent to orient itself before performing complex operations.
{
"name": "describe",
"description": "Describe the xolu schema: entity types, relationships, FSMs",
"inputSchema": {
"entity_type": "string? — describe a specific type, or all if omitted"
}
}molu exposes the semantic map as MCP resources, allowing the agent to read the schema directly:
molu://schema — all entity types
molu://schema/{entity_type} — specific entity type schema
molu://fsm/{definition_id} — FSM definition
molu://fsm/machine/{id} — machine state and history
molu://gen — all generators
The planner is the core of molu. It takes a natural language instruction
and the semantic map and produces an OperationPlan — a sequence of
xolu API calls that realises the intent.
type OperationPlan struct {
Steps []OperationStep
Atomic bool // if true, wrap in /commit
Explain string // human-readable plan summary
}
type OperationStep struct {
Kind StepKind // Lookup, Create, Update, Walk, Query, Generate
Entity string
ID int64
Data map[string]interface{}
FSMInput string
Payload map[string]interface{}
DependsOn []int // step indices this step depends on
}The planner uses the semantic map for grounding and Claude (via the Anthropic API) for natural language understanding. The planning call is a structured output request: given the instruction, the semantic map summary, and the available operation types, produce a JSON plan.
This is the component where molu is most agentic: the planner may make intermediate tool calls (e.g. looking up John Doe's customer ID before constructing the invoice creation step) before producing the final plan.
Simple single-entity operations (create, update, find) are planned without an LLM call using pattern matching against the semantic map. This keeps latency low for common cases.
Complex multi-step operations (involving REF resolution, FSM walks, atomic commits, sequence assignment) use a structured LLM call with the semantic map as context.
The planner never executes speculatively. It produces a plan, presents it to the executor, and the executor performs the actual xolu API calls. Plan and execution are cleanly separated.
The executor takes an OperationPlan and executes it against xolu.
It handles:
- Step ordering based on
DependsOnrelationships - Result propagation (John Doe's ID from the lookup step feeds into the REF field of the create step)
- Atomic commit construction when
plan.Atomicis true - Error handling and partial failure reporting
- Response normalisation for MCP return values
type Executor struct {
client *xolu.Client
smap *SemanticMap
logger zerolog.Logger
}
func (e *Executor) Execute(ctx context.Context, plan *OperationPlan) (*ExecutionResult, error)# Required
MOLU_XOLU_URL=http://localhost:7070 # xolu instance URL
MOLU_XOLU_API_KEY= # xolu API key (if auth enabled)
MOLU_XOLU_TENANT= # default tenant (empty = tenant 0)
# MCP transport
MOLU_TRANSPORT=stdio # stdio | sse
MOLU_SSE_ADDR=:8090 # for sse transport
# Planner
MOLU_ANTHROPIC_API_KEY= # for LLM-backed planning
MOLU_PLANNER_MODEL=claude-sonnet-4-6 # model for planning calls
MOLU_PLANNER_SIMPLE_THRESHOLD=1 # steps below this use pattern matching
# Schema
MOLU_SCHEMA_POLL_INTERVAL=30s # fallback polling if events unavailable
MOLU_SCHEMA_CACHE_TTL=5m # how long to cache schema reads
# Observability
MOLU_LOG_LEVEL=info
MOLU_LOG_FORMAT=console # console | jsonmodule github.com/ha1tch/molu
go 1.22
require (
github.com/modelcontextprotocol/go-sdk v1.6.1
github.com/rs/zerolog v1.x
github.com/ha1tch/xolu v0.9.8 // HTTP client only
)
molu imports xolu only for the HTTP client types — it does not embed xolu's storage layer. The dependency is on the API contract, not the implementation.
- molu does not generate or run code
- molu does not have its own storage
- molu does not implement authentication (delegates to xolu)
- molu does not support multiple simultaneous xolu instances (one molu ↔ one xolu)
- molu does not cache entity data (always reads through to xolu)
- molu does not implement the
/api/v2FSM or event endpoints until xolu implements them
-
Planner grounding quality. How well does the semantic map ground natural language requests against arbitrary xolu schemas? This needs empirical testing with real schemas before the planner design can be finalised.
-
Ambiguity handling. "Prepare a new invoice for John Doe" is unambiguous if exactly one customer named John Doe exists. If zero or multiple exist, molu must ask for clarification. The tool response format for disambiguation requests needs design.
-
Tenant awareness. Multi-tenant xolu instances require molu to know which tenant to operate in. Should tenant be a per-connection config, a per-request parameter, or derived from the agent's identity?
-
Write safety. Should molu require explicit confirmation for destructive operations (delete, FSM terminal state)? Or trust the agent to confirm before calling? The answer affects the tool design significantly.
-
Schema coverage. xolu
/api/v2endpoints (FSM, event, gen, meta) are not implemented yet. molu's design accounts for them but the initial implementation targets/api/v1only.
Draft 01. Pre-implementation. Subject to revision as xolu v1.0 approaches and the /api/v2 subsystems are built.