Skip to content
BenchMesh

Model Context Protocol · local

Connect AI assistants (MCP)

AI assistants such as Claude Code, Claude Desktop and Cursor can connect to the running BenchMesh app: read your instruments, look at recordings, write and validate flows and - only when you allow it - set instruments, run flows and record.

What MCP is

The Model Context Protocol is an open standard for connecting AI assistants to tools and data. An MCP server offers tools - named actions with a description and typed arguments - and an MCP client (the assistant) decides when to call them while it works on your request. BenchMesh is an MCP server: its tools read the bench, handle flows and recordings, and set instruments within the access you grant.

Endpoint

MCP endpoint
http://127.0.0.1:57666/mcp
  • Streamable HTTP with JSON responses (POST JSON-RPC; no server stream, so GET /mcp answers 405). Protocol versions 2025-11-25, 2025-06-18, 2025-03-26 and 2024-11-05.
  • The app must be running - the endpoint is part of it. There is nothing to install.
  • The desktop app listens on port 57666, or on a free port if that one is taken. The endpoint actually in use, and the bridge command for this computer, are shown in Automation → Settings → MCP. For the stdio bridge, set BENCHMESH_URL (e.g. http://127.0.0.1:57700) when it is not on 57666.

Access levels

You choose what clients may do in Automation → Settings → MCP access:

AccessClients may
offNothing. No tools are listed; every call returns an error saying where to enable access.
readRead only - the default. Instruments, flows (including validating a draft), runs and recordings; plus abort_run.
controlEverything in read, plus set instruments, save and run flows, continue prompts, start and stop recordings.

A client that calls a control tool at read access gets a message that the user can allow it in those settings.

Tools

ToolAccessWhat it does
bench_overviewreadInstruments on the bench: id, name, model, online, live status per class / channel, status fields and operations (setters with type, min, max, unit, energizes).
read_instrumentreadRead one live status field (e.g. PSU VOUT, DMM MEAS, ELL IIN) or run one query op.
flow_formatreadThe flow format reference (benchmesh.flow/v1) with an example - what the client reads before writing a flow.
list_flowsreadSaved flows: id, name, description.
get_flowreadOne saved flow document.
validate_flowreadCheck a flow against this bench: errors and warnings with paths, and which steps can switch outputs on.
run_statusreadState of the current or last run with its log (events after after).
list_recordingsreadRecordings: id, name, state, start / stop time, series.
get_recordingreadSamples of a recording, at most max_points rows (default 500, 10-5000).
abort_runreadAbort the running flow now - its cleanup still runs and outputs it switched on are switched off. Allowed at read access: stopping is always safe.
set_instrumentcontrolCall one setter and wait until the instrument reports the value. Setters that can switch an output on need confirm_energize: true.
save_flowcontrolValidate and save a flow (new, or replacing id). Saving never runs it; the flow appears in Automation.
run_flowcontrolStart a saved flow (id) or a flow document, with optional params. Flows that can switch outputs on need arm: true.
continue_runcontrolContinue a run waiting at a prompt step.
start_recordingcontrolStart a recording of numeric status fields on the common time grid (name, series, interval_s 1-3600).
stop_recordingcontrolStop a recording.

Instrument tools take device (the id from bench_overview), class and channel (default 1). Status values come back as numbers in base units (V, A, W).

Setup

Claude Code

Terminal
claude mcp add --transport http benchmesh http://127.0.0.1:57666/mcp

Claude Desktop

Claude Desktop starts its servers as programs, so it uses BenchMesh’s stdio bridge: the BenchMesh executable started with --mcp opens no window and forwards the messages to the running app. Add this to Claude Desktop’s configuration (Settings → Developer → Edit Config, the file claude_desktop_config.json) and restart Claude Desktop:

claude_desktop_config.json
{
  "mcpServers": {
    "benchmesh": {
      "command": "<path to the BenchMesh executable>",
      "args": ["--mcp"]
    }
  }
}

Windows installs BenchMesh for your user; the path is usually the one below - the exact path for your computer is shown in Automation → Settings → MCP. Note the doubled backslashes in JSON.

Windows
{
  "mcpServers": {
    "benchmesh": {
      "command": "C:\\Users\\<you>\\AppData\\Local\\BenchMesh\\benchmesh.exe",
      "args": ["--mcp"]
    }
  }
}

Linux: the path of the AppImage file itself, wherever you keep it (it must be executable).

Linux AppImage
{
  "mcpServers": {
    "benchmesh": {
      "command": "/home/<you>/Applications/BenchMesh_<version>_amd64.AppImage",
      "args": ["--mcp"]
    }
  }
}

If BenchMesh is not running, the bridge answers every request with an error asking you to start the app.

Cursor and other HTTP clients

Clients that speak Streamable HTTP connect to the URL directly - for Cursor in ~/.cursor/mcp.json (or the project’s .cursor/mcp.json):

mcp.json
{
  "mcpServers": {
    "benchmesh": {
      "url": "http://127.0.0.1:57666/mcp"
    }
  }
}

Headless server

With benchmesh-server instead of the desktop app, the same bridge is benchmesh-server mcp; BENCHMESH_URL points it at the server (default http://127.0.0.1:57666):

stdio bridge to benchmesh-server
{
  "mcpServers": {
    "benchmesh": {
      "command": "benchmesh-server",
      "args": ["mcp"],
      "env": {"BENCHMESH_URL": "http://127.0.0.1:57666"}
    }
  }
}

Or try a tool by hand - any HTTP client without a browser Origin header works:

curl
curl -s http://127.0.0.1:57666/mcp -H 'content-type: application/json' \
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/call",
       "params": {"name": "read_instrument", "arguments": {"device": "psu-1", "class": "PSU", "field": "VOUT"}}}'

Safety

  • Read by default. A connected client can look, not touch, until you choose control.
  • Energising needs explicit agreement. Even at control, a setter that can switch an output or input on needs confirm_energize: true and a flow that does needs arm: true. The server tells clients to ask you before passing either; without it the call is refused.
  • Confirmed like the UI. set_instrument waits until the instrument reports the new value, and flows run with all of the flow safety rules - cleanup, safe state, bounded loops, one run at a time.
  • Stopping is always allowed: abort_run works at read access, and you can abort from the app at any time.
  • This computer only. The MCP endpoint is served on 127.0.0.1 only, by the desktop app and by benchmesh-server alike. Remote access (a browser on your local network, HTTPS with a password) never reaches it: AI clients get control only on the bench computer. The cross-site guard refuses requests from web pages of other sites - a page you visit cannot reach the endpoint through your browser, as the MCP specification requires.

Example conversations

“What is the PSU output right now?”

  • bench_overview - finds the supply and its live status
  • read_instrument {device: "psu-1", class: "PSU", field: "VOUT"} (and IOUT, OUTPUT) - answers with the measured voltage, current and whether the output is on

Access: read

“Write a flow that sweeps the load from 0 to 2 A in 100 mA steps and logs the DMM voltage. Save it but don’t run it.”

  • flow_format and bench_overview - learns the format and the load’s and DMM’s operations
  • validate_flow - checks the draft, fixes what is reported
  • save_flow - saves it; it appears in Automation, where you review, arm and run it

Access: control (save_flow); at read the client can validate and show you the flow to paste

“Record VOUT and IOUT for 10 minutes.”

  • start_recording {name, series: [PSU VOUT, PSU IOUT]} - the recording appears in BenchMesh → Recording
  • stop_recording after ten minutes - or, better, a flow with record start, a 600 s wait and record stop, so the app keeps the time

Access: control

“Abort the run.”

  • abort_run - waits are interrupted at once, the cleanup runs, outputs the run switched on are switched off
  • run_status - confirms the run ended as aborted

Access: read