11 Downloads
11 Downloads
A lightweight LM Studio Plugin that wraps the original qemu-mcp-server (Rust) into a native LM Studio tool plugin.
qemu-mcp brings QEMU virtual machine control directly into LM Studio conversations. It exposes the same
Model Context Protocol (MCP) tools provided by the upstream qemu-mcp-server Rust project, wrapped in a
TypeScript layer that conforms to the LM Studio Plugin development guide v2.0.
The plugin ships a pre-built Rust binary (bin/qemu-mcp-server) so it works out of the box when
installed from the LM Studio Hub — no Rust toolchain or build step is required at install time.
The original Rust source tree is kept untouched in the ./qemu-mcp-server/ subdirectory (cloned on
demand by scripts/setup.cjs). This allows you to stay up to date with the original project by running
git pull --rebase inside ./qemu-mcp-server/ and rebuilding.
The plugin exposes three tools that map 1:1 to the upstream MCP server:
| Tool | Purpose |
|---|---|
execute_qmp | Execute a QMP command on the QEMU instance (e.g. query-status, stop, cont, eject). Any unknown command name is passed through to QEMU verbatim. |
read_serial | Read pending output from the guest's serial console. Supports waiting for a substring, timeouts, and character limits. The socket stays connected in the background and buffers output between calls. |
write_serial | Write data to the guest's serial console (simulate typing into the UART). Combine with read_serial to drive interactive guest programs. |
Note: LM Studio does not run
postinstallscripts for security reasons. The pre-built binary is shipped in the published package so the plugin works out of the box. If the binary is missing or corrupted, see the troubleshooting section below.
Prerequisite: Make sure
cargo(Rust toolchain) is installed and available in yourPATHbefore running the local setup.
The scripts/setup.cjs script performs the clone and build:
https://github.com/nagy/qemu-mcp-server into ./qemu-mcp-server/ (only on first run).git pull --rebase to update the source tree.cargo build --release.bin/qemu-mcp-server (overwriting the shipped pre-built artifact).To pull the latest changes from the original project and rebuild:
After installation, open the plugin settings in LM Studio to adjust the Unix socket paths if your QEMU instance uses locations other than the defaults:
| Setting | Default | Description |
|---|---|---|
| QMP Socket Path | /tmp/qmp-sock | Path to the QEMU QMP unix socket. |
| Serial Socket Path | /tmp/serial-sock | Path to the guest serial console unix socket. |
These correspond to the QMP_SOCKET_PATH and SERIAL_SOCKET_PATH environment variables used by the upstream
server.
execute_qmpExecutes a QMP command on the QEMU instance listening on the QMP unix socket. Convenience commands include
query-status, stop, cont, and eject. Any other command name is forwarded to QEMU as-is.
| Parameter | Type | Description |
|---|---|---|
qmp_command | string | QMP command name, e.g. query-status, stop, cont, eject. |
qmp_arguments | string | JSON object with the command's arguments (may be {}). |
Examples:
Query the VM status:
Eject the medium from the CD-ROM drive:
Stop the VM:
read_serialReads pending output from the guest's serial console. The socket stays connected in the background and buffers everything the guest prints between calls, so nothing is lost while no read is in flight. Output is returned as lossy UTF-8.
| Parameter | Type | Default | Description |
|---|---|---|---|
wait_for | string (optional) | — | Keep polling until this substring appears in the output. |
timeout_ms | number | 5000 | Give up waiting after this many milliseconds. |
max_chars | number (optional) | — | Return at most this many characters from the end of the buffer. |
clear | boolean | false | Discard the buffered output after returning it. |
write_serialWrites data to the guest's serial console, i.e. simulates typing into its UART.
| Parameter | Type | Default | Description |
|---|---|---|---|
data | string | — | Bytes to send to the guest serial port. |
newline | boolean | true | Append a newline after data. |
Treat this plugin as full remote control of the VM: it can pause and resume the machine, access or eject
drives, and interact with the guest's serial console. Anyone who can talk to the MCP server — or to the QMP or
serial socket itself — controls the VM. Use a per-user socket directory (e.g. under $XDG_RUNTIME_DIR) rather
than a world-writable /tmp path shared between users.
If the tools return errors about socket files not being found (e.g. failed to connect to QMP socket /tmp/qmp-sock), this is expected — it means the Rust binary is working correctly, but no QEMU instance
is running with the required QMP and serial sockets. Start QEMU with:
Or update the socket paths in the plugin settings (QMP Socket Path / Serial Socket Path).
This means the pre-built binary (bin/qemu-mcp-server) is missing or corrupted. Try:
qemu-mcp-server binary at .The shipped pre-built binary is compiled for Linux x86_64. If you are using macOS or Windows, you will need to build from source:
This project is a port of the original nagy/qemu-mcp-server repository. The porting approach:
We would like to express our gratitude to nagy and the contributors of the original qemu-mcp-server project for creating and maintaining the upstream Rust MCP server that makes QEMU interaction possible via the Model Context Protocol. This plugin would not exist without their work.
The original qemu-mcp-server Rust source tree (located in ./qemu-mcp-server/) is licensed under the
GNU Affero General Public License v3.0 or later (AGPL-3.0+) by nagy.
The TypeScript wrapper code written for this LM Studio plugin (everything outside ./qemu-mcp-server/) is
licensed under the MIT License (see the LICENSE file in this repository's root).
All third-party names and project names are the property of their respective owners.
A lightweight LM Studio Plugin that wraps the original qemu-mcp-server (Rust) into a native LM Studio tool plugin.
qemu-mcp brings QEMU virtual machine control directly into LM Studio conversations. It exposes the same
Model Context Protocol (MCP) tools provided by the upstream qemu-mcp-server Rust project, wrapped in a
TypeScript layer that conforms to the LM Studio Plugin development guide v2.0.
The plugin ships a pre-built Rust binary (bin/qemu-mcp-server) so it works out of the box when
installed from the LM Studio Hub — no Rust toolchain or build step is required at install time.
The original Rust source tree is kept untouched in the ./qemu-mcp-server/ subdirectory (cloned on
demand by scripts/setup.cjs). This allows you to stay up to date with the original project by running
git pull --rebase inside ./qemu-mcp-server/ and rebuilding.
The plugin exposes three tools that map 1:1 to the upstream MCP server:
| Tool | Purpose |
|---|---|
execute_qmp | Execute a QMP command on the QEMU instance (e.g. query-status, stop, cont, eject). Any unknown command name is passed through to QEMU verbatim. |
read_serial | Read pending output from the guest's serial console. Supports waiting for a substring, timeouts, and character limits. The socket stays connected in the background and buffers output between calls. |
write_serial | Write data to the guest's serial console (simulate typing into the UART). Combine with read_serial to drive interactive guest programs. |
Note: LM Studio does not run
postinstallscripts for security reasons. The pre-built binary is shipped in the published package so the plugin works out of the box. If the binary is missing or corrupted, see the troubleshooting section below.
Prerequisite: Make sure
cargo(Rust toolchain) is installed and available in yourPATHbefore running the local setup.
The scripts/setup.cjs script performs the clone and build:
https://github.com/nagy/qemu-mcp-server into ./qemu-mcp-server/ (only on first run).git pull --rebase to update the source tree.cargo build --release.bin/qemu-mcp-server (overwriting the shipped pre-built artifact).To pull the latest changes from the original project and rebuild:
After installation, open the plugin settings in LM Studio to adjust the Unix socket paths if your QEMU instance uses locations other than the defaults:
| Setting | Default | Description |
|---|---|---|
| QMP Socket Path | /tmp/qmp-sock | Path to the QEMU QMP unix socket. |
| Serial Socket Path | /tmp/serial-sock | Path to the guest serial console unix socket. |
These correspond to the QMP_SOCKET_PATH and SERIAL_SOCKET_PATH environment variables used by the upstream
server.
execute_qmpExecutes a QMP command on the QEMU instance listening on the QMP unix socket. Convenience commands include
query-status, stop, cont, and eject. Any other command name is forwarded to QEMU as-is.
| Parameter | Type | Description |
|---|---|---|
qmp_command | string | QMP command name, e.g. query-status, stop, cont, eject. |
qmp_arguments | string | JSON object with the command's arguments (may be {}). |
Examples:
Query the VM status:
Eject the medium from the CD-ROM drive:
Stop the VM:
read_serialReads pending output from the guest's serial console. The socket stays connected in the background and buffers everything the guest prints between calls, so nothing is lost while no read is in flight. Output is returned as lossy UTF-8.
| Parameter | Type | Default | Description |
|---|---|---|---|
wait_for | string (optional) | — | Keep polling until this substring appears in the output. |
timeout_ms | number | 5000 | Give up waiting after this many milliseconds. |
max_chars | number (optional) | — | Return at most this many characters from the end of the buffer. |
clear | boolean | false | Discard the buffered output after returning it. |
write_serialWrites data to the guest's serial console, i.e. simulates typing into its UART.
| Parameter | Type | Default | Description |
|---|---|---|---|
data | string | — | Bytes to send to the guest serial port. |
newline | boolean | true | Append a newline after data. |
Treat this plugin as full remote control of the VM: it can pause and resume the machine, access or eject
drives, and interact with the guest's serial console. Anyone who can talk to the MCP server — or to the QMP or
serial socket itself — controls the VM. Use a per-user socket directory (e.g. under $XDG_RUNTIME_DIR) rather
than a world-writable /tmp path shared between users.
If the tools return errors about socket files not being found (e.g. failed to connect to QMP socket /tmp/qmp-sock), this is expected — it means the Rust binary is working correctly, but no QEMU instance
is running with the required QMP and serial sockets. Start QEMU with:
Or update the socket paths in the plugin settings (QMP Socket Path / Serial Socket Path).
This means the pre-built binary (bin/qemu-mcp-server) is missing or corrupted. Try:
qemu-mcp-server binary at .The shipped pre-built binary is compiled for Linux x86_64. If you are using macOS or Windows, you will need to build from source:
This project is a port of the original nagy/qemu-mcp-server repository. The porting approach:
We would like to express our gratitude to nagy and the contributors of the original qemu-mcp-server project for creating and maintaining the upstream Rust MCP server that makes QEMU interaction possible via the Model Context Protocol. This plugin would not exist without their work.
The original qemu-mcp-server Rust source tree (located in ./qemu-mcp-server/) is licensed under the
GNU Affero General Public License v3.0 or later (AGPL-3.0+) by nagy.
The TypeScript wrapper code written for this LM Studio plugin (everything outside ./qemu-mcp-server/) is
licensed under the MIT License (see the LICENSE file in this repository's root).
All third-party names and project names are the property of their respective owners.
cargo) is only needed for local development or when rebuilding from
source (see scripts/setup.cjs).nix develop inside ./qemu-mcp-server/. This is not required for the LM Studio plugin to work.bin/qemu-mcp-serversrc/toolsProvider.ts layer defines LM Studio-compatible tools
(using @lmstudio/sdk tool() and zod schemas) and proxies calls to the upstream Rust binary over stdio
using a minimal MCP-over-stdio client (src/core/qemuMcpClient.ts)../qemu-mcp-server/ and never
modified here. The Cargo.toml, src/, and all other upstream files remain as the original authors wrote
them.postinstall scripts for installed
plugins (for security reasons). To ensure the plugin works out of the box when installed from the Hub, a
pre-built Rust binary is shipped in the bin/ directory of the published package.cd ~/.lmstudio/extensions/plugins/hoonowng/qemu-mcp
node scripts/setup.cjs # clones upstream source + builds the Rust binary
npm run build
lms dev
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
{ "qmp_command": "query-status", "qmp_arguments": "{}" }
{ "qmp_command": "eject", "qmp_arguments": "{\"device\": \"ide-cd0\"}" }
{ "qmp_command": "stop", "qmp_arguments": "{}" }
qemu-system-x86_64 \
-qmp unix:/tmp/qmp-sock,server,nowait \
-serial unix:/tmp/serial-sock,server,nowait \
...
lms uninstall qemu-mcp
lms install qemu-mcp
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
cargo) is only needed for local development or when rebuilding from
source (see scripts/setup.cjs).nix develop inside ./qemu-mcp-server/. This is not required for the LM Studio plugin to work.bin/qemu-mcp-serversrc/toolsProvider.ts layer defines LM Studio-compatible tools
(using @lmstudio/sdk tool() and zod schemas) and proxies calls to the upstream Rust binary over stdio
using a minimal MCP-over-stdio client (src/core/qemuMcpClient.ts)../qemu-mcp-server/ and never
modified here. The Cargo.toml, src/, and all other upstream files remain as the original authors wrote
them.postinstall scripts for installed
plugins (for security reasons). To ensure the plugin works out of the box when installed from the Hub, a
pre-built Rust binary is shipped in the bin/ directory of the published package.cd ~/.lmstudio/extensions/plugins/hoonowng/qemu-mcp
node scripts/setup.cjs # clones upstream source + builds the Rust binary
npm run build
lms dev
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
{ "qmp_command": "query-status", "qmp_arguments": "{}" }
{ "qmp_command": "eject", "qmp_arguments": "{\"device\": \"ide-cd0\"}" }
{ "qmp_command": "stop", "qmp_arguments": "{}" }
qemu-system-x86_64 \
-qmp unix:/tmp/qmp-sock,server,nowait \
-serial unix:/tmp/serial-sock,server,nowait \
...
lms uninstall qemu-mcp
lms install qemu-mcp
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs
npm run build
qemu-system-x86_64 \
-qmp unix:/tmp/qmp-sock,server,nowait \
-serial unix:/tmp/serial-sock,server,nowait \
...
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs # clones + pulls source + rebuilds + copies binary to bin/
npm run build
qemu-system-x86_64 \
-qmp unix:/tmp/qmp-sock,server,nowait \
-serial unix:/tmp/serial-sock,server,nowait \
...
cd /home/sensei/works/qemu-mcp
node scripts/setup.cjs # clones + pulls source + rebuilds + copies binary to bin/
npm run build