mltree-mcp
This MCP server lets a coding assistant build, run, track, inspect, and share ML/QSAR/GNN workflows as a node DAG with experiment-tree runs.
Initialize a project and register/update pipeline steps with scripts, inputs, outputs, params, and descriptions.
Connect steps into a DAG and retrieve the full pipeline with topological order.
Log runs with params, metrics, artifacts, notes, tags, parent runs, metric history, and data versions.
Check which step inputs changed or are missing, and compare runs by params, metrics, data versions, and script diffs.
Statically scan existing projects to build maps and import existing results as runs.
Execute steps and grid sweeps, stream/follow logs, and cancel runs or sweeps.
Start/finish manual sweeps for trials run outside mltree.
Add notes/tags to steps and runs, and find the best succeeded run by metric.
Summarize GNN model architectures and optionally inspect dataset/checkpoint stats.
Open the browser map viewer and export a self-contained offline HTML map.
Imports PyTorch Lightning lightning_logs/version_* runs, capturing hparams and the last values from each run's metrics.csv so prior training runs appear in the experiment tree.
Imports existing MLflow experiment runs from a project's mlruns/ directory into the experiment tree, capturing each run's params, latest metric values, and status so prior experiments appear as runs alongside new ones.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mltree-mcpscan this project and show me the workflow map"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mltree-mcp
Your ML workflow as a node map, your experiments as a tree — filled in by your coding assistant as it works.
mltree-mcp is an MCP server for Codex, Claude Code and any other MCP client.
While the assistant writes and runs your ML / QSAR / GNN code, it calls mltree tools to:
register each pipeline step (load → clean → featurize / graph-build → split → HPO → train → evaluate) as a node, with its own
.pyscript, inputs, outputs and default params;wire the steps into a DAG;
log every execution as a run with params, metrics and artifacts, branching from a parent run (HPO trials, GNN variants…), so experiments form a mind-map tree instead of being scattered down a notebook.
Everything lives as plain files in your repo under .mltree/, and mltree-mcp view opens a KNIME-style map of it in your browser.



Status: 0.8.0. MCP core, map viewer,
scan_projectfor existing projects, shareable HTML export, running steps and grid sweeps from the map (opt-in), data versions, compare with param changes / curves / code diffs, notes and tags, GNN views, and now PyPI packaging, CI and a multi-project viewer. See the changelog.
Install
Requires Python 3.11+. Works with the MCP Python SDK 1.x (FastMCP) and 2.x (MCPServer).
pip install mltree-mcp # or: uv tool install mltree-mcp
mltree-mcp --version
# or run it without installing
uvx mltree-mcp --versionThe wheel ships the prebuilt viewer, so Node is not needed. From source:
git clone https://github.com/yboulaamane/mltree-mcp
cd mltree-mcp
pip install -e . # or: uv pip install -e ".[dev]"
# straight from the git repo
uvx --from git+https://github.com/yboulaamane/mltree-mcp mltree-mcp --versionThe mltree-mcp command starts a stdio MCP server (that is what Claude Code and Codex expect). Clients launch it for you; you don't run it by hand.
Which project does it use?
The project root is resolved on every call, in this order:
--project <dir>flag /MLTREE_PROJECTenvironment variableCLAUDE_PROJECT_DIR(Claude Code sets this for stdio servers automatically)the server's current working directory
Related MCP server: mlops-mcp-server
Add it to Claude Code
# once on PyPI
claude mcp add mltree -- uvx mltree-mcp
# before that, from your clone
claude mcp add mltree -- uvx --from /path/to/mltree-mcp mltree-mcp
# make it available in every project, or share it with the repo via .mcp.json
claude mcp add --scope user mltree -- uvx mltree-mcp
claude mcp add --scope project mltree -- uvx mltree-mcp
claude mcp list # should show: mltree ... ✔ ConnectedInside Claude Code, /mcp shows the server and its tools. Claude Code passes CLAUDE_PROJECT_DIR, so the store lands in the project you opened.
Add it to Codex
Either use the CLI:
codex mcp add mltree -- uvx mltree-mcp
codex mcp listor edit ~/.codex/config.toml (or a project-scoped .codex/config.toml in a trusted project):
[mcp_servers.mltree]
command = "uvx"
args = ["mltree-mcp"]
# before PyPI: args = ["--from", "/path/to/mltree-mcp", "mltree-mcp"]
startup_timeout_sec = 20 # first uvx run downloads dependencies
# Optional: pin the project instead of using the directory Codex starts in
# [mcp_servers.mltree.env]
# MLTREE_PROJECT = "/home/you/projects/qsar-gnn"In the Codex TUI, /mcp lists active servers. Codex also reads the server's built-in instructions, which tell it when to call each tool.
Use it on an existing project over SSH with Codex
You already have a project on a GPU server: numbered scripts, a utils.py, a notebook or two, some metrics.json
files, maybe mlruns/ or an Optuna study. scan_project builds the map from that code without running any of it.
It parses scripts with Python's ast and reads notebooks as JSON.
1. Install on the server (once):
ssh you@server
pip install --user "git+https://github.com/yboulaamane/mltree-mcp" # or: uv tool install git+https://github.com/yboulaamane/mltree-mcp
mltree-mcp --version2. Register it with Codex on the server, pinned to the project:
codex mcp add mltree -- mltree-mcp --project /path/to/your/project3. Ask Codex to scan it. Start codex in the project and say:
Scan this project with mltree and show me the map. Fix anything the scan got wrong.
Codex calls scan_project (the server instructions tell it to do this first on an existing project). It reviews
the summary and corrects edges or kinds with connect_steps / add_step. You can also scan from the shell:
mltree-mcp scan --project /path/to/your/project --dry-run # preview, writes nothing
mltree-mcp scan --project /path/to/your/project # write .mltree/4. Look at it from your laptop. On the server:
mltree-mcp view --project /path/to/your/project # serves on localhost:8765 on the serverOn your laptop:
ssh -L 8765:localhost:8765 you@server
# then open http://localhost:8765What the scan detects
Signal | How |
Data reads / writes |
|
Params | argparse |
Description | The module docstring, or the notebook's first markdown heading. |
Kind |
|
Utilities | A helper module such as |
Edges | 1) one step's output path matches another's input (exact, glob, or folder); 2) imports of other step modules; 3) notebook section order; 4) file numbering ( |
Notebooks | One step per notebook, or one step per markdown-headed section with |
Existing results → runs tagged |
|
Re-scanning is safe. Steps the scanner owns are refreshed, new scripts become new steps, and nothing is deleted.
A step you or the assistant edited with add_step keeps its description, kind and param values; the scan only adds
new inputs, outputs and param keys. Results are imported once (they are keyed by source). The summary lists new,
updated, merged and unchanged steps, edges, inputs no step produces, outputs no step consumes, skipped files, and
imported runs. Default excludes: virtualenvs, .git, tests/, test_*.py, __pycache__, .mltree,
node_modules, build/, dist/.
The map viewer
mltree-mcp view # project = $MLTREE_PROJECT / cwd
mltree-mcp view --project ~/projects/qsar-gnn --port 8765
# then open http://localhost:8765Or ask the assistant: it calls open_map, which starts the viewer in the background if needed and returns the URL.
Workflow map. Your steps form a DAG, coloured by each step's latest run (grey not run, blue running, green done, red failed). Nodes are laid out automatically (dagre). If you drag them, their positions are saved to the store (
pos_x/pos_y), and Auto layout resets them.Step panel. Click a node to see its inputs, outputs and params, and a read-only editor (Monaco, the VS Code editor) showing the script. A dropdown switches between the current file and the snapshot saved with each run, marked "same as current" or "changed". Below it is the step's runs table.
Experiment tree. All runs form a mind-map built from
parent_run_id. Pick a metric and "lower/higher is better" to highlight the best run (★). You can filter by step.Compare. Tick 2 or more runs anywhere to get a params/metrics table (rows that differ are marked) and a grouped Plotly bar chart.
Live. The page updates by itself as the assistant logs runs, using Server-Sent Events with polling as a fallback. Dark and light themes follow your OS and can be toggled.
The built frontend ships inside the Python package (src/mltree_mcp/static/), so pip install needs no Node. Monaco is bundled too, with no CDN, so it works offline and on air-gapped clusters.

Data versions
Each step's inputs and outputs that are files or folders inside the project are fingerprinted. The fingerprint is
the SHA-256 of the content (a folder hashes its sorted relative path + file hash list) and the version shown is
its first 12 hex characters. Hashes are cached in mltree.db by path, size and mtime, so unchanged files are not
re-read. Files over 4 GiB and folders over 5000 files get a quick digest (size + mtime only, marked ~) instead.
Runs record the versions they used:
log_runrecords inputs and outputs, a run started from the map or byrun_steprecords inputs at start and outputs when it succeeds. Runs imported byscan_projectrecord none (it never runs or reads your data beyond the scan).The step panel's Data versions table compares the files now with the latest run. The node shows ⚠ data changed when an input changed since that run and input missing when one is gone, so you know which steps to re-run.
Compare has a Data versions row group, and the
data_status(step?)tool gives the assistant the same view.Only paths are hashed, never executed or parsed. Paths outside the project are shown by name only in the export.

