mullvad-mcp
# 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
Scored across 18 tools
Each tool targets a distinct aspect of VPN management: connection, settings, status, info, and listings. There is no overlap in functionality.
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.
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.
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.