The MCP tools¶
noodlelab mcp serves these tools over the Model Context Protocol (stdio). Add
it to an agent with one of:
claude mcp add noodlelab -- uvx noodlelab mcp # Claude Code
codex mcp add noodlelab -- uvx noodlelab mcp # Codex CLI
noodlelab init-agent # writes .mcp.json, and more
It works on the graphs in its workspace folder (the current folder, or
--workspace). Started from the editor’s Agent panel, it saves through the
editor instead, which reloads each graph as the agent saves it.
What an AI agent can do with a noodlelab workspace: the MCP server’s tools.
Each tool is a plain function of JSON-ready arguments returning JSON-ready
data, so they are easy to test and could serve another protocol too. A
Workspace is a folder of graphs:
standalone (the default), it reads and writes
*.graph.jsonfiles in the folder;connected to a running editor (
NOODLELAB_URL,NOODLELAB_WORKSPACE_IDand, with logins,NOODLELAB_TOKENset, as the editor’s agent terminal does), graphs are saved through the server’s API. The editor showing a graph then reloads it as soon as the agent saves.
Runs happen in this process in both cases, with the server’s settings (so checkpoints are shared), and add to the graph’s tracked-values and requirements history like any other run.
- class noodlelab.agent.tools.Workspace(root, *, remote=None, home=None)[source]
A folder of graphs, and the tools that work on it.
- Parameters:
root (str | Path)
remote (Remote | None)
home (str | Path | None)
- property executor: Any
- property registry: Any
- graph_file(path)[source]
- Parameters:
path (str)
- Return type:
Path
- read_doc(path)[source]
- Parameters:
path (str)
- Return type:
GraphDocument | None
- write_doc(path, graph, metadata)[source]
Save a graph with no layout (the editor lays it out afresh); returns its new revision.
- Parameters:
path (str)
graph (ExecGraph)
metadata (dict[str, Any])
- Return type:
int
- issues(graph)[source]
- Parameters:
graph (ExecGraph)
- Return type:
list[dict[str, Any]]
- guide()[source]
How to use noodlelab well: the rules, the Python API, the graph format and the workflow. Read it first.
- Return type:
str
- list_nodes(query='', category='', limit=80)[source]
Installed node types, one line each (id, title, what it does). Filter with words in
query(all must match the id, title, category or description) or acategory.- Parameters:
query (str)
category (str)
limit (int)
- Return type:
dict[str, Any]
- describe_node(type)[source]
One node type in full: its documentation, and each input (type, default, options, description) and output.
- Parameters:
type (str)
- Return type:
dict[str, Any]
- list_examples()[source]
The bundled example graphs: id, title, what they show, and whether the installed packs can run them.
- Return type:
list[dict[str, Any]]
- get_example(id)[source]
An example graph (its
graphin the formatsave_graphtakes).- Parameters:
id (str)
- Return type:
dict[str, Any]
- copy_example(id, path='')[source]
Copy an example into the workspace (as
path, defaultexamples/<id>) with its data files, to run or adapt it.- Parameters:
id (str)
path (str)
- Return type:
dict[str, Any]
- list_graphs()[source]
The graphs in the workspace, with their titles.
- Return type:
list[dict[str, Any]]
- get_graph(path)[source]
A graph of the workspace: its
graph(nodes and report), metadata and revision.- Parameters:
path (str)
- Return type:
dict[str, Any]
- save_graph(path, graph, title='', description='')[source]
Write a whole graph (
{"nodes": [...], "report": [...]}). Input values may be given bare ("b": 2) or as{"value": 2}; links as{"link": {"node": "1", "output": "result"}}. It is saved even with problems (so it can be fixed in steps); they are returned.- Parameters:
path (str)
graph (dict[str, Any])
title (str)
description (str)
- Return type:
dict[str, Any]
- edit_graph(path, operations)[source]
Change a graph step by step, creating it if new. Operations, applied in order (
sectionis"nodes", the default, or"report"):{"op": "add", "type": "core.number", "id": "7", "title": "...", "inputs": {"value": 3}}(idis optional){"op": "set", "node": "7", "inputs": {"b": {"link": {"node": "3", "output": "result"}}}}{"op": "remove", "node": "7"}{"op": "title", "node": "7", "title": "Drag force"}{"op": "track", "node": "7", "output": "result", "label": "drag"}: follow the output in the editor’s Tracked tab{"op": "constant", "name": "g_local", "value": 9.8123, "unit": "m/s^2", "uncertainty": 0.0005, "source": "survey 2024", "title": "local g"}: a named constant of the graph’s own, for Constant nodes and Values lines ("value": nullremoves it;"value": "998.2 kg/m^3"works too)
- Parameters:
path (str)
operations (list[dict[str, Any]])
- Return type:
dict[str, Any]
- check_graph(path)[source]
Problems with a saved graph before running it: unknown types, mismatched types or units, missing inputs, cycles.
- Parameters:
path (str)
- Return type:
dict[str, Any]
- run_graph(path, targets=None)[source]
Run a saved graph (only what
targets, node ids, need). Returns each node’s outputs in short, the checks and requirement verdicts with their margins, errors, the files written (a report’s PDF) and the provenance record.- Parameters:
path (str)
targets (list[str] | None)
- Return type:
dict[str, Any]
- get_output(path, node, output='', key=None)[source]
The full value of a node’s outputs (all of them, or
output), as JSON: numbers; quantities as {value, unit}; uncertain values as {value, u, unit}; tables as {columns, units, rows}; dicts (an uncertainty budget, a fit’s summary) and named results as objects; arrays as lists; figures as the path of a PNG. Long tables and arrays give their first 500 rows, with a note.keydigs in: [“Input”] for one entry of a dict, a column’s name for a table’s column. Read from the graph’s latest run when it has the output in full; otherwise the node (and what it needs) is run for it.- Parameters:
path (str)
node (str)
output (str)
key (list[str] | None)
- Return type:
dict[str, Any]
- requirements(path)[source]
Each requirement of a graph as its latest run left it (passed, failed, inconclusive or not verified, with the margin and where it came from), and how many runs are recorded.
- Parameters:
path (str)
- Return type:
dict[str, Any]
- verify(target, strict=False)[source]
Run and audit a Python script (that uses noodlelab.verify.record), a graph (a path in the workspace) or records written earlier, as
noodlelab verify --jsondoes:passedis true when every check passed and every requirement was verified. Verifying a script runs it, aspython script.pywould, so only targets inside the workspace are accepted.- Parameters:
target (str)
strict (bool)
- Return type:
dict[str, Any]