Compare: param changes, curves and code diff
Tick 2 or more runs (or use the Runs table's Compare):
Param changes: for each run, the params that differ from the first one (
alpha: 1 → 0.5).Params / metrics / data versions table, rows that differ marked, and a grouped bar chart of the ticked metrics.
Curves: step-wise metrics (
MLTREE_METRIClines, orlog_run(history=[{"epoch": 1, "loss": 0.9}, ...])) overlaid per run, with a metric picker and log-y.Code diff of two runs' script snapshots, unified or side by side, hunks or the whole file. It is computed in the browser, so it also works in the HTML export.


Notes and tags
Click + Add note / Edit in a step's panel or a run's panel to write free-text notes (Ctrl+Enter saves, Esc
cancels). Runs also get tags: type one or more (comma-separated) in the run panel's tag box, × removes one. Notes
show as ✎ on map nodes, tree cards and the runs table; the experiment tree's Tag filter dims every run without
that tag. The assistant uses add_note and tag_run, and get_pipeline returns each step's notes and the tags in
use. Notes and tags are in the HTML export (read-only there).
Editing notes doesn't need --allow-run, but the same request checks apply as for runs: an X-MLTree: 1 header,
a loopback Host and, if present, a loopback Origin.

GNN views
For graph-learning steps the step panel gets a Graph model & data section, and the node a chip like
GCNConv ×3 · hidden 64 · global_mean_pool or 20 graphs.
Architecture summary (static). mltree parses the step's script and the project modules it imports (it never imports or runs them). For
torch.nn.Modulesubclasses that use PyTorch Geometric or DGL layers it lists the layers in__init__(type, library, in → out channels, heads, repeats fromfor _ in range(num_layers)/ModuleListcomprehensions), the readout / pooling and the order the layers are called inforward. Prebuilt models (GCN(in, hidden, num_layers),GAT,GIN, …) and literal / default / module-constant dimensions are resolved; anything else is shown as the source text.Dataset stats (opt-in introspection). The section lists dataset classes the script uses (
TUDataset,MoleculeNet,DGLDataset, …) and.pt/.bingraph files among the step's outputs. Inspect dataset… loads the file in a separate Python process (--python/$MLTREE_PYTHONwith torch installed) without importing your code, and caches: number of graphs, nodes / edges min/mean/max, node and edge feature sizes, self loops, isolated nodes, average degree, labels (classes and counts, or the regression range) and train/val/test masks. Astate_dictcheckpoint gives tensor shapes and the parameter count. Stats are marked stale when the file changes. This loads data withtorch.load(which can run code embedded in a pickle ifweights_only=Truefails), so it needsview --allow-run,MLTREE_ALLOW_RUN(MCPgnn_summary(introspect=true)) or the explicit CLI:
mltree-mcp gnn --project . --step featurize # static summary + cached stats (JSON)
mltree-mcp gnn --project . --step featurize --introspect --python ~/envs/pyg/bin/pythonBroken or unusual scripts never break the map; the section just shows less. The export keeps the summaries and cached stats (not the source fragments when scripts are left out) and never offers introspection.


On a remote server or HPC cluster
The viewer binds to 127.0.0.1 by default. Run it on the server and tunnel the port from your laptop:
# on the server (or let the assistant call open_map there)
mltree-mcp view --project ~/projects/qsar-gnn
# on your laptop
ssh -L 8765:localhost:8765 you@server
# open http://localhost:8765Use --host 0.0.0.0 only on a network you trust. The viewer has no authentication; without --allow-run its only
writes are node positions and notes/tags, and notes/tags are refused unless the request comes through a loopback
Host (an SSH tunnel). --allow-run refuses any bind other than 127.0.0.1, so run steps through the SSH tunnel.
Several projects in one viewer
One viewer can serve several projects, with a switcher in the header. Each project gets its own URL prefix
(/p/<slug>/), API, live stream and run manager, so tabs on different projects work side by side.
mltree-mcp view --projects ~/projects/qsar-egfr ~/projects/tox21-gnn
# or register them once (stored in ~/.mltree/projects.json, or $MLTREE_HOME/projects.json)
mltree-mcp projects add ~/projects/qsar-egfr --name "QSAR EGFR"
mltree-mcp projects add ~/projects/tox21-gnn
mltree-mcp projects list
mltree-mcp projects remove tox21-gnn # by folder or by name
mltree-mcp view --projects # serves everything in the registryhttp://localhost:8765/ redirects to the first project, GET /api/projects lists them all (name, steps, runs), and
every route in the HTTP API is available under /p/<slug>/. --allow-run and the edit guards apply
per project exactly as in single-project mode. When the assistant calls open_map and a multi-project viewer is
already running on the port, it links to that project's page (or warns if the project isn't in the viewer).
The registry file is plain JSON:
{"projects": [{"path": "/home/you/projects/qsar-egfr", "name": "QSAR EGFR"}, {"path": "/home/you/projects/tox21-gnn"}]}
Run steps from the map
Start the viewer with --allow-run and each node gets a ▶ button, and the step panel gets ▶ Run… and Grid sweep…:
mltree-mcp view --project ~/projects/qsar-gnn --allow-run # Python: see "Which interpreter" below
mltree-mcp view --project ~/projects/qsar-gnn --allow-run --python ~/miniconda3/envs/gnn/bin/python
Run dialog. The params are prefilled from the step's last run, or from its scanned / declared params. You can edit them, add extra CLI arguments and see the exact command before you launch. A checkbox confirms that you know it executes the script on this machine (remembered for the browser tab).
Live log. stdout and stderr stream into a panel at the bottom, over Server-Sent Events, with stderr in red. Cancel sends SIGTERM, then SIGKILL after 5 s. Closing the page doesn't stop the run, and reopening it re-attaches.
Automatic record. Every run is logged by itself: params, the script snapshot (SHA-256 and git commit), the exact command, exit code, duration, the full log (
.mltree/runs/<id>/log.txt) and metrics. A failed exit code marks the run failed, and its last stderr lines go into the notes. A run branches in the experiment tree from the newest succeeded run of an upstream step, soevaluatehangs under thetrainrun that made its model.

