Direct over the tailnet
The daemon binds streamable-HTTP on the local network (or the tailnet IP). Agents on the same tailnet dial it directly. Network membership is the auth boundary.
galois-edge exposes every connected instrument as a typed Model Context Protocol (MCP) tool. Point any MCP-capable agent at the daemon and it sees per-instrument typed tools (keithley_2400__source_voltage, siemens_s71200__read_holding_register, dps150__set_voltage) plus a small set of generic discovery, execute, sweep, and stream tools — same shape, same auth, same audit log as the gRPC surface.
The MCP listener is enabled by default. After install the daemon binds streamable-HTTP on 127.0.0.1:8767/mcp; tailnet members reach it at http://<edge>.tail-1234.ts.net:8767/mcp.
The agent ecosystem fragmented into vendor-specific tool-use schemas (Anthropic tool use, OpenAI function calling, LangChain tools, …). MCP is the one wire protocol every major framework now consumes: Anthropic’s mcp_servers API connector, OpenAI Agents SDK, Claude Desktop, Cursor, LangGraph, LlamaIndex. Implementing MCP once gets the daemon into all of them with no per-framework glue.
Three tool categories, all on the same endpoint:
| Category | Examples | Comes from |
|---|---|---|
| Static tools (always present, 13 in total) | list_instruments, get_capabilities, scan_instruments, list_profiles, get_status, execute_command, execute_sequence, send_scpi, start_sweep, get_sweep_status, stop_sweep, start_stream, stop_stream | Hardcoded in mcp/tools/ |
| Dynamic per-instrument tools | keithley_2400__source_voltage, keysight_34461a__measure_voltage_dc, siemens_s71200__read_holding_register | Generated at runtime from the matched profile’s command catalogue |
| Dynamic per-SDK tools | dps150_wrapper__set_voltage, digilent_dwf_wrapper__configure_oscilloscope | Generated from each sdk_wrappers/*.py module that declares MCP_TOOL_SPECS |
Agents typically lead with list_instruments + get_capabilities to discover what’s reachable, then call the typed per-instrument tools. The static execute_command is the universal escape hatch — it works against every matched instrument and is what you’d target if you didn’t want to enumerate dynamic tools first.
These aren’t generic MCP — they’re things the daemon does that most MCP servers don’t:
tools/list reflects every connected instrument with typed parameters, units, ranges, and is_dangerous flags pulled live from profile YAML. The agent doesn’t read a vendor manual to use a new oscilloscope — it reads the tool catalogue.notifications/tools/list_changed fires within ~2 s. The agent’s tool catalogue updates without a session restart. Unplug it, the per-instrument tools come back out.start_sweep returns a handle and the ramp continues on the daemon. start_stream maps each measurement point to an MCP notifications/progress event. An agent session can drop, hand off, or sleep without stranding hardware mid-ramp.There are two transports today:
Direct over the tailnet
The daemon binds streamable-HTTP on the local network (or the tailnet IP). Agents on the same tailnet dial it directly. Network membership is the auth boundary.
Through the cloud relay
https://cloud.galoislabs.ai/mcp/<edge_id> terminates streamable-HTTP at the cloud and tunnels JSON-RPC over the existing relay WebSocket. Per-call JWT scopes the tool surface.
Daemon side shipped (this release). Cloud side is in PR review — rolling out.
The daemon is identical in both cases. Phase 1 (direct) and Phase 2 (relay) are the same FastMCP server reached through different ingress.
The MCP server lands in three phases. Phases 1 and 2 (daemon side) and Phase 3 are all in this release; the cloud side of the relay path is in PR review.
| Phase | What it gives you | Status |
|---|---|---|
| Phase 1 — FastMCP server with static tool surface | 13 static tools at :8767/mcp, reachable on the tailnet | Shipped |
| Phase 2 — relay envelope + JWT validation (daemon side) | Daemon validates Galois-Caller-JWT against cached JWKS, enforces per-call ACL | Shipped (daemon); cloud termination at cloud.galoislabs.ai/mcp/<edge_id> is in PR review |
| Phase 3 — dynamic tools, streaming, typed SDK wrappers | Per-instrument typed tools, hot-plug tools/list_changed, real StreamMeasurement → progress notifications, typed SDK tools replacing opaque ProxySDKCall | Shipped |