{"id":"804ce8ee-69f5-4cb5-bad3-cd25cf696585","slug":"nygmeta-openlabai","kind":"mcp","name":"OpenLabAI","summary":"Natural language AI agents for lab robot control: no coding required. MCP servers for Opentrons OT-2, Hamilton, Cellario workcells, and Beckman Biomek. Built for wet lab scientists.","owner":"nygmeta","repoUrl":"https://github.com/nygmeta/OpenLabAI","license":"MIT","licenseTier":"permissive","trust":"community","stars":0,"match":null,"fewStars":true,"format":"mcp","createdAt":"2026-04-15T01:53:05.000Z","addedAt":"2026-10-14T05:16:09.517Z","logoUrl":"https://avatars.githubusercontent.com/u/60275456?u=eb6a31e7330e1267589bba0defc68169a50eacec&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["utilities"],"tags":[],"runtime":"binary","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-17T23:01:50.142Z","sample":false,"url":"https://conduits.dev/tools/nygmeta-openlabai","language":"Python","transports":["stdio"],"install":{},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# OpenLabAI\n\n**Natural language agents for lab robot control, built on the Model Context Protocol.**\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)\n[![Python 3.13+](https://img.shields.io/badge/python-3.13+-blue.svg)](https://www.python.org/)\n[![MCP](https://img.shields.io/badge/MCP-compatible-brightgreen.svg)](https://modelcontextprotocol.io)\n\nOpenLabAI exposes liquid handling instruments to an LLM agent as a small set of\nstructured tools, so a scientist can describe a protocol in plain English and get\na reviewable protocol file back. It does not give the agent raw hardware access,\nand it never moves a robot without a person explicitly approving that run.\n\n---\n\n## Project Status\n\n\n**Runs end to end today**\n\n- The OT-2 MCP server: reads the deck over the Opentrons HTTP API, reports run\n  status, homes the robot, generates protocols, and can upload and execute them\n  under an explicit approval gate. The read, status, home and generate tools have\n  been run against a physical OT-2. **The execution tools — `upload_protocol`,\n  `start_run`, `pause_run`, `resume_run`, `stop_run` — have not yet been run\n  against a physical OT-2.** They are written against the documented Opentrons\n  HTTP API and their refusal paths are tested, but no robot has executed a\n  protocol through them.\n- The Biomek FXP MCP server: reads deck and method variables over COM and\n  generates `.mth` method files. Generated files have been opened and validated\n  in Biomek Software on a real instrument.\n- The Hamilton MCP server: generates PyLabRobot protocols for a STAR/STARlet and\n  dry-runs them through PyLabRobot's chatterbox backend, which logs every command\n  instead of sending it to hardware. Verified in simulation. \n- The LIMS connector (`mcp_servers/lims_server.py`): reads worklists and sample\n  concentrations from a laboratory information management system and writes run\n  records back. Profiles for Benchling, LabWare, STARLIMS, LabVantage, Thermo\n  SampleManager and RETISOFT Genera. Exercised against the mock profile only; not\n  yet connected to a production LIMS.\n- The Slack control surface (`integrations/slack_bot.py`): a scientist requests a\n  protocol in Slack, the agent plans and validates it, and a named person presses\n  Approve before anything moves. Tested offline; not yet run in a live workspace.\n- The benchtop device layer (`mcp_servers/device_server.py`): nine simulated\n  instruments across eight classes — two plate readers, a heat sealer, a seal\n  peeler, a plate centrifuge, a shaking incubator, a thermal cycler, a barcode\n  reader and a plate hotel. Devices describe themselves through a manifest of\n  states and procedures and are reached through three primitives, so adding an\n  instrument is a driver file rather than new agent instructions. Simulated only;\n  no driver contacts hardware.\n- Workcell orchestration (`integrations/workcell.py`): sequences a whole\n  experiment across instruments, the LIMS, a human, and a teleoperated humanoid.\n  Plans the entire run — including which steps will stop for approval — before\n  anything moves.\n- The teleoperation layer (`teleop/`, `mcp_servers/teleop_server.py`,\n  `integrations/teleop_bridge.py`): validated rig configuration, a ten-item\n  pre-session safety checklist, and a session state machine that refuses to bring\n  the robot to standing until its support frame is confirmed and refuses to hand\n  over control without a named operator and verified hand tracking. The agent can\n  observe a session, request work, and stop the robot; it can never drive it.\n  The control loop is Unitree's xr_teleoperate and the operator console is a\n  separate application; neither is vendored here.\n- The eval framework (`evals/`): deck constraint checking, acceptance criteria\n  per protocol type, scoring, run logging with a protocol hash, and a test suite\n  (`python evals/test_criteria.py`, 32 checks), plus the Slack approval-flow\n  tests (`python integrations/test_slack_flow.py`, 12 checks).\n- The browser GUI (`gui/BiomekAgent.html`): a single HTML file, no install.\n\n**Partial**\n\n- The Cellario MCP server: the four tools are implemented against the\n  `CellarioAutomation.Application` COM interface, but this connector has only\n  been exercised in mock mode. It has not been run against a physical workcell.\n- The Hamilton connector is simulation-verified only, as above. A live connection\n  additionally needs Windows, USB, and the libusbK driver, none of which has been\n  exercised.\n\n**Planned, not built**\n\n- Tecan Freedom EVO connector.\n- Conformance with Anthropic's Model Hardware Standard. The specification is not\n  published — access is by application to a research preview — so no conformance\n  is claimed. The device layer is built on MHS's publicly described model so that\n  adopting the schema, when published, is a mapping exercise rather than a\n  rewrite. See `docs/MHS_INTEROP.md`.\n- The `resources/` labware library. `protocols/` is created at runtime as the\n  output directory for `create_protocol()`.\n\n## Safety and Control\n\nThe architecture deliberately puts four barriers between an agent and a moving\nrobot. This is the part of the design that matters most.\n\n**1. Instruments are exposed as structured tools, not raw hardware access.**\nEach server publishes a small, fixed set of MCP tools with explicit JSON\nschemas — `read_deck`, `get_run_status`, `create_protocol`, and so on. The agent\ncannot issue arbitrary commands, open a socket to the instrument, or reach the\nCOM object directly. Anything not on the tool list is not reachable. The full\ninventory is 9 tools for the OT-2, 4 for Hamilton, 3 for the Biomek FXP, 4 for\nCellario, 5 for the LIMS connector, and 5 for the benchtop device server, which\ncovers nine instruments through one manifest-driven surface.\n\n**2. Protocols are validated before execution.**\n`evals/protocol_evals.py` checks a generated protocol against per-instrument\ndeck constraints (volume limits per tip type, valid slot and position names, tip\navailability) and against acceptance criteria for the protocol type (required\nsteps, bead ratios, wash cycles, elution volume ranges). It returns a score, a\npass/fail, and an explicit list of violations.\n\n**3. A human approves before anything physical happens.**\nThe OT-2 server can execute protocols, and the approval gate is where that is\nmade safe. `upload_protocol` talks to the robot but moves nothing: it uploads the\nfile, waits for the robot's own protocol analysis, and creates a run that sits\nidle. `start_run` is the only tool that begins motion, and it refuses unless\n`confirm=true` is passed — which represents a person's approval of that specific\nprotocol — and refuses again if the robot's analysis reported errors or if the\nprotocol fails the deck constraint checks. `stop_run` is deliberately never\ngated, because stopping is the safe direction. Writes to the LIMS are gated the\nsame way, because they change the laboratory's system of record. When the gate is\npresented in Slack it is still the same gate: a protocol that fails validation\ncannot be approved, and the approver's identity is recorded. The Biomek, Cellario and Hamilton\nservers execute nothing at all: they write files a person runs through the vendor\nsoftware, and the Hamilton server's `simulate_protocol` uses PyLabRobot's\nchatterbox backend, which never contacts hardware.\n\n**4. Every run is logged.**\n`evals/run_logger.py` writes a JSON audit record per run: operator, instrument,\nprotocol name, a SHA-256 hash of the protocol, eval score, generation method,\nper-step start and completion timestamps, status, and errors. Intended for\nGxP-adjacent environments where traceability is a requirement.\n\n---\n\n## The Problem\n\nIn the labs I have worked in, one automation engineer supports somewhere between\ntwenty and thirty scientists. Every new liquid handling method goes through that\none person, and scientists wait days or weeks. This ratio is my own observation\nfrom several years at Guardant Health, Personalis, and Hexagon Bio; I am not aware of\na published survey establishing it as an industry-wide figure.\n\nPyLabRobot ([Wierenga et al., 2023](https://doi.org/10.1101/2023.07.10.547733))\nand Pioneer Labs ([ngs_library_prep](https://github.com/Pioneer-Research-Labs/ngs_library_prep))\nreplaced proprietary vendor software with Python, which removes the vendor lock-in\nbottleneck. OpenLabAI is aimed at the next one: the scientist still has to know\nPython. It adds a conversational layer on top, so the scientist describes the\nexperiment and reviews a generated protocol instead of writing one.\n\n---\n\n## Supported Instruments\n\nStatus values mean: **Implemented** — the tools work and have been run against a\nphysical instrument. **Partial** — the code is written but has only run in mock\nmode. **Planned** — not built.\n\n| Instrument | Status | Interface | What is implemented | What is not |\n|---|---|---|---|---|\n| Opentrons OT-2 | Implemented — partly verified on hardware | Opentrons HTTP API, port 31950 | `read_deck`, `get_run_status`, `home_robot`, `create_protocol` (Opentrons API and PyLabRobot formats), plus `upload_protocol`, `start_run`, `pause_run`, `resume_run`, `stop_run`. Read, status, home and generate have run against a physical OT-2. | The execution tools have not been run against a physical OT-2. Their refusal paths are tested; the successful-run path is not hardware-verified. |\n| Beckman Biomek FXP | Implemented — verified on hardware | COM (`BiomekFX.Application`), Windows | `read_deck`, `get_variables`, `create_protocol` writing `.mth` XML. Generated methods opened and validated in Biomek Software. | No runtime execution — the FXP exposes no runtime API in its standard configuration. Methods are run manually. |\n| Hamilton STAR/STARlet | Partial — simulation only | PyLabRobot STAR backend | `read_deck`, `get_status`, `create_protocol`, `simulate_protocol`. Generated protocols dry-run through PyLabRobot's chatterbox backend. | Never connected to a physical Hamilton. No execution tool. A live connection needs Windows, USB and the libusbK driver, none of it exercised. |\n| Cellario workcells | Partial — mock mode only | COM (`CellarioAutomation.Application`), Windows | `schedule_run`, `get_device_status`, `query_queue`, `get_batch_list` are written against the documented COM interface. | Not yet run against a physical workcell. All results to date are from the mock responder. |\n| Tecan Freedom EVO | Planned | PyLabRobot | Nothing. | Everything. |\n\nEvery server falls back to mock mode when its instrument is unreachable, and\nlabels the response `\"mode\": \"mock\"`. Mock output is for development and training\nonly; it is not evidence that a connector works on hardware.\n\n---\n\n## Quick Start\n\n### Option 1: the browser GUI, no installation\n\nDownload [`gui/BiomekAgent.html`](gui/BiomekAgent.html), open it in Chrome, and\npaste in a Claude API key. No Python, no terminal.\n\n### Option 2: the MCP servers\n\n**Requirements:** Python 3.13+, pip. The Cellario and Biomek servers need\nWindows for COM; they start on macOS and Linux but run in mock mode only.\n\n```bash\ngit clone https://github.com/nygmeta/OpenLabAI.git\ncd OpenLabAI\npip install -r requirements.txt\n```\n\nRun the server for your instrument, from the repository root:\n\n```bash\npython mcp_servers/ot2_server.py --host 169.254.10.10   # Opentrons OT-2\npython mcp_servers/hamilton_server.py --deck starlet    # Hamilton STAR/STARlet\npython mcp_servers/biomek_server.py                     # Beckman Biomek FXP\npython mcp_servers/cellario_server.py                   # Cellario (Windows)\npython mcp_servers/lims_server.py --lims labware \\\n       --base-url https://lims.example.org               # LIMS (see docs/LIMS_AND_SLACK.md)\npython mcp_servers/device_server.py                     # Benchtop devices, all simulated\npython mcp_servers/teleop_server.py --arm G1_29 --ee inspire1   # Humanoid session\n```\n\nTo sequence a whole experiment across instruments, a human, and the humanoid:\n\n```bash\npython integrations/workcell.py --demo                  # plan only, nothing moves\npython integrations/workcell.py --demo --approve        # run it through\n```\n\nTo drive protocols from Slack instead of a terminal:\n\n```bash\npython integrations/slack_bot.py --dry-run              # no Slack, no robot\npython integrations/slack_bot.py --instrument Hamilton_STAR --require-second-person\n```\n\nThe OT-2 server takes the deck it should generate protocols for, and the operator\nname recorded in the audit log:\n\n```bash\npython mcp_servers/ot2_server.py --host 169.254.10.10 \\\n  --pipette p1000_single_gen2 --mount right \\\n  --tiprack opentrons_96_tiprack_1000ul --operator \"your name\"\n```\n\nEach server speaks MCP over stdio, so it will appear to hang when run directly —\nthat is a server waiting for a client on stdin, not a failure. Point Claude\nDesktop at it by adding to `claude_desktop_config.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"openlab\": {\n      \"command\": \"python\",\n      \"args\": [\"/path/to/OpenLabAI/mcp_servers/ot2_server.py\", \"--host\", \"169.254.10.10\"]\n    }\n  }\n}\n```\n\nThe config file lives at `%APPDATA%\\Claude\\claude_desktop_config.json` on Windows\nand `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS.\n\nThen, in Claude Desktop:\n\n```\nRead my OT-2 deck and tell me what is loaded\n```\n```\nPlan an AMPure bead cleanup: 1.8x beads, 2x 80% ethanol wash, elute in 20 µL EB\n```\n\nThe agent returns a plan and writes a protocol file to `protocols/`. To run it:\n\n```\nUpload that protocol to the robot and tell me what the analysis says\n```\n\n`upload_protocol` sends the file, waits for the robot's own analysis, and creates\na run that sits idle — nothing moves. Review the protocol, then approve it\nexplicitly:\n\n```\nI have reviewed it. Start the run.\n```\n\nThe agent calls `start_run` with `confirm=true`. It will refuse if the robot's\nanalysis reported errors, or if the protocol fails the deck constraint checks.\n`stop_run` is never gated.\n\n---\n\n## Repository Structure\n\n```\nOpenLabAI/\n├── gui/\n│   └── BiomekAgent.html          # Standalone web GUI — open in Chrome, no install\n├── mcp_servers/\n│   ├── ot2_server.py             # Opentrons OT-2 (HTTP API, can execute)\n│   ├── hamilton_server.py        # Hamilton STAR/STARlet (PyLabRobot, simulation)\n│   ├── biomek_server.py          # Beckman Biomek FXP (Windows COM, file-based)\n│   └── cellario_server.py        # Cellario workcells (Windows COM)\n├── evals/\n│   ├── protocol_evals.py         # Deck constraints, acceptance criteria, scoring\n│   ├── run_logger.py             # Audit trail and run logging\n│   └── test_criteria.py          # Tests for criteria matching and score ranges\n├── examples/\n│   ├── ngs_cleanup_example.md    # Step-by-step walkthrough\n│   └── slas_boston_case_study.md # SLAS 2026 Boston live demo case study\n├── docs/\n│   ├── INSTRUMENT_GUIDE.md       # How to connect each instrument\n│   ├── LIMS_AND_SLACK.md         # LIMS profiles and the Slack approval flow\n│   ├── HUMANOID_TELEOP.md        # The Unitree G1, and why the agent cannot drive it\n│   ├── MHS_INTEROP.md            # Model Hardware Standard alignment, and its limits\n│   └── SCIENTIST_GUIDE.md        # For scientists with no coding background\n├── requirements.txt\n├── LICENSE\n└── README.md\n```\n\n`protocols/` is not checked in. It is created at runtime by `create_protocol()`\nas the output directory for generated protocol files.\n\n---\n\n## Eval Framework\n\n`evals/` validates AI-generated protocols before a human is asked to approve them.\n\n- **Deck constraint checker** — volume limits per tip type, valid slot and\n  position names, and tip availability, per instrument.\n- **Device-enforced limits** — benchtop instruments refuse an out-of-range value\n  themselves, before anything happens, so an agent cannot talk past a temperature\n  ceiling or a rotor speed. Limits are checked *before* the confirmation gate, so\n  an unsafe request is refused as unsafe even when a human confirms it.\n- **Acceptance criteria** — per protocol type (NGS cleanup, normalization, serial\n  dilution, simple transfer): required steps, bead ratio bounds, minimum wash\n  cycles, elution volume range. Step labels are matched by token and synonym, so\n  a criterion is satisfied by the wordings scientists actually use.\n- **Run logger** — operator, timestamp, per-step status, and SHA-256 protocol hash.\n\nRun the bundled example and the tests:\n\n```bash\npython evals/protocol_evals.py\npython evals/run_logger.py\npython evals/test_criteria.py                 # 32 checks\npython mcp_servers/devices/test_devices.py    # 25 checks\npython integrations/test_slack_flow.py        # 12 checks\npython integrations/test_workcell.py          # 18 checks\npython teleop/test_teleop.py                  # 23 checks\npython mcp_servers/mhs_bridge.py --verify     # architectural invariants\n```\n\nCriteria matching is token-based with synonyms, not literal substring matching,\nso ordinary wordings are recognised: \"Aspirate AMPure beads\" and \"Add 90 uL SPRI\nbeads to sample\" both satisfy the `aspirate_beads` criterion. It is not merely\npermissive — \"Aspirate 50 uL of sample\" does not satisfy it, and \"Wash with PBS\"\ndoes not satisfy `ethanol_wash`. `evals/test_criteria.py` covers both directions\nplus score-range and constraint checks, and exits non-zero on failure.\n\n```python\nfrom evals.protocol_evals import evaluate_protocol\n\nresult = evaluate_protocol(protocol, protocol_type=\"ngs_cleanup\", instrument=\"OT-2\")\nprint(result.overall_score)   # float in 0.0–1.0\nprint(result.passed)          # True when acceptance passes and score >= 0.80\nprint(result.protocol_hash)   # first 16 hex chars of the SHA-256 protocol hash\n```\n\nScores depend entirely on the protocol you pass in. No benchmark figure is\nclaimed here, because no benchmark has been run.\n\n---\n\n## How It Works\n\n```\nScientist (plain English)\n        ↓\nClaude agent (protocol planning)\n        ↓\nMCP server (structured tools: read_deck, create_protocol, upload_protocol, ...)\n        ↓\nOpentrons HTTP API  /  PyLabRobot  /  Windows COM  /  .mth file output\n        ↓\nRobot analysis + deck constraint checks\n        ↓\nHuman approval (confirm=true)  →  physical robot\n        ↓\nAudit log\n```\n\nThe design borrows the generate-several-candidates-and-select idea from\nScattered Forest Search ([Light et al., 2024](https://codespace-optimization.github.io/)),\nwhich reports its own results on code generation benchmarks. Those results are\nfor code generation, not laboratory protocols, and no equivalent measurement has\nbeen made for OpenLabAI. Any first-attempt validity rate for protocol generation\nwould need its own benchmark, which has not been run.\n\n---\n\n## Contributing\n\nContributions welcome, especially from wet lab scientists who can say what is\nmissing.\n\n- **Found a bug?** Open a GitHub issue.\n- **New instrument backend?** Open a PR adding a server under `mcp_servers/`.\n  Tecan is the remaining gap; the Hamilton connector needs someone with physical\n  hardware to verify it.\n- **Protocol templates or labware definitions?** Open an issue first — there is\n  no library structure yet and it is worth agreeing on one.\n\n---\n\n## References\n\nIf you use OpenLabAI, please link to this repository. There is no paper to cite.\n\nThis work builds on:\n\n- [PyLabRobot](https://github.com/PyLabRobot/pylabrobot) — Wierenga, Golas, Ho and\n  Coley, 2023. [doi:10.1101/2023.07.10.547733](https://doi.org/10.1101/2023.07.10.547733)\n- [Scattered Forest Search](https://codespace-optimization.github.io/) — Light et al., 2024\n- [Pioneer Labs NGS library prep](https://github.com/Pioneer-Research-Labs/ngs_library_prep)\n\n---\n\n## About\n\nBuilt by **Ainur Nygmet** at ZenoVistaAI Inc.\n\nSeveral years as a lab automation engineer at Guardant Health, Personalis, and\nHexagon Bio: 50+ Hamilton methods developed, 40+ scientists trained on lab\nautomation, certified Cellario operator. DDemonstrated live humanoid teleoperation for laboratory work at the SLAS 2026 International Conference and Exhibition in Boston, February 2026 International Conference and Exhibition in Boston,\nFebruary 2026 — see [examples/slas_boston_case_study.md](examples/slas_boston_case_study.md).\n\nThis project exists because I was the bottleneck.\n\n**Contact:** nygmetainur@gmail.com ·\n[LinkedIn](https://linkedin.com/in/nygmetainur) ·\n[GitHub](https://github.com/nygmeta)\n\n---\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n"}