mullvad-mcp
An MCP (Model Context Protocol) server for controlling Mullvad VPN 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
- Verify:
- Python 3.11+
- uv package manager — install uv
Installation
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):
{
"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:
{
"mcpServers": {
"mullvad": {
"command": "uv",
"args": ["--directory", "/path/to/mullvad-mcp", "run", "mullvad-mcp"]
}
}
}
Generic MCP Client (stdio)
{
"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)thenset_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
License
MIT