a73x

MCP has no host_list: the fleet is only visible through error messages

open   by a73x

Labels: backlog

[claude 2026-09-01] The /mcp tool surface exposes 14 tools (`internal/mcpserver/server.go:57`) and not one of them lists hosts. A model driving eitri over MCP cannot answer "what hosts are there, which are online, what networks do they advertise, what agent version do they run" — it can only place a VM and find out.

The data is already on the interface. `toolsAPI.ListHosts` (`internal/mcpserver/tools.go:26`) is called by `FirstEligibleHost` for default placement and by `resolveHost` when the caller names a host, and `describeHosts`/`describeHostNetworks` (tools.go:415,430) already render a fleet summary for humans — but only inside *error* strings. Today the only way for a model to learn the host names is to guess one wrong and read the 400, or to ask for a network nobody advertises and read the "online hosts advertise: ..." line. Discovery-by-failure.

Where it bites:
- `vm_create` takes `host` ("host name to place on; default first eligible host", tools.go:172) with no way to enumerate the legal values.
- Named networks: picking a network requires knowing which host advertises it. That is exactly what `describeHostNetworks` renders into an error.
- Placement is manual and permanent — `e698610c` (VMs cannot move between hosts) means the host choice at create is the final one. Choosing it blind is a poor trade.
- Volumes (branch `volumes`, unmerged) makes this sharper: a bound claim pins its host, and a volume-bearing create on the wrong host is a 409. A model that cannot see hosts cannot see where its data lives.

Suggested shape — `host_list`, read-only, mirroring `vm_list`: id, name, online, agent_version, host_networks, and whether it is placeable (the `placeable` predicate at tools.go:87 is the existing rule). Consider surfacing capacity too if it is cheap, since it is the other thing a placement decision wants.

Note the console and CLI already show hosts; MCP is the surface that does not.