How params reach your script. mltree reads the script (it doesn't run it) to choose a style:
Script uses | Params passed as |
|
|
| positional values, in that order |
|
|
none of these | environment only |
Every run also gets the following environment variables, so params the CLI doesn't declare still arrive and the dialog warns about them:
Variable | Value |
| all params as JSON |
| one param, with the name upper-cased |
| the run, the step, the project root |
|
|
Runs use the project root as the working directory, with python -u (unbuffered output).
Which interpreter. --python, else $MLTREE_PYTHON, else the project's .venv/ or venv/, else the active
$VIRTUAL_ENV / $CONDA_PREFIX, else python3 on PATH.
Reporting metrics. Print lines like these. Nested JSON is flattened to val.rmse.
print(f"MLTREE_METRIC epoch={epoch} train_loss={loss:.4f} val_rmse={rmse:.4f}") # key=value pairs
print("MLTREE_METRIC " + json.dumps({"val": {"rmse": rmse, "r2": r2}})) # or a JSON objectAlternatively, write a JSON dict to $MLTREE_METRICS_FILE (or to a metrics*.json file the step declares as an output).
The last value of each metric becomes the run's metric; a file overrides printed values. Every MLTREE_METRIC line is
also kept as one point of a step-wise history (.mltree/runs/<id>/metrics_history.jsonl, GET /api/runs/{id}/history),
which will feed the loss-curve overlays. Lines without the prefix are just log, so the script still works without mltree.
Sweeps
Grid sweep… takes comma-separated values per param (0.05, 0.2, 0.5), a metric to rank by, and lower or higher
is better. It shows how many runs the grid makes (64 at most by default) and then runs them one after another as
children of a sweep run. The log panel shows the progress, a child table with the best one starred, and each
child's log. Cancel stops the current child and skips the rest.

In the experiment tree a sweep is one card: its label, the number of runs, ✓/✗ counts and the best value. The children fan out below it with the best child highlighted (★ sweep best). Sweeps with more than 8 children start folded to the best one. ▸ unfold shows them all.

Sweeps also come from:
scan_project: an Optuna study becomes a sweep with its trials as children, ranked by the study's direction. A scikit-learnGridSearchCV/RandomizedSearchCVcv_results_CSV becomes a sweep over itsparam_*columns, ranked bymean_test_score.The assistant:
run_sweepruns a grid for you. For trials it runs itself (Optuna, a manual loop), it callsstart_sweep, thenlog_run(..., sweep_id=...)per trial, thenfinish_sweep.
Safety model
Running code from a browser page is the one dangerous thing the viewer can do, so it takes several locks:
Off by default. Without
--allow-runevery run/sweep/cancelPOSTreturns 403 and the buttons are greyed out. The shareable HTML export never has them.Loopback only. With
--allow-runthe viewer won't bind anything but127.0.0.1. Use an SSH tunnel for remote machines.No cross-site requests. Each
POSTneeds anX-MLTree: 1header, which a plain form or a cross-origin page can't send without a CORS preflight that mltree never approves. It also needs a loopbackHost(this defeats DNS rebinding) and, if anOriginheader is present, a loopbackOrigin.Only the project's own scripts. A step's
.pyscript_pathmust resolve inside the project. Nothing is run through a shell, and params become separate argv entries.An explicit confirm in the dialog for each tab session.
scan_project still never executes anything.
The MCP tools run_step / run_sweep are allowed by default, because the assistant can already run commands in your
shell. Set MLTREE_ALLOW_RUN=0 in the server's environment to turn them off, for example on a shared machine.
HTTP API
Route | Returns |
| project, root, |
| nodes (params, script, position, latest run status), edges, order |
| body |
| one node |
| current script, or the snapshot stored with a run |
| runs of the step that carry a script snapshot |
| runs, newest first |
| one run |
| run forest (runs, edges, roots) and the best run |
| runs, param/metric keys and which ones differ |
| numeric metric names |
| the shareable single-file HTML (as a download) |
|
|
| command preview, param-passing style, form defaults, warnings |
|
|
|
|
| cancel a run or a whole sweep |
| runs and sweeps in progress in this viewer |
| log lines |
|
|
| step-wise metrics ( |
| data versions of every step (or one): each input/output now vs the latest run, |
|
|
|
|
| static model summary, dataset candidates, cached stats |
| load the step's graph file(s) in a subprocess and cache stats (needs |
With view --projects, every route above lives under /p/<slug>/ and the root has GET /api/projects (slug, name,
root, url, steps, runs) and GET /api/health (multi: true, the project roots).
The POST and PUT routes need the X-MLTree: 1 header (see Safety model).
Share the map
Export ▾ in the viewer header gives you:
Shareable HTML: one self-contained
<project>-mltree.htmlfile. It opens offline in any browser by double-click, with no server, no install and no network requests. It is read-only and includes the workflow map, the step panel with each script (current file and the snapshot stored with every run), the experiment tree and the compare view. It inlines a lighter build of the viewer: a small highlighted code view instead of Monaco and SVG bar charts instead of Plotly. The bundled demo exports to about 530 KB: ~500 KB of app and the rest data, with scripts deduplicated by SHA-256.docs/example-export.htmlis a sample.Shareable HTML without scripts: the same file with the code left out.
Map as PNG / SVG: an image of the current map view (pan and zoom first), for slides and papers.
From the shell or through the assistant:
mltree-mcp export --project /path/to/project # -> ./<project>-mltree.html
mltree-mcp export --project /path/to/project -o share/map.html --no-scriptsexport_map(path=None, include_scripts=True) # MCP tool; returns {"path", "bytes", "size", ...}The MCP tool writes to <project root>/<project>-mltree.html by default. On a remote server, copy the file to
your machine with scp you@server:/path/to/project/<project>-mltree.html .
Ways to send it
Email or Slack. Attach the
.htmlfile. The recipient downloads it and opens it in a browser. (Previews inside Slack or a mail client won't run it; it has to be opened in a browser.)GitHub Pages. Commit it as
docs/index.html(or any.htmlin a Pages-enabled repo) and share the URL.Gist.
gh gist create --secret myproj-mltree.html, then open it through a raw-HTML viewer such ashttps://gist.githack.com/(gist.github.com itself shows HTML as source).
Warning: the export contains your scripts. The default file embeds the full source of every step script and every run's script snapshot, plus params, notes, tags and artifact paths. If any of that is private (unpublished methods, internal paths, credentials someone hard-coded), use Shareable HTML without scripts, or
--no-scripts/include_scripts=false, and don't publish the file on a public Pages site or a public gist. The absolute project path on the server is never included.*-mltree.htmlis in this repo's.gitignore; add it to yours too so an export isn't committed by accident.
Tools
Tool | What the assistant uses it for |
| Write the single-file, offline, read-only HTML of the map and return its path and size. It includes the scripts unless |
| Build the map of an existing project by static analysis (never runs your code): steps, params, edges, utilities, and existing results imported as runs. Idempotent; |
| Create |
| Register a node, or update it if the name exists. Script paths are relative to the project and may not escape it. |
| Add an edge. Both steps must exist; self-loops and cycles are rejected; warns when outputs and inputs don't match. |
| Nodes (script, params, latest run status, run count), edges and a topological order. |
| Execute the step's script and record the run by itself: params, snapshot, command, exit code, duration, log and metrics. Returns the run and the log tail. Off with |
| Run every grid combination one after another as children of a sweep run, and return the best one. |
| Follow or stop a run or sweep started with |
| Group trials that the assistant runs itself: |
| Record a run. Metrics must be numbers. Artifacts ≤ 50 MB are copied into |
| Data versions now vs each step's latest run: which inputs changed or are missing, so the assistant knows what to re-run. |
| Param changes, differing metrics and data versions of 2+ runs, and a unified diff of the first two runs' scripts. |
| Runs, newest first. |
| Append to (or replace) the notes of a step or a run. |
| Add / remove tags on a run, or set the whole list. |
| GNN architecture summary (static) and dataset stats of one step or all; |
| Best succeeded run by a metric. |
| URL of the map viewer. It starts |
Resource: mltree://pipeline — the same JSON as get_pipeline.
Errors come back as normal MCP tool errors with a message the assistant can act on (e.g. "Unknown step 'trian'. Known steps: split, train").
Project layout
your-project/
├── steps/ # one script per node (your code)
│ ├── featurize.py
│ └── train_gcn.py
└── .mltree/
├── pipeline.yaml # nodes, edges, default params — commit this
├── mltree.db # SQLite: steps, edges, runs, file-hash cache
└── runs/<run_id>/
├── run.json # params, metrics, parent, status, timestamps
├── script.py # snapshot of the step script for this run
├── log.txt # stdout/stderr of runs started by mltree (stderr lines prefixed)
├── metrics.json # $MLTREE_METRICS_FILE, if the script wrote it
├── metrics_history.jsonl # one line per MLTREE_METRIC print (or log_run history point)
└── artifacts/ # copied outputs (plots, small models…)mltree.db is the source of truth; pipeline.yaml is rewritten on every change so it diffs well in git. If you commit only pipeline.yaml, a fresh clone rebuilds the steps and edges from it. Whether you commit mltree.db and runs/ is up to you.
Tell your assistant to use it (AGENTS.md / CLAUDE.md)
Codex reads AGENTS.md, Claude Code reads CLAUDE.md. Paste this into either:
## Experiment tracking with mltree (MCP)
This repo tracks its ML workflow with the `mltree` MCP server. Keep the map up to date as you work:
- At the start, call `get_pipeline`. If the project is not initialized and already has code, call `scan_project`
(`dry_run=true` first to preview) and fix its proposals; for a brand-new project call `init_project`.
- Put each pipeline stage in its own script under `steps/` (e.g. `steps/split.py`, `steps/train_gcn.py`).
Whenever you create or materially change one, call `add_step` with its name, `script_path`,
`inputs`, `outputs`, default `params` and a one-line `description`.
- Call `connect_steps` for every data dependency (upstream → downstream).
- After every execution of a step, call `log_run` with the exact `params` used, numeric `metrics`,
produced `artifacts` (plots, model files) and `status` ("failed" if it crashed, with the error in `notes`).
- When a run is a variation of an earlier one (HPO trial, new architecture, different split seed),
pass that run's id as `parent_run_id` so the experiment tree branches correctly.
- Prefer `run_step` over running a step script yourself: it records the run (params, script, log, metrics) by
itself. Make scripts print `MLTREE_METRIC name=value` lines. For a grid search use `run_sweep`. For trials you
run yourself (Optuna), use `start_sweep`, then `log_run(..., sweep_id=...)`, then `finish_sweep`.
- Before re-running, call `data_status` to see which steps have changed inputs; to explain how two runs differ,
call `compare_runs`.
- To answer "which model was best?" use `best_run` (mode "min" for losses/RMSE, "max" for AUC/R²)
and `list_runs`; don't guess from memory.
- Record decisions with `add_note` (on the step or run) and label runs with `tag_run` ("baseline", "paper").
- When the user wants to see the workflow, call `open_map` and give them the URL. When they want to send it to
someone, call `export_map` (warn them that it includes the scripts unless `include_scripts=false`).Demo: a tiny GNN pipeline
examples/gnn_demo/ is a toy molecular-property pipeline: load SMILES → featurize to graphs → split → train a toy GCN (mean aggregation + ridge, stdlib only) → evaluate. It runs without torch; featurize.py uses RDKit if installed.
cd examples/gnn_demo
python steps/load_smiles.py && python steps/featurize.py && python steps/split.py 0.2 42 \
&& python steps/train.py 1.0 && python steps/evaluate.py
# register the steps and log a few FAKE runs (tagged "demo") to see the tree
python register_demo.py --reset
mltree-mcp view --project . # http://localhost:8765
mltree-mcp view --project . --allow-run # same, with Run / Grid sweep buttons (the demo needs only the stdlib)With --allow-run, run load_smiles → featurize → split → train → evaluate from the map, then try Grid sweep…
on train with alpha = 0.05, 0.2, 0.5, 1, 2 and rank by train_rmse (lower is better).
The values in data/molecules.csv and the metrics logged by register_demo.py are illustrative demo data, not real measurements.
Development
uv venv && uv pip install -e ".[dev]"
pytest -qThe tests cover:
the store, and every tool called in-process through the MCP server
the
mltree://pipelineresource and the demoa smoke test that launches the stdio server and talks to it with the MCP client SDK
every viewer API route, the SPA fallback, the live event stream and
open_mapthe runner (CLI detection, param passing, metric parsing, logs, cancel, grid sweeps, schema migration) and the run safety guard (403 without
--allow-run, withoutX-MLTree, with a foreignOriginorHost)data versions, compare/diffs, notes/tags, GNN summaries (static and introspected) and the HTML export (with a headless-Chrome render check when Playwright is installed)
the multi-project registry,
/p/<slug>/routing, theprojectsCLI andopen_mapagainst a multi-project viewer
Frontend (React + TypeScript + Vite + React Flow + Monaco + Plotly) lives in frontend/:
cd frontend && npm install
npm run dev # http://localhost:5173, proxies /api to a running `mltree-mcp view`
npm run build # type-checks and writes the bundle into src/mltree_mcp/static/ (commit it)CI (.github/workflows/test.yml) runs pytest on Python 3.11–3.13 (plus macOS and the 1.x MCP SDK), checks that the
committed static/ bundle matches npm run build, and builds the sdist and wheel, runs twine check and installs
the wheel in a clean venv.
Screenshots: pip install -e ".[screenshots]" && playwright install chromium, start the viewer on the demo, then python scripts/screenshots.py. For the run screenshots, start it on a fresh copy of the demo with --allow-run and run python scripts/screenshots_run.py (this really runs the demo scripts); for the data-version / curves / diff screenshots run python scripts/screenshots_data.py --project <copy> the same way; for the notes / GNN screenshots start it with --allow-run --python <python with torch_geometric> and run python scripts/screenshots_gnn.py; for the project switcher and docs/demo.gif, register two copies of the demo, start view --projects and run python scripts/screenshots_projects.py (needs ffmpeg). If you have a local Chrome, use --chrome /usr/bin/google-chrome instead of installing Playwright's browser.
Roadmap
MCP core ✅
Map viewer ✅ (map, script panel with run snapshots, experiment tree, compare, live refresh)
scan_project✅ (static import of existing projects and their MLflow / Optuna / Lightning / wandb results)Run steps and sweeps ✅ (0.5.0: Run button, live logs, auto-recorded runs, grid sweeps, sweep fans,
run_step)Data versioning and compare ✅ (0.6.0: input/output hashes per run, changed-input flags, param changes, code diff, metric curves)
Notes, tags and GNN views ✅ (0.7.0: editable notes/tags, static architecture summary, opt-in dataset stats)
PyPI packaging, CI, multi-project viewer ✅ (0.8.0)
Releasing
Releases go to PyPI from .github/workflows/release.yml with trusted publishing
(no API token). One-time setup:
On PyPI, under Your projects → Publishing → Add a new pending publisher, enter: project
mltree-mcp, owneryboulaamane, repositorymltree-mcp, workflowrelease.yml, environmentpypi. (Optional: the same on TestPyPI with environmenttestpypi.)On GitHub, Settings → Environments: create
pypi(andtestpypi); adding yourself as a required reviewer makes every upload wait for your click.
To release: bump version in pyproject.toml, src/mltree_mcp/__init__.py and frontend/package.json, rebuild the
frontend, commit, then publish a GitHub release with tag vX.Y.Z (gh release create v0.8.0 --generate-notes).
The workflow checks the tag matches the version, builds, runs twine check and uploads. Actions → release → Run
workflow uploads to TestPyPI instead. Locally: python -m build && twine check --strict dist/*.
Changelog
0.8.0
Multi-project viewer:
mltree-mcp view --projects DIR ...or a registry (~/.mltree/projects.json, managed withmltree-mcp projects add|list|remove); each project under/p/<slug>/, a project switcher in the header,GET /api/projects;open_maplinks into a running multi-project viewer.PyPI-ready packaging: classifiers, project URLs,
py.typed, a lean sdist; the wheel ships the viewer and export bundles.python -m build+twine check --strictpass.CI: GitHub Actions test matrix (3.11–3.13, macOS, MCP SDK 1.x), frontend bundle freshness check, wheel smoke test; release workflow with PyPI trusted publishing.
README: demo GIF, badges, refreshed screenshots.
0.7.0
Notes on steps and runs and tags on runs, editable in the viewer (loopback +
X-MLTreeonly), shown on nodes, tree cards and the runs table, with a Tag filter in the experiment tree; MCP toolsadd_note,tag_run;get_pipelinereturns notes and tags; both are in the export.GNN views: static
nn.Modulearchitecture summary for PyG / DGL models (layers, dims, repeats, pooling, forward order) and opt-in dataset / checkpoint stats loaded in a subprocess; MCP toolgnn_summary, CLImltree-mcp gnn,GET /api/steps/{step}/gnn,POST …/gnn/introspect. The demo gets a PyGMolGCNmodel file.Store schema v4 (step
notes,gnn_statscache).
0.6.0
Data versions: inputs/outputs are fingerprinted (SHA-256, cached by size + mtime) and recorded with each run; the step panel, the node badge (⚠ data changed / input missing), Compare and the export show them.
Compare: param changes per run, a data-versions row group, overlaid step-wise curves (SVG, works offline) and a unified / side-by-side code diff of the script snapshots (computed in the browser, works in the export).
MCP tools
data_statusandcompare_runs;log_run(history=, record_data=);GET /api/data.Store schema v3 (run
data,file_hashescache); older databases migrate on open.The viewer runs file hashing off the event loop, so live updates keep flowing on big data folders.
0.5.0
Run steps from the map (
view --allow-run): Run dialog with prefilled params and a command preview, live stdout/stderr panel (SSE), Cancel, and automatic run records (params, snapshot, command, exit code, duration, log, metrics fromMLTREE_METRIClines or$MLTREE_METRICS_FILE, step-wise history).Grid sweeps: sweep runs that group their children, a sweep launcher in the viewer, collapsible sweep fans with the best child highlighted in the tree, and sweep cards in the HTML export.
MCP tools
run_step,run_sweep,run_log,cancel_run,start_sweep,finish_sweep, andlog_run(sweep_id=).scan_projectimports Optuna studies andGridSearchCVcv_results_CSVs as sweeps.Store schema v2 (run
kind,sweep_id,sweep,command,exit_code); v1 databases migrate on open.Export: commands are made portable (interpreter basename, project-relative paths).
0.4.0 shareable single-file HTML export · 0.3.0 scan_project · 0.2.0 map viewer · 0.1.0 MCP core
License
MIT © Yassir Boulaamane
Available Tools
21 toolsadd_noteA
Add a note to a step or a run, e.g. why a run failed, what a step assumes, or a conclusion from a comparison. Notes show in the viewer (where the user can edit them), in get_pipeline / list_runs and in the HTML export.
| Name | Required | Description | Default |
|---|---|---|---|
| step | No | Note on this step (give step OR run_id) | |
| text | Yes | The note, plain text (markdown is fine); appended as a new paragraph | |
| run_id | No | Note on this run (give step OR run_id) | |
| replace | No | Replace the existing notes instead of appending |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the load, and it does disclose meaningful behavior: notes surface in the viewer, are user-editable, and appear in get_pipeline, list_runs, and the HTML export. It doesn't cover permissions or whether the note is returned, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no filler; the core action comes first and the visibility/consumers detail follows as supporting context. Every clause contributes information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and the description covers purpose, use cases, and downstream visibility. What's missing is minor but real: no note on permissions or limits, and no mention of what happens when both step and run_id are omitted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and every parameter (step, run_id, text, replace) is documented in-schema, so the schema already does the heavy lifting. The description's 'to a step or a run' only echoes the schema's own 'give step OR run_id' guidance, adding no new syntax or format details.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Uses a specific verb (add) plus resource (note) and states the two attachment targets (step or run), so the agent can distinguish it from siblings such as tag_run or log_run with no schema inspection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The examples 'why a run failed, what a step assumes, or a conclusion from a comparison' give concrete situations that call for this tool, which is stronger than generic context. It stops short of naming alternatives or exclusions, so it stays at 4 rather than 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
add_stepB
Register a pipeline step (a node on the map), or update it if the name already exists.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | Unique step name, e.g. 'load_smiles', 'split', 'train_gcn' | |
| inputs | No | Data this step consumes, e.g. ['graphs.pkl'] | |
| params | No | Default parameters, e.g. {'test_size': 0.2, 'seed': 42} | |
| outputs | No | Data this step produces, e.g. ['train.pkl', 'test.pkl'] | |
| description | No | One-line description of what the step does | |
| script_path | No | Path of the step's Python script, relative to the project root |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It usefully discloses that an existing name is updated rather than rejected, but is silent on what an update replaces (are stale inputs/outputs/params discarded or merged?) and on whether the step is persisted immediately.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence with zero filler; the upsert caveat is placed where it will be read.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a rich six-parameter schema and an output schema present, the description need only cover intent and side effects. Intent and upsert semantics are covered; the only real gap is the precise overwrite/merge semantics of the update path.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and every parameter carries a concrete example, so the schema does the heavy lifting. The description adds no extra meaning about parameter interaction, such as whether outputs must match a downstream step's inputs.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Register a pipeline step') plus the domain framing ('a node on the map'). It also discloses the upsert behavior, which distinguishes it from a pure create. It doesn't explicitly contrast with sibling connect_steps, but the resource distinction is inferable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no statement of when to call this versus connect_steps, get_pipeline, or init_project, and no prerequisites (e.g., must a project exist first?). The only guidance is implicit in the upsert clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
best_runB
Find the best succeeded run by a metric.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | 'min' for losses/errors, 'max' for scores | max |
| step | No | Restrict to one step | |
| metric | Yes | Metric name, e.g. 'val_rmse' or 'roc_auc' |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It does disclose that only succeeded runs are considered and that selection is metric-based, but it omits tie-breaking behavior, permission requirements, and whether 'succeeded' has any special semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. It is appropriately brief for a tool whose schema and output schema carry most of the structural detail, though it could provide slightly more framing around the key qualifier 'best'.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool is simple, with full schema coverage and an output schema, so the description does not need to explain parameters or return values. However, with no annotations, it remains incomplete on behavioral details such as tie handling and permission expectations.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so metric, mode, and step are already well documented. The description mentions the metric concept but adds no syntax or usage detail beyond what the schema provides, making the baseline 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: find the best succeeded run by a metric. It is understandable without opening the schema, but it does not differentiate itself from list_runs or explain what 'best' means, so it falls short of full sibling-level clarity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit guidance on when to use this tool versus list_runs or other siblings. The phrase 'Find the best succeeded run' implies the use case, but no alternatives, prerequisites, or exclusions are mentioned.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
cancel_runB
Stop a run (SIGTERM, then SIGKILL after 5 s) or a whole sweep started from this session.
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | Yes | Run or sweep id started by run_step / run_sweep |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden, and it does add real value by disclosing the termination mechanism (SIGTERM, escalating to SIGKILL after 5 s), signalling a forced, likely non-graceful termination. It omits other important traits: whether cancellation is reversible, what happens to partial results or checkpoints, and whether cancelling a sweep cascades to its child runs.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single compact sentence with the core action and the key mechanic (SIGTERM/SIGKILL timing) front-loaded, and no filler. The parenthetical is dense but every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, which lowers the bar. Still, for a destructive, annotation-free operation on runs and sweeps, the description should say what happens to in-flight work and whether sweep cancellation propagates to child runs; those gaps matter for correct invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the run_id description already states it accepts a sweep id as well as a run id, so the description adds little parameter-level detail. Its mention of 'a whole sweep' echoes rather than extends the schema, which is consistent with the baseline 3 for fully-covered single-parameter tools.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (stop) and resource (run or sweep) with an added scope qualifier ('started from this session') that separates it from other run-level tools. It does not explicitly name which siblings it supersedes or differs from, so identification relies on the reader inferring against run_step/run_sweep/start_sweep.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'started from this session' implies a precondition for use, and 'or a whole sweep' hints at the sweep-cancellation case. However, there is no explicit when-to-use vs when-not-to-use guidance and no alternative tool is named for cases where the run was not started in this session.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
compare_runsA
Compare runs: params that differ (baseline -> each run), metrics side by side, data versions used, and a unified diff of the script snapshots of the first two runs.
| Name | Required | Description | Default |
|---|---|---|---|
| run_ids | Yes | Two or more run ids; the first is the baseline | |
| code_diff | No | Include a unified diff of the first two runs' script snapshots |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full disclosure burden, and it does surface meaningful behavior: the four categories of comparison output and the non-obvious constraint that the script diff only covers the first two runs. It stops short of stating that this is a read-only/non-mutating operation or any limits on run count or cost.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence, front-loaded with the verb, then a tight enumeration of outputs. No filler, no restatement of the title, and every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists and parameters are fully documented, so the description needn't explain return shapes; what it adds is the right shape of summary for a read-only comparison tool. Minor gaps remain around minimum run count enforcement and error behavior with a single run id.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so run_ids and code_diff are already fully documented, including the baseline rule and the first-two-runs diff scope. The description restates rather than extends that semantics, which is the defined baseline of 3.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Compare runs") and enumerates exactly what the comparison yields: differing params, metrics, data versions, and a script diff. It is clearly distinct from list_runs, best_run, and run_log. It loses a point only because it never names a sibling to contrast against explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied rather than stated: "params that differ (baseline -> each run)" signals that you supply multiple run ids with the first as baseline, which tells an agent when the tool fits. There is no explicit when-to-use, when-not-to-use, or alternative such as best_run for picking a winner instead of comparing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
connect_stepsA
Draw a directed edge source -> target. Both steps must exist; cycles are rejected.
| Name | Required | Description | Default |
|---|---|---|---|
| label | No | Optional edge label, e.g. the data passed along | |
| source | Yes | Upstream step name | |
| target | Yes | Downstream step name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It usefully discloses two key constraints (existence prerequisite and cycle rejection), but omits what happens on failure, whether the edge is idempotent, or whether it mutates persisted graph state.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two compact sentences with the operation first and the constraints immediately after; every clause carries information.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need no explanation, and the essential preconditions are stated. Only the failure/error behavior of the cycle or missing-step cases is left unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so source/target direction and the optional label are already documented in the schema. The description's ordering implicitly reinforces direction but adds no syntax or format detail beyond the structured fields.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb (draw a directed edge) with explicit source -> target roles, which cleanly separates it from node-creating siblings like add_step. It doesn't name a sibling directly, but the semantics are unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Preconditions ("both steps must exist; cycles are rejected") imply when the call will succeed, but there is no explicit guidance on when to use this vs. alternatives like add_step or log_run, and no mention of what to do on rejection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
data_statusA
Data versions: the current SHA-256 of every step's input and output files, what the step's latest run used, and which inputs changed since (so the step is stale and should be re-run). Reads files only; runs nothing.
| Name | Required | Description | Default |
|---|---|---|---|
| step | No | Only this step (default: all) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the load and does it: it declares the read-only contract ('Reads files only; runs nothing') and explains the comparison logic against the latest run, which is the key behavioral trait. It omits cost/latency considerations for hashing large file sets.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core output (hashes, latest-run comparison, staleness) is front-loaded, and the trailing 'Reads files only; runs nothing' earns its place as a safety signal. The parenthetical is slightly dense but no sentence is wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, and the description still covers read-only behavior, scope, and the staleness interpretation. Nothing an agent needs in order to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The single `step` parameter is fully documented in the schema ('Only this step (default: all)'), and the description's 'every step's input and output files' corroborates the all-steps default. That is baseline-level value, no additional semantics about step identifiers or scoping.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States the concrete resource precisely: SHA-256 hashes of each step's input/output files, the hashes the latest run used, and which inputs changed since. That is a specific, unambiguous verb+resource pair an agent can distinguish from siblings like list_runs or run_log, though no sibling is named explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Implies the decision it supports -- 'which inputs changed since (so the step is stale and should be re-run)' -- giving the agent a clear trigger for calling it before re-running or sweeping. It also closes off misuse with 'reads files only; runs nothing', though it never names run_step or list_runs as the alternative actions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
export_mapA
Write a single self-contained HTML file of the map (steps, code, runs, experiment tree, compare).
It opens offline in any browser, read-only, with no server, so the user can email it, post it in Slack or host it on GitHub Pages / a gist. Returns the file path and size. It contains the scripts unless include_scripts=false: tell the user that before they share it.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Output file or folder (relative to the project root). Default: <project root>/<project>-mltree.html | |
| include_scripts | No | Embed the step scripts and their run snapshots |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it discloses the output is self-contained, read-only, offline, requires no server, and returns file path and size. It flags that scripts are embedded by default and that the user must be warned before sharing – a genuine safety trait. It omits what happens to an existing file at `path` (overwrite/failure), which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action and the contents list are front-loaded in the first sentence, and the sharing caveat is separated so it reads as a distinct instruction. The parenthetical content list and the stray line breaks add slight clutter but no wasted sentences.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be spelled out, yet the description still notes path and size. All parameters are documented, the behavioral scope is covered, and the share-safety caveat is included – nothing an agent needs to call this correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3, but the description adds real meaning beyond the schema: it explains the consequence of `include_scripts=false` (scripts omitted, and the sharing warning no longer applies). It does not add anything about `path` semantics, which the schema already covers with its default.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and artifact: 'Write a single self-contained HTML file of the map', and enumerates its contents (steps, code, runs, experiment tree, compare). It does not distinguish itself from the sibling open_map, which an agent could easily confuse it with, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives clear situational context: the file opens offline with no server so the user can email it, post it in Slack, or host it on GitHub Pages/gist. This tells the agent when the tool is appropriate, but there is no explicit exclusion or pointer to open_map as the interactive alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
finish_sweepB
Mark a sweep finished and return its summary (trial counts and the best trial).
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Outcome of the sweep | succeeded |
| sweep_id | Yes | Id returned by start_sweep |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description must carry the full behavioral burden for this mutation operation. It states that the sweep is marked finished and that a summary is returned, but it does not disclose important details like idempotency, required permissions, effects on in-flight trials, or error conditions.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single focused sentence with no wasted words. It front-loads the action and then mentions the return summary, which is appropriately sized for this simple tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has an output schema, so the description does not need to explain return formatting in detail. However, with no annotations and only implicit usage guidance, the definition is somewhat thin for a mutation operation whose status parameter has behavioral implications.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameters are already well documented by the schema. The description adds no parameter-level detail beyond what the schema provides, which is acceptable at the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource: 'Mark a sweep finished'. It also clarifies that the tool returns a summary with trial counts and the best trial. It does not explicitly compare itself to siblings like start_sweep or best_run, but its purpose is unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The usage is implied by 'finished', meaning this should be called when a sweep is complete. However, there is no explicit guidance on when to choose finish_sweep versus alternatives such as cancel_run, or how to pick the status value.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_pipelineB
Return the whole map: nodes (with params, script and latest run status), edges and a topological order.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the burden; it does establish that this is a retrieval ("Return") with no arguments and tells the agent the data includes run status, which signals freshness comes along with the map. It says nothing about cost, size, permissions, or whether the call has side effects, which matters for a zero-param call whose name does not itself imply read-only semantics.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
One sentence, front-loaded with the object returned, then the enumerated contents. No filler and nothing buried.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no parameters and an output schema present, the description needn't document return values, and the shape of the payload is briefly characterized. But with zero annotations and several plausible sibling tools that also surface map data, the definition leaves the agent without routing criteria or any note on cost/freshness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing to disambiguate and the baseline is 4. The description correctly implies no scoping inputs are needed to fetch the whole map.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a clear verb ("Return") and specific resource ("the whole map"), then enumerates the payload: nodes with params, script and latest run status, edges, and a topological order. An agent knows exactly what it gets. It falls short of a 5 because it never distinguishes itself from siblings like open_map or export_map, which plausibly return the same map.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to call this versus open_map, export_map, or list_runs. The word "whole" faintly implies a full fetch rather than a partial one, but no explicit condition or alternative is named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
gnn_summaryA
GNN view of a step: the model architecture read statically from its script and imported project modules (conv layer types and counts, hidden sizes, heads, pooling, head, forward order; nothing is imported or run), dataset classes it constructs (TUDataset, MoleculeNet, QM9, OGB, DGL ...), and cached dataset stats (graphs, nodes/edges per graph, feature dims, classes or target range, self loops, isolated nodes).
| Name | Required | Description | Default |
|---|---|---|---|
| step | No | One step in full (default: every step with GNN models or graph data) | |
| introspect | No | Also load the step's .pt/.bin graph files to compute dataset stats. Only when the user asked for it: it runs torch.load / dgl.load_graphs in a subprocess with the project's Python, and unpickling can execute code |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description excels here by contrasting two behavioral states: the default state where models are read 'statically... nothing is imported or run' versus the `introspect` state, which explicitly states that loading files 'can execute code.' This is critical behavioral context.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is dense and highly technical, serving as a comprehensive single block of text. While efficient, its structure is very complex, typical of GNN tooling.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given that an output schema exists, the description does not need to explain return values. It comprehensively defines the inputs, the scope of the summary, and the behavioral risks, making it a complete definition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even with 100% schema coverage, the description adds massive value, especially for the `introspect` parameter, by detailing the dangerous subprocess actions (torch.load, unpickling) that occur when that flag is set.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description precisely defines the scope of the tool as a 'GNN view of a step,' detailing exactly what information is extracted (model architecture, dataset classes, cached stats). This highly specific definition clearly separates it from other general step management tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
While it doesn't start with a high-level 'when to use' statement, it defines its utility by listing the specific GNN data it provides. The strong warning within the `introspect` parameter provides crucial usage guidance regarding potential execution risks.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
init_projectA
Create the .mltree/ store (pipeline.yaml, mltree.db, runs/) in the project root. Safe to call again.
| Name | Required | Description | Default |
|---|---|---|---|
| name | No | Project name; defaults to the folder name |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries the full behavioral burden, and it does disclose the key risk trait: idempotency ('safe to call again'). It leaves open what happens to pre-existing files (overwrite vs preserve), whether permissions are required, and whether the call is slow — gaps that matter for an initialization/mutation tool with zero annotation coverage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the concrete side effects front-loaded before the idempotency note. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Output schema exists and annotations are absent but the tool is simple (one optional param), so the description covers nearly everything needed: what is created, where, and that re-invocation is safe. Only the overwrite/permission behavior on existing stores is unaddressed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the single optional 'name' parameter is fully documented in the schema ('defaults to the folder name'). The description adds no parameter-level detail, so the schema baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb (Create) and resource (.mltree/ store) and enumerates the artifacts produced (pipeline.yaml, mltree.db, runs/), so the agent knows exactly what will exist afterward. It does not distinguish itself from siblings such as scan_project, but no sibling plausibly competes for the same action.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: creating the store is obviously a prerequisite step, but the description never says when to call it, when not to, or how it relates to scan_project. 'Safe to call again' informs repeated invocation but is not selection guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_runsB
List runs, newest first.
| Name | Required | Description | Default |
|---|---|---|---|
| step | No | Only runs of this step | |
| limit | No | Maximum runs to return (1-1000) | |
| status | No | Only runs with this status | |
| parent_run_id | No | Only direct children of this run |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full behavioral burden. It discloses that results are ordered newest first, but does not state that the operation is read-only, whether it has side effects, or how pagination behaves beyond the schema's limit parameter.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with zero waste. Every word contributes directly to the operation and its ordering behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The schema fully documents all parameters and an output schema exists, so the description needn't explain return values or parameter details. However, with no annotations and no usage guidance, the description leaves important behavioral and selection context unstated.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all four parameters are already documented in the schema. The description adds no parameter-specific meaning beyond the ordering note, making the baseline score of 3 appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource ('List runs') plus an ordering behavior ('newest first'), so an agent can understand the core operation. It does not explicitly differentiate itself from sibling tools such as best_run or log_run, though those appear to be distinct operations.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no guidance on when to use this tool versus alternatives, nor any exclusions or prerequisites. The agent must infer usage entirely from the tool name and schema.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
log_runB
Record one execution of a step: params, metrics, artifacts and its parent run in the experiment tree. The versions (SHA-256) of the step's input and output files are recorded too, so later runs can tell when the data changed.
| Name | Required | Description | Default |
|---|---|---|---|
| step | Yes | Name of the step that was executed | |
| tags | No | Optional tags, e.g. ['hpo', 'gcn'] | |
| notes | No | Free-text notes about the run | |
| params | No | Parameters actually used for this run | |
| status | No | Run outcome | succeeded |
| history | No | Step-wise metrics for curves, e.g. [{'epoch': 1, 'train_loss': 0.9, 'val_rmse': 1.1}, ...] | |
| metrics | No | Numeric results, e.g. {'val_rmse': 0.61, 'r2': 0.78} | |
| sweep_id | No | Sweep this run is a trial of (from start_sweep) | |
| artifacts | No | Files produced (paths relative to project), as a list or {name: path}; copied into .mltree/runs/<run_id>/ when <= 50 MB | |
| record_data | No | Fingerprint the step's input/output files now (data versions). False for results from elsewhere | |
| parent_run_id | No | Run this one branches from (e.g. the base config of an HPO trial) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full behavioral burden. It adds useful context that SHA-256 versions of input/output files are recorded so later runs can detect data changes, but it does not state that this is a write/mutation operation, nor does it cover permissions, duplicate handling, or error behavior.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core action and followed by one sentence of useful behavioral context about data versioning. No filler and no repetition.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained, and full schema coverage documents the parameters. But with 11 parameters and no annotations, the description should still clarify write semantics and distinguish this tool from run_step and run_log; those gaps keep it from being complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so all 11 parameters are already documented in the schema. The description restates some of the same fields (params, metrics, artifacts, parent run) without adding syntax, format, or edge-case semantics beyond what the schema provides, so the baseline of 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'Record one execution of a step', and enumerates what is captured (params, metrics, artifacts, parent run). However, it gives no differentiation from similarly named siblings such as run_step, run_log, and list_runs, so an agent cannot tell from the description alone which tool to pick.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
There is no explicit when-to-use or when-not-to-use guidance, and no mention of alternatives like run_step or run_log. Usage is only weakly implied by 'Record one execution of a step', leaving the agent to infer routing from the name alone.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
open_mapA
Return the URL of the mltree map viewer (and start it if needed). Give the URL to the user.
| Name | Required | Description | Default |
|---|---|---|---|
| port | No | Viewer port (default $MLTREE_VIEW_PORT or 8765) | |
| start | No | Start the viewer in the background if it is not running | |
| allow_run | No | Start it with Run buttons enabled (only if the user asked to run steps from the map) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden, and it does disclose the key side effect: the viewer may be started in the background. It says nothing about process lifetime, what happens if the port is occupied, or the security implication of enabling Run buttons, so meaningful gaps remain.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, zero filler, with the action and its conditional side effect front-loaded ahead of the delivery instruction.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so the return value (a URL) needn't be explained, and the description covers the conditional start behavior. Minor gaps remain around failure modes and whether the started viewer persists, but nothing essential to invoking it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% – port defaults, the start flag, and the allow_run condition are all documented in the schema itself. The description adds no parameter meaning beyond that, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a concrete verb and resource: return the URL of the mltree map viewer, and start it if needed. It is clearly distinguishable from siblings like export_map or get_pipeline, though it never names an alternative to contrast with.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
'Give the URL to the user' is a delivery instruction, not a selection rule. There is no statement of when to prefer this over export_map or get_pipeline, and no exclusions; usage context is only implied.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_logA
Return the status and the last lines of a run's log (live while it runs).
| Name | Required | Description | Default |
|---|---|---|---|
| tail | No | Last N lines | |
| run_id | Yes | Run id |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the behavioral burden. It does disclose that output is live during execution and includes status alongside log tail, but it omits details like permissions, truncation behavior, or handling of finished/failed runs. Given the presence of an output schema, the return format gap is mitigated, making a 3 appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, efficient sentence that front-loads the action and resource. The parenthetical adds a useful nuance without bloat, though there is minimal structure beyond that one sentence.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple two-parameter read tool with a fully described schema and an output schema, the description covers the essentials: what it returns and when it is live. Missing details (e.g., behavior on completed runs) are minor given the structured coverage.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so both parameters (run_id and tail) are already documented in the schema. The description adds no extra meaning about the tail parameter's behavior or run_id format, so the baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Return') and resource ('status and the last lines of a run's log'), making the tool's function immediately clear. It does not explicitly differentiate itself from siblings like log_run or list_runs, which keeps it just short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The parenthetical '(live while it runs)' hints that the tool can be polled during an active run, which is useful implied guidance. However, there is no explicit when-to-use vs. when-not-to-use guidance or reference to alternatives such as log_run, leaving usage to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_stepA
Execute a step's script as a subprocess and record it as a run automatically.
Params are passed as CLI flags when the script uses argparse/click (or positionally for sys.argv scripts, or
key=value for hydra), and always as $MLTREE_PARAMS (JSON). Records params, script snapshot, command, exit status,
duration, log (.mltree/runs//log.txt) and metrics from MLTREE_METRIC name=value stdout lines or a JSON file
written to $MLTREE_METRICS_FILE / a declared metrics*.json output. Returns the run and the end of its log.
| Name | Required | Description | Default |
|---|---|---|---|
| step | Yes | Step to execute (its script_path is run with Python from the project root) | |
| wait | No | Wait for the run to finish (up to timeout_s) | |
| params | No | Params for this run; default: the last run's params, else the step's | |
| timeout_s | No | Max seconds to wait; the run keeps going after that | |
| extra_args | No | Extra command-line arguments appended verbatim | |
| parent_run_id | No | Run this one branches from (default: newest succeeded run of an upstream step) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full load and does well: it discloses that arbitrary script code is executed as a subprocess, that params are injected three different ways plus $MLTREE_PARAMS, and exactly what gets persisted (params, script snapshot, command, exit status, duration, log path, metrics). It does not state whether a run record is still written when the script fails or whether execution mutates project state beyond recording, which keeps it from a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The core action is front-loaded in sentence one, and the following clauses are dense but information-bearing rather than filler. The long parenthetical enumerating param-passing styles is slightly cramped reading but not wasteful.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 6-param mutating execution tool with no annotations, the description covers the mechanism, the side effects recorded, the log and metrics conventions, and even summarizes the return value (the run plus the tail of its log) despite an output schema existing. An agent has enough to call it correctly without opening anything else.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3, but the description genuinely adds semantics the schema lacks: it explains how `params` is transformed per script framework (argparse/click flags, positional sys.argv, hydra key=value, always $MLTREE_PARAMS JSON) and how metrics are detected from stdout or $MLTREE_METRICS_FILE. The remaining params (wait, timeout_s, extra_args, parent_run_id) are already well documented in the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening sentence gives a specific verb and resource: 'Execute a step's script as a subprocess and record it as a run automatically.' An agent knows exactly what happens (subprocess execution plus automatic run recording). It does not, however, explicitly contrast itself with nearby siblings like run_sweep or cancel_run, so it falls short of a 5.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the mechanics described (params get passed as CLI flags, which presupposes a script that accepts arguments), but the description never states when to choose run_step over run_sweep, or what preconditions exist (step must exist, project must be initialized). No exclusions or alternatives are named.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_sweepB
Run a grid search: one sweep run plus one child run per combination, executed one after another.
| Name | Required | Description | Default |
|---|---|---|---|
| grid | Yes | Param -> list of values, e.g. {'alpha': [0.1, 1, 10], 'layers': [1, 2]} | |
| mode | No | Whether lower or higher metric is better | max |
| step | Yes | Step to execute for every combination | |
| wait | No | Wait for the whole sweep (up to timeout_s) | |
| metric | No | Metric that ranks the runs, e.g. 'val_rmse' | |
| params | No | Fixed params shared by all runs | |
| max_runs | No | Refuse grids larger than this | |
| timeout_s | No | Max seconds to wait | |
| extra_args | No | Extra command-line arguments for every run |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden of behavioral disclosure. It usefully states that execution creates one sweep run plus child runs and runs combinations one after another, but it does not disclose permissions, failure behavior, blocking semantics, or side effects.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single front-loaded sentence with no wasted words. It communicates the core action and execution model efficiently.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The tool has nine parameters, a nested grid object, and an output schema, so the description is only moderately complete. It explains the run structure but omits operational details such as blocking behavior, failure handling, and how the sweep relates to start_sweep/finish_sweep.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all nine parameters, including grid, mode, step, wait, metric, and max_runs. The description adds the notion that each combination produces a child run, but it otherwise does not add meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource ('Run a grid search') and explains the resulting run structure: one sweep run plus one child run per combination, executed sequentially. This is clear, but it does not distinguish the tool from sibling tools such as start_sweep, run_step, or finish_sweep.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description contains no explicit guidance about when to use this tool instead of start_sweep, run_step, or other sibling tools. The name and short description imply a grid-search use case, but there are no stated exclusions, prerequisites, or alternative-selection rules.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
scan_projectA
Build the map of an EXISTING project by static analysis (ast only; user code is never executed).
Detects data reads/writes, argparse/click params, local imports, docstrings and step kinds, links steps whose output paths match other steps' inputs (falling back to file numbering and imports), and imports existing results as runs tagged 'imported'. Idempotent: re-scans update scanner-owned fields, add new steps, never delete, and keep edits made with add_step. Review the returned summary and fix it with connect_steps / add_step.
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | Folder to scan, relative to the project root | . |
| dry_run | No | Return the proposed map without writing anything | |
| exclude | No | Glob patterns to skip (default: venvs, .git, tests, __pycache__, .mltree, build dirs) | |
| include | No | Glob patterns to scan (default **/*.py, **/*.ipynb) | |
| import_results | No | Import existing metrics/MLflow/Optuna/Lightning/wandb results as runs | |
| notebook_sections | No | Make each markdown-headed notebook section a step |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does so: it discloses the safety profile (AST only, user code never executed), mutation semantics (re-scans update scanner-owned fields, add steps, never delete), edit preservation (keeps changes made with add_step), and side effects (imports results as runs tagged 'imported').
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Front-loaded with the core purpose and no filler; each subsequent sentence covers detection scope, idempotency, and next steps. The middle sentence is a dense run-on list that could be split for faster scanning.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
All six parameters are documented in the schema, an output schema exists so return details needn't be restated, and the description still covers safety, idempotency, and correction workflow. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so parameters are already documented; the description nevertheless adds meaning the schema lacks, notably what import_results produces (runs tagged 'imported'). It does not explain include/exclude interaction or default traversal cost, keeping it below schema-plus-extra depth.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with a specific verb+resource ('Build the map of an EXISTING project') and immediately scopes the mechanism ('by static analysis (ast only; user code is never executed)'). The capitalized EXISTING implicitly separates it from init_project, and the enumerated detections (data reads/writes, CLI params, imports, step kinds) make the output concrete.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Clearly positions the tool in the workflow: run it, then 'fix it with connect_steps / add_step', and explains the idempotent re-scan case. It never explicitly says when NOT to use it (e.g., a brand-new project should use init_project), so exclusions stop short of a 5.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
start_sweepA
Create a sweep (an HPO study / grid search) that groups trial runs. Pass its sweep_id to log_run for each trial; the map shows the sweep as one collapsible fan with the best trial highlighted. Use run_sweep instead to have mltree launch a grid itself.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Whether lower or higher metric is better | max |
| name | No | Short label, e.g. 'alpha x layers grid' | |
| step | Yes | Step the trials run, e.g. 'train' | |
| metric | No | Metric that ranks the trials, e.g. 'val_rmse' | |
| search_space | No | Optional search space, e.g. {'alpha': [0.1, 1, 10]} | |
| parent_run_id | No | Run the sweep branches from (e.g. the baseline) |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and does disclose meaningful behavior: it creates a grouping that persists, its id must be threaded into subsequent log_run calls, and the map renders the group as a collapsible fan with the best trial highlighted. It does not say whether creation mutates/commits project state or what happens on a duplicate/invalid step, so it stops short of full disclosure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three tight sentences: what it creates, how to consume its output, and the sibling alternative. The parenthetical 'an HPO study / grid search' is a worthwhile disambiguation rather than filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists so return values need not be explained, and the description covers the creation semantics, the id hand-off, and the routing decision. It leaves open what happens if metric is omitted (no best-trial ranking) and whether the sweep must be closed with finish_sweep, both of which an agent would benefit from knowing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and each parameter carries its own description (mode, name, step, metric, search_space, parent_run_id), so the schema does the parameter work. The description adds no syntax or semantics for any of the six parameters beyond referencing the returned sweep_id, so baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Create a sweep') and immediately glosses it as 'an HPO study / grid search that groups trial runs', which makes the concept unambiguous. It also distinguishes the tool from its closest sibling by describing what log_run and run_sweep do relative to it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit usage protocol ('Pass its sweep_id to log_run for each trial') and an explicit alternative with the condition that selects it ('Use run_sweep instead to have mltree launch a grid itself'). An agent knows both the follow-up step and when to pick the other tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tag_runA
Add or remove tags on a run (e.g. 'baseline', 'best', 'final'). The tree can highlight runs by tag.
| Name | Required | Description | Default |
|---|---|---|---|
| add | No | Tags to add, e.g. ['best', 'paper-fig-3'] | |
| remove | No | Tags to remove | |
| run_id | Yes | The run to tag |
Output Schema
| Name | Required | Description |
|---|---|---|
No output parameters | ||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It discloses the mutation intent and a real side effect (tags drive tree highlighting), which is genuine context, but it omits idempotency, behavior on duplicate/absent tags, and permission requirements.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the core action and followed by the observable effect. Nothing wasted.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return values need not be explained. Still, for a mutation with zero annotation coverage, the description leaves open whether add/remove are exclusive, how existing tags are preserved, and what errors to expect.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so each parameter is already documented in the schema. The description adds only naming-convention examples for tag values, which is a modest increment over what the schema states.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb pair ('Add or remove') plus resource ('tags on a run'), with concrete tag examples. It is implicitly distinct from siblings like add_note or log_run, though it never names an alternative to bound the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The example tags ('baseline', 'best', 'final') imply the intended use case, and the second sentence hints at why tagging matters (tree highlighting). There is no explicit when-to-use, no exclusion of alternatives, and no statement about whether add and remove can be combined in one call.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
13 tool updates
v0.8.0- Added
add_note - Added
cancel_run - Added
compare_runs - Added
data_status - Added
finish_sweep - Added
gnn_summary - Changed
log_run3 fields changed- added
Input schema / properties / historyAdded value: +{ + "anyOf": [ + { + "items": { + "additionalProperties": { + "type": "number" + }, + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Step-wise metrics for curves, e.g. [{'epoch': 1, 'train_loss': 0.9, 'val_rmse': 1.1}, ...]", + "title": "History" +} - added
Input schema / properties / record_dataAdded value: +{ + "default": true, + "description": "Fingerprint the step's input/output files now (data versions). False for results from elsewhere", + "title": "Record Data", + "type": "boolean" +} - added
Input schema / properties / sweep_idAdded value: +{ + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "default": null, + "description": "Sweep this run is a trial of (from start_sweep)", + "title": "Sweep Id" +}
- Changed
open_map1 field changed- added
Input schema / properties / allow_runAdded value: +{ + "default": false, + "description": "Start it with Run buttons enabled (only if the user asked to run steps from the map)", + "title": "Allow Run", + "type": "boolean" +}
- Added
run_log - Added
run_step - Added
run_sweep - Added
start_sweep - Added
tag_run
10 tool updates
v0.4.0- First observed
add_step - First observed
best_run - First observed
connect_steps - First observed
export_map - First observed
get_pipeline - First observed
init_project - First observed
list_runs - First observed
log_run - First observed
open_map - First observed
scan_project
TDQS
Scored across 21 tools
Most tools target a distinct resource+action: steps (add_step, connect_steps, scan_project), runs (log_run, run_step, list_runs, best_run, run_log, cancel_run), sweeps (start_sweep, finish_sweep, run_sweep), and outputs (get_pipeline, open_map, export_map). The closest overlaps are start_sweep vs run_sweep (explicitly cross-referenced in the descriptions) and add_step vs scan_project (manual upsert vs static analysis), both of which are clarified in text. gnn_summary is a narrowly scoped inspection tool that stands clearly apart.
Nearly all names are snake_case verb_noun (add_step, connect_steps, list_runs, log_run, compare_runs, run_step, cancel_run, export_map). A few deviate from that pattern—best_run (adjective_noun), data_status (noun_noun) and gnn_summary (noun_verb)—but they remain readable and unambiguous. No mixing of camelCase or inconsistent delimiters.
At 21 tools the surface sits in the heavy band, spread across pipeline modeling, run logging/execution, sweeps, data versioning, notes/tags, and three output mechanisms (viewer, pipeline read, HTML export). Each tool maps to a recognizable capability, so nothing is obviously redundant, but the set is larger than the core job strictly requires.
Lifecycle coverage is broad (init_project, scan_project, add/connect steps, run/log/compare/tag/note, sweeps, export), but there is no way to delete a step, run, or note, and no tool to remove or edit an edge once created with connect_steps. Those omissions are notable in a mutable graph store, since mistakes require editing underlying files by hand. Agents can work around gaps but cannot fully clean up the model.
Maintenance
Related MCP Connectors
Cross-agent artifact workspace with provenance across Claude Code, Codex, Cursor, LangGraph.
Discover, run, inspect, build, test, and privately reuse AI workflows.
Train, explain, optimise and deploy transparent glass-box ML models via workflow tools.
Durable, shareable and governed project memory with smart triage and explicit project composition.
Related MCP Servers
FlicenseNot gradedqualityNot gradedmaintenanceEnables building and querying code knowledge graphs for project analysis, with tools for exploring code relationships, managing workflows, and automating development tasks. Integrates with Git and GitHub for branch management and pull request creation.42 npm6-- AlicenseDqualityDmaintenanceEnables AI assistants to perform MLOps workflows such as experiment tracking, model registry, dataset management, pipeline orchestration, and data lineage by wrapping DVC, MLflow, and Git.1001MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI-assisted scientific research workflow management through MCP, including project creation, ideation, experiment execution, and artifact handling, with integration for ChatGPT, Codex, and Claude Code.Apache 2.0
- AlicenseNot gradedqualityBmaintenanceEnables building, running, and optimizing cheminformatics pipelines via composable blocks, with an MCP agent interface for natural language interaction.2MIT