Skip to main content
Glama
relative-interpreter-mcp

relative-interpreter-mcp

by CalWtr

Relative — MCP Interpreter

An MCP server that lets an LLM (Claude Code, Claude Desktop, any MCP host) act as a third interpreter for the Relative service — alongside relative-interpreter-list and relative-interpreter-graph, which are browser UIs for a human. This one exposes a model as tools instead of buttons.

See DESIGN.md for why it is shaped the way it is.

Run

npm install
RELATIVE_SERVICE_URL=http://localhost:4000/api npm start

Needs a running relative service (see that repo's README.md). RELATIVE_SERVICE_URL defaults to http://localhost:4000/api.

Register it as a local stdio server. For Claude Code, in .mcp.json:

{
  "mcpServers": {
    "relative": {
      "command": "npx",
      "args": ["tsx", "/path/to/relative-interpreter-mcp/src/main.ts"],
      "env": { "RELATIVE_SERVICE_URL": "http://localhost:4000/api" }
    }
  }
}

Related MCP server: Next MCP Server

What it gives the model

Reads return a compact outline, not JSON — names as identifiers, links as arrows, submodels summarised to a line:

Model "Switch Circuit" · 4 nodes, 3 links, 1 view · rev 0
Scope: (root)

Nodes:
  battery  const boolean = true    out out:boolean
  switch   var boolean = false     in in:boolean  out out:boolean
  circuit  fn python runtimes/python/examples/circuit.py [onUpdate]   in powered:boolean,closed:boolean  out lit:boolean
  bulb     var boolean = false     in in:boolean  out out:boolean

Links:
  battery.out -> circuit.powered  [power flow]  battery powers circuit
  switch.out -> circuit.closed    [power flow]  switch closes circuit
  circuit.lit -> bulb.in          [power flow]  circuit lights bulb

Views:
  power flow  (3 links)

One edit_model tool takes many steps, applied as a single undoable operation via the service's /batch endpoint, with later steps able to reference what earlier ones create:

{ "steps": [
  { "action": "addValueNode", "input": { "name": "Switch", "mutability": "variable",
                                         "initialValue": { "type": "boolean", "value": false } } },
  { "action": "addValueNode", "input": { "name": "Bulb", "mutability": "variable",
                                         "initialValue": { "type": "boolean", "value": false } } },
  { "action": "addView", "input": { "name": "Power" } },
  { "action": "addLinkWithEndpoints", "input": { "name": "sw-to-bulb",
      "endpointA": "Switch.out", "endpointB": "Bulb.in",
      "direction": "forward", "views": ["Power"] } }
] }

References are names, and bad ones are refused. The service's state layer is total, so a mutation aimed at something that does not exist silently succeeds; every reference is resolved and checked here first:

Step 1 (updateNode): No node "NoSuchNode" in this scope.
Available: Switch#4e64975c, Bulb#159d3b8a

Names are not unique in Relative, so an ambiguous one is an error offering name#uuidprefix handles — the same handles reads print.

Staleness is reported, not assumed. The server consumes the service's SSE stream, pushes resources/updated to subscribed hosts, and prefixes any read whose revision moved since the caller last saw it:

[changed outside this conversation since you last looked: rev 3 -> 4,
 views 0->1. The view below is current.]

Tools

Group

Tools

Navigation

list_models, select_model, create_model, import_model, delete_model, get_scope, enter_submodel, exit_submodel

Read

get_model, get_element, get_validation, get_script_source

Edit

edit_model, link_external_submodel

Execution & history

run_node, undo, redo, list_snapshots, save_snapshot, restore_snapshot

Resources: relative://models, relative://models/{id} (subscribable).

Available Tools

20 tools
create_modelCreate modelA

Create an empty model and select it.

Inputs: name (required), description.

delete_modelDelete modelA

Permanently delete a model and its snapshots.

Inputs: modelId.

edit_modelEdit modelA

Apply one or more changes as a single undoable operation. Put every change you already know you want in one call — steps apply in order and a later step can reference something an earlier one created. References are names ("Switch") or port references ("Switch.out"); anything that does not resolve is rejected before it is sent, so an edit never silently does nothing.

Inputs: steps (required), path, modelId.

enter_submodelEnter submodelA

Scope into a submodel node, so reads and edits apply inside it.

Inputs: node (required).

exit_submodelExit submodelA

Leave the current submodel. Give a depth to jump straight to that level (0 = root).

Inputs: depth.

get_elementGet elementB

One node, link, or view in full, including everything the outline summarises away.

Inputs: ref (required), kind (required).

get_modelGet modelA

The current scope as a compact outline: nodes with their kind and value, links as arrows between named ports, views, and validation findings. Submodels are summarised, not expanded — use enter_submodel or get_element to look inside one.

Inputs: modelId.

get_scopeGet scopeB

Which model is selected, how deep the submodel scope is, and whether it is editable.

Inputs: no named parameters.

get_script_sourceGet script sourceB

A function node's script source, read-only.

Inputs: scriptPath (required).

get_validationGet validationB

Validation findings for the whole selected model.

Inputs: no named parameters.

import_modelImport modelA

Create a model from exported Relative JSON and select it.

Inputs: json (required).

list_modelsList modelsD

Every model the service holds.

Inputs: no named parameters.

list_snapshotsList snapshotsC

Named on-disk checkpoints for the selected model.

Inputs: no named parameters.

redoRedoB

redo the last operation on the selected model.

Inputs: no named parameters.

restore_snapshotRestore snapshotC

Restore a snapshot. This is itself undoable.

Inputs: snapshotId (required).

run_nodeRun nodeC

Execute a function node's pipeline and settle the reactive cascade.

Inputs: node (required), inputs.

save_snapshotSave snapshotB

Save a named, restorable checkpoint.

Inputs: name (required).

select_modelSelect modelA

Open a model for this session and reset the scope to its root. Returns its outline.

Inputs: modelId (required).

undoUndoB

undo the last operation on the selected model.

Inputs: no named parameters.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

Loading tool schema changelog…

    TDQS

    B3.4/5.0

    Scored across 20 tools

    Disambiguation5/5

    Each tool targets a distinct resource and operation: scope management (get_scope, enter_submodel, exit_submodel), model inspection at different granularities (get_model, get_element, get_script_source), model lifecycle (create, select, import, delete, list), editing and execution (edit_model, run_node), validation, snapshots, and undo/redo. No overlapping purposes.

    Naming Consistency5/5

    All tools follow a consistent verb_noun snake_case pattern, with plural nouns for list operations (list_models, list_snapshots) and clear imperative verbs. The only exceptions are undo and redo, which are universally accepted single verbs.

    Tool Count4/5

    With 20 tools, the set is on the heavier side but remains justified by the complexity of a model interpreter. Each tool has a clear role, and no redundant or trivial tools are present.

    Completeness4/5

    The core workflow is well-covered: model lifecycle, editing, navigation, validation, execution, and snapshots. Minor gaps exist—such as missing export_model and delete_snapshot—but agents can work around these with existing operations.

    Related MCP Connectors

    Related MCP Servers