AgentStack
MCP verified MIT Self-run

Lablink Mcp

mcp-techmanual-ai-lablink-mcp · by techmanual-ai

Unified & extensible MCP server enabling AI agent connectivity to all types of lab equipment — VISA/SCPI, SSH, REST, serial, and Python environments.

No reviews yet
0 installs
4 views
0.0% view→install

Install

$ agentstack add mcp-techmanual-ai-lablink-mcp

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No issues found. Passed automated security review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures

What it can access

  • Network access Used
  • Filesystem access No
  • Shell / process execution Used
  • Environment & secrets No
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

Are you the author of Lablink Mcp? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

LabLink

Unified & extensible MCP server enabling connectivity to all types of lab equipment

Install · Quick Start · Tools · Configuration · CLI · Contributing


What is LabLink?

LabLink gives an AI agent direct, structured access to lab hardware and services — without a human in the loop. Connect by alias, send commands, read results, and iterate across any combination of devices in a single session.

  • 5 protocol drivers out of the box: VISA/SCPI, SSH, REST, serial, and a Python subprocess shell
  • Per-protocol tool names (visa_query, ssh_exec, rest_get) — no leaky one-size-fits-all interface
  • Install only what you need — drivers are optional extras; the server runs with zero installed
  • diagnose() surfaces exactly what is missing or unreachable before the agent tries to use it
  • Extensible — add a driver with no changes to the core server or CLI

Supported Protocols

Each device is addressed by an alias whose config type field selects the driver. Per-driver tools register only when that driver's dependencies are installed.

| Protocol | type | Transport | Operation tools | Extra | Hardware-validated | |----------|--------|-----------|-----------------|-------|:------------------:| | VISA / SCPI | visa | PyVISA (USB-TMC, TCPIP, GPIB, Serial) | visa_query, visa_write | [visa] | ✅ | | SSH | ssh | Paramiko | ssh_exec, ssh_shell_session, ssh_start_stream, ssh_read_stream, ssh_stop_stream | [ssh] | ✅ | | REST | rest | httpx | rest_get, rest_post, rest_put, rest_patch, rest_delete | [rest] | ✅ | | Serial | serial | pyserial (RS232/RS422/RS485) | serial_query, serial_write, serial_read, serial_flush | [serial] | ⚪ | | Python shell | python_shell | subprocess REPL | python_shell_exec, python_shell_eval | [python_shell] | ✅ |

An external routing stub also lets a device be handled by a vendor-supplied MCP server, surfacing routing hints to the agent on connect().

> Legend — ✅ exercised end-to-end on real hardware · ⚪ covered by unit tests with the > driver library mocked (real use needs real hardware).


📦 Install

pip install lablink-mcp          # core only (no drivers)
pip install lablink-mcp[visa]    # + PyVISA
pip install lablink-mcp[ssh]     # + Paramiko
pip install lablink-mcp[all]     # all drivers

🚀 Quick Start

1. Create a device config

One TOML file per device at ~/.lablink/devices/.toml. The type field selects the driver.

VISA instrument:

# ~/.lablink/devices/tek_mso44.toml
type        = "visa"
alias       = "tek_mso44"
resource_string = "USB0::0x0699::0x0527::C012345::INSTR"
manufacturer = "Tektronix"
model_number = "MSO44"
timeout_ms  = 5000
description = "4-channel mixed signal oscilloscope"

Find your resource string:

python -c "import pyvisa; print(pyvisa.ResourceManager('@py').list_resources())"

SSH host:

# ~/.lablink/devices/rpi_dev.toml
type        = "ssh"
alias       = "rpi_dev"
host        = "192.168.1.42"
port        = 22
username    = "pi"
auth_type   = "ssh_key"
auth_ssh_key_path = "~/.ssh/id_rsa"
timeout_ms  = 10000

See [examples/configs/](examples/configs/) for templates for all drivers.

2. Verify with the CLI

lablink list                              # show all configured devices
lablink connect tek_mso44                 # open session, print identity
lablink visa query tek_mso44 "*IDN?"     # send SCPI query

3. Add to your MCP client

Claude Code — add to ~/.claude.json (global) or .mcp.json in your project root:

{
  "mcpServers": {
    "lablink-mcp": {
      "command": "lablink-mcp"
    }
  }
}

Claude Desktop — add to ~/Library/Application Support/Claude/claude_desktop_config.json:

{
  "mcpServers": {
    "lablink-mcp": {
      "command": "lablink-mcp"
    }
  }
}

