# mcvnc

VNC client as an [MCP](https://modelcontextprotocol.io/) server. Gives language models interactive access to remote desktops -- connect to VNC sessions, capture screenshots, send keyboard and mouse input, read and write the clipboard.

Built on [FastMCP](https://gofastmcp.com/) and [asyncvnc2](https://pypi.org/project/asyncvnc2/).

## Install

```bash
pip install mcvnc
```

Or with [uv](https://docs.astral.sh/uv/):

```bash
uv tool install mcvnc
```

## Quickstart

### Claude Code

```bash
claude mcp add mcvnc -- uvx mcvnc
```

### Other MCP hosts (stdio transport)

```json
{
  "mcpServers": {
    "mcvnc": {
      "command": "uvx",
      "args": ["mcvnc"]
    }
  }
}
```

### Manual / development

```bash
git clone https://git.supported.systems/warehack.ing/mcvnc.git
cd mcvnc
make install  # uv sync --group dev
make run      # uv run mcvnc
```

## Tools

### Connection

| Tool | Description |
|------|-------------|
| `vnc_connect` | Connect to a VNC server (host, port, password) |
| `vnc_disconnect` | Close a session |
| `vnc_list_sessions` | List active connections |
| `vnc_session_info` | Details for a specific session |

### Screen

| Tool | Description |
|------|-------------|
| `vnc_screenshot` | Full-desktop screenshot (returns inline PNG + metadata) |
| `vnc_screenshot_region` | Capture a specific rectangle of the desktop |
| `vnc_screen_info` | Desktop dimensions without capturing |
| `vnc_wait_for_screen_change` | Wait until the screen updates after an interaction |

### Input

| Tool | Description |
|------|-------------|
| `vnc_type_text` | Type a string of text |
| `vnc_press_key` | Press a single key (Enter, Tab, Escape, etc.) |
| `vnc_key_combo` | Key combination (Ctrl+C, Alt+F4, etc.) |
| `vnc_click` | Click at coordinates (left/right/middle) |
| `vnc_double_click` | Double-click at coordinates |
| `vnc_move` | Move the mouse cursor |
| `vnc_drag` | Click-drag from one point to another |
| `vnc_scroll` | Scroll up or down |

### Clipboard

| Tool | Description |
|------|-------------|
| `vnc_get_clipboard` | Read the remote clipboard |
| `vnc_set_clipboard` | Write to the remote clipboard |

## Typical workflow

```
vnc_connect  ->  vnc_screenshot  ->  interpret UI  ->  interact
                      ^                                    |
                      |                                    v
                      +----  vnc_screenshot  <----  vnc_wait_for_screen_change
```

Use `vnc_screenshot_region` when you only care about a dialog, menu, or status bar -- it requests just that rectangle from the VNC server instead of the full desktop.

Use `vnc_wait_for_screen_change` after interactions to wait for the UI to actually update before taking the next screenshot. Optionally pass a region to watch for changes only within that area.

## Configuration

All settings via environment variables, all optional:

| Variable | Default | Description |
|----------|---------|-------------|
| `MCVNC_DEFAULT_PORT` | `5900` | Default VNC port |
| `MCVNC_CONNECTION_TIMEOUT` | `10` | Connection timeout (seconds) |
| `MCVNC_SCREENSHOT_TIMEOUT` | `30` | Screenshot timeout (seconds) |
| `MCVNC_SCREENSHOT_MAX_WIDTH` | `0` | Max screenshot width, 0 = no limit |
| `MCVNC_WAIT_CHANGE_TIMEOUT` | `5` | Wait-for-change timeout (seconds) |

## Development

```bash
make install   # uv sync --group dev
make test      # pytest
make lint      # ruff check
```

## License

GPL-3.0-or-later -- required by the [asyncvnc2](https://pypi.org/project/asyncvnc2/) dependency.
