Skip to main content
Glama
README.md
# mullvad-mcp

An MCP (Model Context Protocol) server for controlling [Mullvad VPN](https://mullvad.net) through any MCP-compatible client — Claude Desktop, Cursor, Windsurf, and more.

All VPN interaction goes through the `mullvad` CLI. No direct API calls, no config file parsing, no credentials needed.

## Prerequisites

- **Mullvad VPN app** installed with the CLI available in your PATH
  - Verify: `mullvad --version`
  - [Download Mullvad](https://mullvad.net/en/download)
- **Python 3.11+**
- **uv** package manager — [install uv](https://docs.astral.sh/uv/getting-started/installation/)

## Installation

```bash
git clone https://github.com/your-username/mullvad-mcp.git
cd mullvad-mcp
uv sync
```

## Client Configuration

### Claude Desktop

Add to `~/.config/claude-desktop/claude_desktop_config.json` (Linux) or `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):

```json
{
  "mcpServers": {
    "mullvad": {
      "command": "uv",
      "args": ["--directory", "/path/to/mullvad-mcp", "run", "mullvad-mcp"]
    }
  }
}
```

### Cursor

Add to `.cursor/mcp.json` in your project or `~/.cursor/mcp.json` globally:

```json
{
  "mcpServers": {
    "mullvad": {
      "command": "uv",
      "args": ["--directory", "/path/to/mullvad-mcp", "run", "mullvad-mcp"]
    }
  }
}
```

### Generic MCP Client (stdio)

```json
{
  "mcpServers": {
    "mullvad": {
      "command": "uv",
      "args": ["--directory", "/path/to/mullvad-mcp", "run", "mullvad-mcp"],
      "transport": "stdio"
    }
  }
}
```

## Available Tools

### Connection Control

| Tool | Description |
|------|-------------|
| `connect` | Connect to VPN, optionally specifying country/city/hostname |
| `disconnect` | Disconnect from VPN |
| `reconnect` | Reconnect, optionally to a new location |

### Status & Diagnostics

| Tool | Description |
|------|-------------|
| `get_status` | Current connection state, server, protocol, IPs |
| `check_leak` | Query am.i.mullvad.net to verify VPN protection |

### Server Selection

| Tool | Description |
|------|-------------|
| `list_countries` | All available countries with server counts |
| `list_cities` | Cities for a given country |
| `list_servers` | Servers with filters (country, city, owned_only) |
| `set_location` | Set preferred location by country, city, or hostname |

### Account Management

| Tool | Description |
|------|-------------|
| `get_account_info` | Masked account number, expiry date |
| `get_device_info` | Devices registered to the account |

### Settings

| Tool | Description |
|------|-------------|
| `get_settings` | All current settings as a structured object |
| `set_killswitch` | Enable/disable lockdown mode |
| `set_daita` | Enable/disable DAITA (traffic analysis defence) |
| `set_multihop` | Enable/disable multihop with optional entry location |
| `set_dns` | Set DNS: default (with blocking options) or custom IPs |
| `set_protocol` | Configure WireGuard options (quantum resistance, IPv6) |
| `set_obfuscation` | Set anti-censorship mode (auto/off/udp2tcp/shadowsocks/etc) |

## Example Interactions

### Connection

> "Connect me to Sweden"
>
> → Calls `connect(country="se")` — sets relay to Sweden and connects.

### Status Check

> "Am I leaking?"
>
> → Calls `check_leak()` — queries am.i.mullvad.net and reports whether traffic exits through Mullvad.

### Server Selection

> "What cities are available in Germany?"
>
> → Calls `list_cities(country="de")` — returns Berlin, Frankfurt, etc. with server counts.

### Settings

> "Enable the kill switch and block ads"
>
> → Calls `set_killswitch(enabled=True)` then `set_dns(block_ads=True)`.

## Environment Variables

| Variable | Default | Description |
|----------|---------|-------------|
| `MULLVAD_CLI_PATH` | Auto-detected | Override path to the `mullvad` binary |
| `MULLVAD_CLI_TIMEOUT` | `10` | CLI command timeout in seconds |

## How It Works

All tools call the `mullvad` CLI via subprocess. The CLI handles authentication natively — no API keys or secrets are needed. Output is parsed into structured dicts so LLMs can reason about the results.

## Resources

- [Mullvad CLI Documentation](https://mullvad.net/en/help/how-use-mullvad-cli)
- [Model Context Protocol](https://modelcontextprotocol.io)
- [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)

## License

MIT

TDQS

A4/5.0

Scored across 18 tools

Disambiguation5/5

Each tool targets a distinct aspect of VPN management: connection, settings, status, info, and listings. There is no overlap in functionality.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with underscores, making them predictable and easy to understand. Examples include check_leak, get_status, set_dns, list_countries.

Tool Count4/5

18 tools is slightly above the ideal range of 3-15, but each tool covers a necessary function for a comprehensive VPN configuration surface, so the count is still reasonable.

Completeness4/5

The set covers core VPN operations (connect, disconnect, status, settings) and advanced features (DAITA, multihop, obfuscation). Minor gaps like account login/logout or device management are not critical for the primary use case.

Maintenance

ActivityInactive
ResponsivenessNo issues