MCP server exposing a QEMU instance's QMP socket and serial console
Three well-defined tools with complete schemas, clear descriptions, and proper parameter documentation. Tool names follow verb_noun convention (execute_qmp, read_serial, write_serial). Descriptions are detailed (194 - 392 chars, within baseline 34 - 392 range) and explain WHAT, WHEN, and HOW. All parameters have types and descriptions. Input schemas use schemars JsonSchema with proper type definitions. However, output schemas are not explicitly documented in the tool definitions, responses are inferred from CallToolResult. Error handling is present but minimal; no recovery guidance or error categorization. No tool annotations (readOnlyHint/destructiveHint) despite clear risk levels (WRITE vs READ_ONLY). Doctests in code demonstrate parameter usage, which aids clarity.
Execute a QMP command on the QEMU instance listening on the local QMP unix socket (default /tmp/qmp-sock, override with the QMP_SOCKET_PATH environment variable). Any QMP command passes through, e.g. `query-status`, `stop`, `cont`, `eject`, `query-block`. `qmp_command` is the command name and `qmp_arguments` is an optional JSON object with its arguments (e.g. {"device": "ide-cd0"} for `eject`).
Read pending output from the guest's serial console, connected to the local unix socket (default /tmp/serial-sock, override with the SERIAL_SOCKET_PATH environment variable; launch QEMU with e.g. `-serial unix:/tmp/serial-sock,server,nowait`). The server stays connected in the background and buffers everything the guest prints between calls, so nothing is lost while no read is in flight. With `wait_for`, keeps polling until the substring appears in the output or `timeout_ms` (default 5000) elapses. Without `wait_for`, returns the buffered output immediately (possibly empty). Output is returned as lossy UTF-8, capped at `max_chars` (default 4000) from the end of the buffer; pass `clear` to discard it after reading.
Write data to the guest's serial console (simulate typing into its UART over the same unix socket as `read_serial`). A newline is appended unless `newline` is false. Combine with `read_serial` (`wait_for` on an expected prompt) to drive interactive guest programs.
Output schemas not documented. Tool descriptions do not specify what fields are returned or their types. LLMs cannot plan downstream calls or extract data reliably.
No tool annotations (readOnlyHint/destructiveHint/idempotentHint). execute_qmp and write_serial are marked WRITE but lack destructiveHint annotation; read_serial is READ_ONLY but lacks readOnlyHint. Agents cannot infer safety properties.
Error handling lacks recovery guidance. Errors are returned via McpError but do not include actionable next steps (e.g., 'socket not found, ensure QEMU is running and QMP_SOCKET_PATH is set').
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 66 | 2026-07-28+ | v2 |
read_serial timeout and polling behavior not fully specified in description. Default timeout_ms=5000 and poll interval=50ms are hardcoded; LLMs cannot predict latency or adjust expectations.
No idempotency guarantees documented. execute_qmp and write_serial may have side effects; unclear if retries are safe or risk duplicate operations (e.g., double eject, double command).