MCP Tools

Shared lifecycle (all drivers)

| Tool | Description | |------|-------------| | connect(alias) | Open session, return identity, device memory, and topology slice | | disconnect(alias) | Close session | | list_devices() | List all configured aliases with status | | diagnose(alias?) | Reachability and dependency check; system audit (with topology warnings) when no alias given | | system_topology(alias?) | Return the bench wiring map; or a single device's slice |

Per-driver operation tools

| Driver | Tools | |--------|-------| | visa | visa_query, visa_write | | ssh | ssh_exec, ssh_shell_session, ssh_start_stream, ssh_read_stream, ssh_stop_stream | | rest | rest_get, rest_post, rest_put, rest_patch, rest_delete | | serial | serial_query, serial_write, serial_read, serial_flush | | python_shell | python_shell_exec, python_shell_eval |

Per-driver tools are only registered when that driver's dependencies are installed. All tools return structured dicts. On failure:

{"success": false, "error": "VISA timeout", "hint": "Check that the instrument is powered on."}

Device Configuration

One TOML file per device at ~/.lablink/devices/.toml. Override the directory:

export LABLINK_CONFIG_DIR=/path/to/devices/

Base fields (all drivers)

| Field | Required | Description | |-------|----------|-------------| | type | yes | Driver: visa, ssh, rest, serial, python_shell | | alias | yes | Must match the filename (e.g. tek_mso44.tomlalias = "tek_mso44") | | timeout_ms | yes | Default communication timeout in milliseconds | | description | no | Shown in lablink list output |

Per-driver extras

See [examples/configs/](examples/configs/) for complete templates.

VISA — adds resource_string, manufacturer, model_number, read_termination, write_termination, techmanual_document_ids

SSH — adds host, port, username, auth fields (auth_type, auth_ssh_key_path, auth_token_env, etc.)

REST — adds base_url, auth fields

Serial — adds serial_port, baud_rate, data_bits, parity, stop_bits, read_termination, write_termination

python_shell — adds python_path (path to interpreter), working_dir

Credentials are always referenced by environment variable name — never stored in config files directly.


CLI Reference

The CLI mirrors the MCP tool surface for development and debugging.

lablink list                                    # list all configured devices
lablink diagnose                                # system dep check (all drivers)
lablink diagnose tek_mso44                      # device-specific reachability check
lablink connect tek_mso44                       # open session, print identity
lablink disconnect tek_mso44                    # close session

lablink visa query tek_mso44 "*IDN?"            # SCPI query
lablink visa write tek_mso44 "CH1:SCALE 0.5"   # SCPI write

lablink ssh exec rpi_dev "uname -a"             # run SSH command

lablink rest get my_api /status                 # HTTP GET
lablink rest post my_api /jobs --body '{"n":1}' # HTTP POST

lablink serial query my_device "MEAS?"          # serial write + read

Per-protocol commands appear only when that driver's deps are installed.


VISA Troubleshooting

list_resources() returns an empty tuple ()

  • Confirm the instrument is powered on and the cable is connected.
  • For USB instruments on macOS, check System Settings → Privacy & Security → USB.
  • For USB instruments on Windows, pyvisa-py requires libusb. Install via pip install libusb-package.
  • For GPIB instruments, pyvisa-py has limited GPIB support — consider NI-VISA.

VISA timeout on connect or query

  • Increase timeout_ms in your instrument config.
  • Confirm no other software (e.g. NI MAX, Keysight Connection Expert) has the port locked.

VISA Backend

LabLink uses pyvisa-py by default — a pure-Python implementation with no additional software required.

To use NI-VISA instead (e.g. for GPIB or if you already have it installed):

export LABLINK_VISA_BACKEND=@ni

Using with techmanual.ai (optional)

techmanual.ai is a searchable index of technical manuals for T&M equipment. When both MCP servers are loaded, your agent can look up SCPI commands and execute them without human intervention.

Add techmanual_document_ids to your VISA config to enable targeted lookups:

techmanual_document_ids = [1291, 1323]   # user manual, programming guide

When this field is set, connect() returns the IDs so the agent can fetch relevant pages without a search query.


Control your home (Home Assistant)

Home Assistant is a local-first, open-source smart-home hub. It unifies thousands of devices across ecosystems — Apple Home, Alexa, Google, Zigbee, Z-Wave, Matter — behind one local REST API. That means LabLink's existing rest driver drives your whole home through a single alias; no extra driver to install.

