NanoKVM MCP Server
# NanoKVM MCP Server
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
An MCP (Model Context Protocol) server for controlling [Sipeed NanoKVM](https://github.com/sipeed/NanoKVM) devices. This enables AI assistants like Claude to remotely control hardware via keyboard, mouse, power buttons, and screen capture.
## What is NanoKVM?
[NanoKVM](https://github.com/sipeed/NanoKVM) is an open-source, affordable IP-KVM device based on RISC-V. It allows remote access to computers at the BIOS level—perfect for managing servers, embedded systems, or any headless machine.
## What is MCP?
[Model Context Protocol](https://modelcontextprotocol.io/) is an open standard for connecting AI assistants to external tools and data sources. This server exposes NanoKVM functionality as MCP tools that Claude and other AI assistants can use.
## Features
| Category | Capabilities |
|----------|-------------|
| **Power Control** | Power on/off, reset, force shutdown via ATX header |
| **Keyboard** | Type text, send key combinations (Ctrl+C, Alt+F4, etc.) |
| **Mouse/Touch** | Click, move, scroll, tap at absolute screen coordinates |
| **Screenshots** | Capture display as JPEG from MJPEG video stream |
| **ISO Mounting** | Mount/unmount ISO images for remote OS installation |
| **Monitoring** | Power LED status, HDD activity, HDMI state, resolution |
## Installation
### From Source
```bash
git clone https://github.com/scgreenhalgh/nanokvm-mcp.git
cd nanokvm-mcp
pip install -e .
```
### Dependencies
- Python 3.10+
- `mcp` - Model Context Protocol SDK
- `httpx` - Async HTTP client
- `websockets` - WebSocket client for real-time HID
- `pycryptodome` - AES encryption for authentication
- `pillow` - Image processing for screenshots
## Configuration
### Environment Variables
| Variable | Required | Default | Description |
|----------|----------|---------|-------------|
| `NANOKVM_HOST` | **Yes** | - | NanoKVM IP address or hostname |
| `NANOKVM_USER` | No | `admin` | Web UI username |
| `NANOKVM_PASS` | No | `admin` | Web UI password |
| `NANOKVM_SCREEN_WIDTH` | No | `1920` | Target screen width in pixels |
| `NANOKVM_SCREEN_HEIGHT` | No | `1080` | Target screen height in pixels |
| `NANOKVM_HTTPS` | No | `false` | Use HTTPS instead of HTTP |
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"nanokvm": {
"command": "python",
"args": ["-m", "nanokvm_mcp.server"],
"env": {
"NANOKVM_HOST": "192.168.1.100",
"NANOKVM_USER": "admin",
"NANOKVM_PASS": "admin",
"NANOKVM_SCREEN_WIDTH": "1920",
"NANOKVM_SCREEN_HEIGHT": "1080"
}
}
}
}
```
### Claude Code
Add to your Claude Code MCP configuration:
```json
{
"mcpServers": {
"nanokvm": {
"command": "python",
"args": ["-m", "nanokvm_mcp.server"],
"env": {
"NANOKVM_HOST": "192.168.1.100"
}
}
}
}
```
## Available MCP Tools
### Power Control
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_power` | `action`: `power`, `power_long`, `reset` | Control power button or reset |
| `nanokvm_led_status` | - | Get power and HDD LED states |
**Actions:**
- `power` - Short press (800ms) - normal power on/off
- `power_long` - Long press (5000ms) - force power off
- `reset` - Press reset button
### Display
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_hdmi_status` | - | Get HDMI connection state and resolution |
| `nanokvm_hdmi_reset` | - | Reset HDMI connection |
| `nanokvm_screenshot` | - | Capture display as base64 JPEG |
### Keyboard Input
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_send_text` | `text`, `language` | Type text (max 1024 chars) |
| `nanokvm_send_key` | `key`, `ctrl`, `shift`, `alt`, `meta` | Send single key with modifiers |
**Supported Keys:**
- Letters: `a`-`z`
- Numbers: `0`-`9`
- Function keys: `f1`-`f12`
- Navigation: `up`, `down`, `left`, `right`, `home`, `end`, `pageup`, `pagedown`
- Control: `enter`, `escape`, `tab`, `backspace`, `delete`, `insert`, `space`
### Mouse/Touch Input
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_tap` | `x`, `y` | Tap at screen coordinates |
| `nanokvm_click` | `button`, `x`, `y` | Click button, optionally at position |
| `nanokvm_move` | `x`, `y` | Move cursor to position |
| `nanokvm_scroll` | `amount` | Scroll wheel (positive=down) |
**Coordinate System:**
- Origin (0, 0) is top-left corner
- Coordinates are in screen pixels based on `SCREEN_WIDTH` and `SCREEN_HEIGHT`
- Internally mapped to NanoKVM's 1-32767 absolute coordinate range
### Storage
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_list_images` | - | List available ISO images |
| `nanokvm_mount_iso` | `file`, `as_cdrom` | Mount ISO image |
| `nanokvm_unmount_iso` | - | Unmount current ISO |
| `nanokvm_mounted_image` | - | Get mounted image info |
### System
| Tool | Parameters | Description |
|------|------------|-------------|
| `nanokvm_reset_hid` | - | Reset keyboard/mouse devices |
| `nanokvm_info` | - | Get NanoKVM device info |
| `nanokvm_hardware` | - | Get hardware information |
## Usage Examples
Once configured, ask Claude to:
| Request | Tool Used |
|---------|-----------|
| "Is the server powered on?" | `nanokvm_led_status` |
| "Power on the machine" | `nanokvm_power` |
| "Reset the server" | `nanokvm_power` with `action="reset"` |
| "Force shutdown" | `nanokvm_power` with `action="power_long"` |
| "Type 'root' and press enter" | `nanokvm_send_text` + `nanokvm_send_key` |
| "Press Ctrl+Alt+Delete" | `nanokvm_send_key` with modifiers |
| "Take a screenshot" | `nanokvm_screenshot` |
| "Click at position 500, 300" | `nanokvm_click` |
| "Mount the Ubuntu ISO" | `nanokvm_mount_iso` |
## Programmatic Usage
You can also use the client library directly:
```python
import asyncio
from nanokvm_mcp import NanoKVMClient
async def main():
# Initialize client
client = NanoKVMClient(
host="192.168.1.100",
username="admin",
password="admin",
screen_width=1920,
screen_height=1080,
)
try:
# Check power status
status = await client.get_led_status()
print(f"Power LED: {status['pwr']}, HDD LED: {status['hdd']}")
# Get HDMI info
hdmi = await client.get_hdmi_status()
print(f"Resolution: {hdmi['width']}x{hdmi['height']}")
# Type some text
await client.paste_text("Hello, World!")
# Send Enter key
await client.send_key("enter")
# Take a screenshot
screenshot = await client.screenshot()
with open("screenshot.jpg", "wb") as f:
f.write(screenshot)
# Click at coordinates
await client.tap(500, 300)
# Power cycle
await client.reset()
finally:
await client.close()
asyncio.run(main())
```
## API Reference
See [API_REFERENCE.md](API_REFERENCE.md) for complete documentation of the NanoKVM REST API and WebSocket protocol, including:
- Authentication (AES-256-CBC encryption)
- All REST endpoints with request/response formats
- WebSocket HID protocol for keyboard and mouse
- USB HID keycodes reference
- Direct SSH HID access via `/dev/hidg*`
## How It Works
### Architecture
```
┌─────────────────┐ HTTP/WS ┌─────────────────┐
│ MCP Client │◄────────────────►│ NanoKVM │
│ (Claude, etc.) │ │ │
└────────┬────────┘ │ ┌───────────┐ │
│ │ │ REST API │ │
MCP Protocol │ └───────────┘ │
│ │ ┌───────────┐ │
┌────────▼────────┐ │ │ WebSocket │ │
│ nanokvm-mcp │ │ │ /api/ws │ │
│ Server │ │ └───────────┘ │
│ │ │ ┌───────────┐ │
│ • Power control │ │ │ MJPEG │ │
│ • HID input │ │ │ Stream │ │
│ • Screenshots │ │ └───────────┘ │
└─────────────────┘ └─────────────────┘
```
### Communication Methods
| Feature | Method | Endpoint |
|---------|--------|----------|
| Authentication | REST | `POST /api/auth/login` |
| Power control | REST | `POST /api/vm/gpio` |
| Text input | REST | `POST /api/hid/paste` |
| Key/Mouse events | WebSocket | `/api/ws` |
| Screenshots | REST | `GET /api/stream/mjpeg` (parsed) |
| ISO mounting | REST | `POST /api/storage/image/mount` |
## Development
### Setup
```bash
# Clone repository
git clone https://github.com/scgreenhalgh/nanokvm-mcp.git
cd nanokvm-mcp
# Install with dev dependencies
pip install -e ".[dev]"
# Run tests
pytest
```
### Project Structure
```
nanokvm-mcp/
├── nanokvm_mcp/
│ ├── __init__.py # Package exports
│ ├── server.py # FastMCP server with tool definitions
│ ├── client.py # NanoKVM API client (REST + WebSocket)
│ ├── auth.py # AES password encryption
│ └── hid.py # USB HID keycodes and helpers
├── pyproject.toml # Package configuration
├── README.md # This file
└── API_REFERENCE.md # Complete API documentation
```
## Troubleshooting
### Connection Refused
1. Verify NanoKVM is reachable: `ping <NANOKVM_HOST>`
2. Check web UI is accessible: `http://<NANOKVM_HOST>`
3. Verify credentials are correct
### Authentication Failed
1. Default credentials are `admin`/`admin`
2. Check if password was changed in NanoKVM web UI
3. Authentication can be disabled in `/etc/kvm/server.yaml`
### HID Input Not Working
1. Try `nanokvm_reset_hid` tool
2. Check "Reset HID" in NanoKVM web UI
3. Verify USB cable connection to target machine
4. Check `/dev/hidg*` devices exist on NanoKVM via SSH
### Screenshot Timeout
1. Ensure HDMI is connected and signal detected
2. Check `nanokvm_hdmi_status` for connection state
3. Try `nanokvm_hdmi_reset` to reinitialize
## License
MIT
## Related Projects
- [Sipeed NanoKVM](https://github.com/sipeed/NanoKVM) - The hardware this server controls
- [Model Context Protocol](https://modelcontextprotocol.io/) - The protocol specification
- [FastMCP](https://gofastmcp.com/) - Python MCP framework
TDQS
Scored across 19 tools
Each tool has a distinct purpose with clear boundaries. For example, nanokvm_click, nanokvm_move, and nanokvm_tap handle different mouse/touch actions, while nanokvm_power and nanokvm_power_cycle manage power operations with specific use cases. No tools appear to overlap or cause confusion in selection.
All tools follow a consistent snake_case naming convention with a 'nanokvm_' prefix and descriptive verb_noun combinations, such as nanokvm_click, nanokvm_hardware, and nanokvm_mount_iso. This uniformity makes the tool set predictable and easy to navigate.
With 19 tools, the server provides comprehensive coverage for NanoKVM device management, including input emulation, power control, media handling, and status monitoring. The count is well-scoped for the domain, offering necessary functionality without being excessive.
The tool set covers all essential aspects of NanoKVM operations: hardware and status queries (e.g., nanokvm_info, nanokvm_hdmi_status), input control (e.g., nanokvm_click, nanokvm_send_text), power management (e.g., nanokvm_power, nanokvm_power_cycle), and ISO image handling (e.g., nanokvm_mount_iso, nanokvm_unmount_iso). No obvious gaps exist for the server's purpose.