Specification · section 9

Transports and discovery

MHP defines two transports, mirroring MCP:

Network discovery. Servers SHOULD advertise via mDNS/DNS-SD as _mhp._tcp with TXT records id, class, path=/mhp.json; the reference HTTP transport does so when the optional zeroconf package is installed. Clients discover devices two ways, and SHOULD use both: browse _mhp._tcp, and probe GET /mhp.json on candidate hosts across the conventional port range (18900 to 18939), which works on networks that block multicast. Labs MAY additionally run a directory (§3.2).

9.1 The fleet and mhp_lab

A host keeps a fleet: the list of devices it knows, persisted as ~/.openmhp/fleet.json, each entry an id, a target and the device's card. Device packages the host owns are hosted in-process from ~/.openmhp/devices/<id>/, so a scientist's laptop needs no separate device servers for them. The bridge exposes the fleet through one tool, mhp_lab, with these operations:

op Effect
status how many devices the lab has and what to do next; the agent's starting point
scan mDNS browse plus HTTP probe of localhost and any hosts given; returns devices not yet in the fleet
add register a target (http://host:port, a package folder, or a package id under ~/.openmhp/devices); fetches the card; the device is immediately searchable; an id already in the lab at a different target is refused
onboard a guided interview run by the server: returns the next questions (ask, in plain words for the human) and the shape of the answer; on completion the server writes DEVICE.md, descriptor.yaml and driver.py, validates, and asks the agent to add
new create a package skeleton for an instrument that does not speak MHP yet (for agents that prefer to write files themselves)
write write files (DEVICE.md, descriptor.yaml, driver.py, references, scripts) into that package; paths may not escape it
validate run the package validator
recipes search tested procedures (§3.4)
registry search known community packages; add one with add target="github:owner/repo/path"
safety_card a readable review of a device before first use: enforced limits, gated actions, e-stop, watchdog, validator findings, and live probes (every action dry-run, an out-of-range write on every bounded setting)
events what happened since a sequence number (§3.5)
remove, reload remove refuses a device with active jobs unless force; both drop the device's connection, directory entry and in-process driver. reload loads a package again after its files changed; a changed package is never silently reused
location record where an installed instrument stands; the lab's fleet record, not the package, is the authority
release hand the bridge session's leases back
list, home membership and paths

add accepts sim=true to register a package's simulated twin (sim.py, declared as sim: in the frontmatter) under <id>-sim, so protocols can be rehearsed with nothing plugged in. The bundled devices and the community packages all ship one. Onboarding (onboard) ends with a safety card the agent reads back to the owner; an agent that has the instrument's manual SHOULD submit everything the manual states in one answers call and ask the human only to confirm the limits.

The bridge also declares MCP instructions on initialize, so a harness with no skills support still receives the operating loop and the setup path, and three MCP prompts (setup-my-lab, add-instrument, run-experiment) that harnesses surface as slash commands.

No-code drivers. The interview asks how the instrument is controlled today and picks a driver kind. manual wraps an instrument a person operates: a setting write is a request the operator carries out, reads return only what a person reported, each action waits in waiting_operator until a person acknowledges it, and both acknowledge and record need a person's confirmation. A manual device never claims an automatic e-stop or a watchdog. It can take part in protocols now and swap in a real driver later by changing one file. serial is a declarative driver for instruments with text commands over a serial or USB port: the owner pastes the commands from the manual into descriptor.yaml under serial: (read, write, actions, estop), and openmhp.drivers.serial_ascii does the rest; boolean replies must match known tokens exactly, and anything else counts as unreadable. mhp means the instrument already has an address and is simply added. adapter collects the interview and leaves driver.py for the fleet skill. In all kinds the descriptor, gates and levels are the same.

This is how a scientist adds an instrument without leaving the conversation: "find the instruments on my network" → scan → "add the thermocycler" → add. For an instrument that has no MHP server, the openmhp-onboard-device skill interviews the owner, and the agent writes the package with new, write and validate, then adds it. The npx openmhp-cli launcher installs the runtime, the skills and the harness registration in one command.

Authentication. The device HTTP transport has none in this draft: run it on a trusted network, or behind TLS with authentication. The MCP bridge's HTTP endpoint (mhp-mcp --http) exposes script execution and hardware control, so it requires a bearer token (OPENMHP_HTTP_TOKEN, or a generated ~/.openmhp/http_token), refuses requests whose Origin is not explicitly allowed (--allow-origin), and on a loopback bind refuses Host headers other than localhost. It has no server-initiated requests, so confirm-gated operations are unavailable over it. The protocol reserves params.auth for a future in-band scheme.