Create a Long-Lived Access Token in Home Assistant (Profile → Security → Long-Lived Access Tokens), export it, and point a REST config at your hub:

# ~/.lablink/devices/home_assistant.toml
type        = "rest"
alias       = "home_assistant"
timeout_ms  = 10000
base_url    = "http://homeassistant.local:8123/api"
auth_type      = "bearer"
auth_token_env = "HASS_TOKEN"          # export HASS_TOKEN=

Then your agent can read and command anything HA manages:

lablink rest get  home_assistant /states                 # every entity's state
lablink rest post home_assistant /services/light/turn_on --body '{"entity_id": "light.kitchen"}'

See [examples/configs/resthomeassistant.toml](examples/configs/resthomeassistant.toml) for the full template.


Scope

LabLink ships five protocol drivers — visa, ssh, rest, serial, and python_shell — on a shared multi-driver dispatch core. (An external routing stub also lets a device be handled by a vendor-supplied MCP server.) GPIB is covered by visa through PyVISA; RS232/RS422/RS485 are electrical variants of the one serial driver.

Deliberately out of scope:

  • No server component. LabLink runs on your local machine. There is no cloud

deployment or hosted endpoint.

  • No instrument simulation. Tests mock the driver libraries; real use needs

real hardware.

  • No GUI. The CLI is the only interface beyond MCP.
  • Not a protocol library. LabLink sends commands and returns responses; it

does not parse or interpret SCPI or any other protocol syntax. That knowledge lives in the agent or in techmanual.ai.

  • Docker is not a primary install target. USB/serial passthrough into

containers defeats the point of local lab use.

Streaming-first protocols (MQTT, WebSocket) and others (Modbus, OPC-UA, CAN, …) are considered case-by-case as demand surfaces.


Architecture & Contributing

See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the data models, driver contract, dispatch model, and a step-by-step guide to adding a new driver. Adding a driver requires no changes to lablink/mcp_server.py or lablink/cli.py — just a new lablink/interfaces// package and one line in each registry.

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) to get started.


Running Tests

pip install -e ".[dev]"
pytest tests/

All tests mock hardware drivers — no real instruments required.


Mapping your system (optional)

Create ~/.lablink/topology.toml to give the agent a machine-readable map of how your bench is physically wired — which ports connect to which, what signals flow, and what safety limits apply.

# ~/.lablink/topology.toml
name = "rf_bench"

[[node]]
alias = "siglent_sdg6022"
role  = "signal generator"
[[node]]
alias = "tek_mso44"
role  = "oscilloscope"
[[node]]
id    = "pad_10db"          # passive gear: no alias needed
role  = "10 dB attenuator"

[[link]]
from   = "siglent_sdg6022:OUTPUT1"
to     = "pad_10db:IN"
signal = "stimulus"
params = { impedance_ohm = 50 }

[[link]]
from   = "pad_10db:OUT"
to     = "tek_mso44:CH1"
signal = "stimulus (attenuated)"

[[link]]
from   = "keysight_e36313:CH1"
to     = "dut_serial:12V_IN"
signal = "DC power"
  [[link.constraint]]
  severity = "critical"
  limit    = "voltage <= 13.5"
  note     = "DUT is damaged above 13.5 V on 12V_IN."

Call system_topology() to retrieve the full map, or system_topology(alias) to get one device's wiring slice. connect() and diagnose(alias) also inject the slice automatically as topology_context.

Constraints are advisory only. LabLink surfaces severity / limit / note to the agent; it does not and cannot enforce them (it does not parse protocol syntax). The agent is responsible for honoring limits.

Validate the file with:

lablink topology validate
lablink topology show               # full map
lablink topology show tek_mso44     # one device's slice

See [examples/topology.toml](examples/topology.toml) for a full annotated example.

Override the default path:

export LABLINK_TOPOLOGY_FILE=/path/to/topology.toml

Environment Variables

| Variable | Default | Purpose | |----------|---------|---------| | LABLINK_CONFIG_DIR | ~/.lablink/devices/ | Device config directory | | LABLINK_TOPOLOGY_FILE | ~/.lablink/topology.toml | System topology file (independent of LABLINK_CONFIG_DIR) | | LABLINK_VISA_BACKEND | @py | pyvisa backend (@py or @ni) | | LABLINK_LOG_DIR | ~/.lablink/logs/ | Event log directory; set to "" to disable | | TMAI_API_KEY | — | techmanual.ai API key for agent-directed manual lookups |


License

LabLink is released under the [MIT License](LICENSE).

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.0 Imported from the upstream source.