vpnhop
vpnhop is an MCP server for managing containerized VPN tunnels and sending HTTP(S) requests through them without connecting the host machine to the VPN.
List configured VPN profiles with type, allowed hosts, and tunnel state.
Connect or reuse a profile tunnel, disconnect it, and inspect tunnel status with optional redacted client logs.
Send HTTP(S) requests through a profile with configurable method, headers, text or base64 body, redirects, timeout, TLS verification, and response size limit; auto-connects if needed.
Save supported OpenVPN or WireGuard profile files into the encrypted keyhop vault with Touch ID confirmation, or remove profiles and their secrets.
Refresh vpnhop by recycling servers, dropping cached secrets, and cleaning up stale or outdated tunnels and images while preserving healthy tunnels.
Note: MCP access is HTTP(S) only; raw TCP is available through the vpnhop proxy CLI/SOCKS. OpenConnect, IPsec, or password-requiring profiles must be added in a terminal.
Supports Cisco AnyConnect / ocserv VPN profiles via openconnect, allowing HTTP(S) requests to be routed through the VPN tunnel using username/password, TOTP, or certificate pinning authentication.
Supports Fortinet VPN profiles via openconnect, enabling HTTP(S) requests through a Fortinet tunnel with username/password and TOTP authentication.
Supports OpenVPN profiles, including AWS Client VPN and OpenVPN Connect .ovpn files, using OpenVPN 2.7 in a container with certificate or username/password authentication.
Supports IPsec IKEv2 VPN profiles using strongSwan swanctl, with EAP-MSCHAPv2 and PSK authentication, to route HTTP(S) requests through the tunnel.
Supports WireGuard VPN profiles using wg-quick with kernel support or wireguard-go fallback, authenticating with private keys and routing HTTP(S) requests through the tunnel.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@vpnhop use the work-vpn profile to GET https://internal.company.com/api/health"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
vpnhop
MCP server that sends API calls through a VPN without connecting your machine to the VPN. Each profile's VPN client runs in its own throwaway Docker container; requests run from inside it.
VPN | Client in container | Auth |
OpenVPN (incl. AWS Client VPN, OpenVPN Connect |
| certs, username/password |
WireGuard |
| private key |
Cisco AnyConnect / ocserv, GlobalProtect, Pulse/Ivanti, Juniper NC, Fortinet, F5, Array |
| username/password, TOTP, cert pin |
IPsec IKEv2 | strongSwan ( | EAP-MSCHAPv2, PSK |
Part of a suite with keyhop (the encrypted vault) and hopsql (databases). See docs/suite.md.
Save a profile once
vpnhop import # lists OpenVPN Connect profiles, with the command to save each
vpnhop add aws ~/Downloads/aws.ovpn # any .ovpn or WireGuard .conf
vpnhop add corp --type openconnect --server vpn.example.com --protocol gp --user me --totp
vpnhop listThe profile file and its credentials are encrypted in keyhop (Touch ID). Referenced cert/key files and an
auth-user-passfile are inlined first.config.jsononly gets names, settings and{ "keyhop": "VPNHOP_AWS_CONFIG" }references.Missing credentials are asked for in the terminal, with the input hidden. You can then delete the original file.
Claude can save a profile from a file path with
save_profile; you confirm with Touch ID. Claude never sees the contents.
Related MCP server: pipepie
How it works
No sudo, no host routes, no system VPN. Host traffic is never affected.
When a tunnel starts, vpnhop fetches all of the profile's secrets from keyhop in one request, which takes one Touch ID tap. keyhop only answers the vpnhop install it pinned.
Secrets can also come from
env,fileorcommand(e.g.op read).Either way, secrets reach the container as a tar on stdin: no host temp file, env var or bind mount.
DNS is resolved inside the tunnel (pushed DNS, WireGuard
DNS=, ordns/searchDomainsoverrides).Tunnels are shared and leased:
Every request or
vpnhop proxycall extends the lease.The container stops itself after
idleMinuteswithout use.Reusing a running tunnel needs no secrets, so no Touch ID.
Other tools reach the VPN through
vpnhop proxy <p>, a SOCKS5 proxy on127.0.0.1. hopsql uses it with"vpn": {"provider": "vpnhop", "profile": "aws"}.Client logs come back redacted, and only for tunnels this server started.
Tools
Tool | Does |
| Profiles, type, allowed hosts, tunnel state |
| HTTP(S) via a profile; auto-connects |
| Manual tunnel control |
| Save a profile file into keyhop, or delete one (Touch ID) |
| State, plus the redacted client log |
| Same as |
Install
Needs Docker Desktop (running) and Node.js 24+. One command installs and registers it with Claude Code:
curl -fsSL https://raw.githubusercontent.com/kylepantall/vpnhop/main/scripts/install.sh | bash -s -- --claudeWhat the installer does:
Installs into
~/.local/share/vpnhop, with avpnhoplauncher in~/.local/bin. The launcher uses the Node it found at install time.Builds the VPN runtime image.
Creates
~/.config/vpnhop/config.jsonfrom the example if you don't have one. Edit it to add your VPNs.Starts the new version: servers on the old build are stopped, and Claude starts the new one when it reconnects.
Options:
Pin a branch, tag or commit:
bash -s -- --claude <ref>.An existing
vpnhopentry stops the installer.--forcereplaces it.From a local checkout:
VPNHOP_SOURCE_DIR=~/Code/vpnhop bash scripts/install.sh --claude.VPNHOP_INSTALL_DIRandVPNHOP_BIN_DIRchoose other directories.
Start a new Claude session after installing.
Uninstall
curl -fsSL https://raw.githubusercontent.com/kylepantall/vpnhop/main/scripts/uninstall.sh | bashThis removes:
the Claude entry;
running servers;
tunnel containers and runtime images;
the launcher and the install directory.
Your config is kept. Add -s -- --purge to delete ~/.config/vpnhop as well.
Command line
Command | Does |
| MCP server on stdio |
| Checks GitHub for a newer release and reruns the installer for it. |
| Closes and restarts dangling instances (details below). macOS and Linux |
| Manage saved profiles (see above) |
| SOCKS5 proxy into the tunnel for other tools; extends the lease |
| Register this install with keyhop again (the installer does this) |
| Every profile and its tunnel state |
| Bring a tunnel up or down |
| GET a URL through a tunnel |
| Rebuild the runtime image |
What vpnhop refresh does:
Running servers drop the secrets they cached.
Servers older than the installed build, or orphaned by a closed client, are stopped. Claude restarts them on reconnect.
Tunnels that are stopped, belong to a deleted profile, or were built from an older profile or image are removed. Healthy tunnels stay up.
Old runtime images are removed.
Releasing: bump version in package.json and src/version.ts, then publish a v<version> GitHub release. vpnhop update picks it up.
Config
~/.config/vpnhop/config.json (or $VPNHOP_CONFIG). See examples/config.json. Relative paths resolve against the config file's folder.
Field | Applies to | Notes |
| all |
|
| all | Override pushed DNS |
| all | Also settable under |
secrets | all |
|
| openvpn, wireguard | A file path, or |
⚠️ For OpenVPN, external ca/cert/key/tls-* files are copied in, and host hook scripts (up, down, …) are dropped.
Limits
SAML / browser SSO VPNs (AWS Client VPN federated auth, Okta-fronted GlobalProtect) need a human in a browser, so they can't run headless.
L2TP, PPTP and SSTP are not supported.
Claude gets HTTP(S) only. Raw TCP goes through
vpnhop proxy.⚠️ Any local process can use a tunnel's SOCKS port while it is up.
⚠️ Anything that can run
docker execcan read a running tunnel's staged secrets. That includes Claude's shell.
Develop
npm install
npm test # unit
npm run test:e2e # real WireGuard, OpenVPN and IPsec servers in Docker, a fake keyhop, SOCKS and leases
npm run typecheckAvailable Tools
8 toolsconnectConnect a VPN profileAIdempotent
Starts the tunnel for a profile and waits until it is up (http_request also does this on demand). Reuses a running tunnel. On failure the error includes the redacted VPN client log.
Inputs: profile (required).
disconnectDisconnect a VPN profileBIdempotent
Stops and removes the tunnel container for a profile.
Inputs: profile (required).
http_requestHTTP request through a VPNADestructive
Sends an HTTP(S) request from inside the profile's tunnel (connecting first if needed) and returns status, headers and body. Text bodies come back as utf8, binary as base64; bodies over maxBodyBytes are truncated. Redirects are not followed unless followRedirects is set.
Inputs: url (required), profile (required), body, method, +6 more.
list_profilesList VPN profilesBRead-only
Configured VPN profiles with their type, description, allowed hosts and whether each tunnel is up.
Inputs: no named parameters.
refreshRefresh vpnhopAIdempotent
Recycles running vpnhop servers (cached secrets dropped), stops outdated or orphaned ones, and removes stopped, orphaned or outdated tunnel containers and old runtime images. Healthy tunnels stay up. Use after updating vpnhop or editing profiles; disconnect a stuck tunnel instead.
Inputs: no named parameters.
remove_profileRemove a VPN profileADestructiveIdempotent
Deletes a saved profile and its keyhop secrets (the user confirms with Touch ID), and stops its tunnel.
Inputs: profile (required).
save_profileSave a VPN profileA
Saves a VPN profile from a file on this machine (.ovpn or WireGuard .conf) into the encrypted keyhop vault; the user confirms with Touch ID. Referenced cert/key files and an auth-user-pass file are inlined. You never see the contents. Profiles that need a password not in the file, or OpenConnect/IPsec profiles, must be added by the user in a terminal: vpnhop add.
Inputs: file (required), name (required), type, allowHosts, +1 more.
statusTunnel statusBRead-only
State of one or all tunnels, optionally with the last lines of the (redacted) VPN client log.
Inputs: logs, profile.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Tools split cleanly into profile management (save/remove/list), tunnel lifecycle (connect/disconnect/status/refresh), and tunnelled HTTP (http_request). Minor overlap: list_profiles also reports tunnel-up state, and refresh's note about disconnecting stuck tunnels slightly bleeds into disconnect's territory, but descriptions clarify boundaries.
Mostly snake_case, but conventions are mixed: verb_noun compounds (save_profile, remove_profile, list_profiles), bare verbs (connect, disconnect, refresh), a bare noun (status), and a noun_verb form (http_request). Readable overall, but no single predictable pattern.
Eight tools is well-scoped for a VPN profile manager with tunnelled requests—each tool covers a distinct operation (create, delete, list, connect, disconnect, status, refresh, request). Nothing feels redundant or missing at this granularity.
Covers the full tunnel lifecycle plus profile create/delete/list and in-tunnel HTTP. Gaps are minor: there is no update/edit_profile tool (editing is assumed external, and refresh merely picks up changes), and profiles requiring passwords or OpenConnect/IPsec must fall back to a terminal.
Maintenance
Related MCP Connectors
Route HTTP requests through the Tor network. Rotating exit IPs, .onion support, no body logging.
Secure tunneling, reverse proxy and remote access for local applications.
Dedicated static outbound IPv4 over WireGuard. Free 7-day trial, no card, no sales call.
Remote shell and detached long-running jobs on your own machines — no SSH, open ports or VPN.
Related MCP Servers
- AlicenseAqualityCmaintenanceCredential isolation proxy for AI agents. Injects API keys at the network boundary so your agent never sees the raw credential. Supports domain allowlists, agent auth, policy enforcement, and audit logging.379 npm16Apache 2.0
- AlicenseAqualityDmaintenanceSelf-hosted webhook relay and tunnel with Noise NK encryption. Inspect requests, replay webhooks, trace AI pipelines, connect/disconnect tunnels — 13 MCP tools. No tokens or passwords needed.138AGPL 3.0
- AlicenseNot gradedqualityBmaintenanceBounded egress gateway & secret proxy for AI agents and applications, enabling safe credential injection into upstream requests while keeping raw secrets out of LLM prompt contexts.28 npmMIT
- AlicenseNot gradedqualityCmaintenancePlaywright browser MCP for coding agents working behind a full-tunnel VPN. The tunnel stays up so the agent keeps reaching its API, while the browser's own traffic egresses through your real ISP — for services that reject the tunnel's exit IP: domestic APIs, payment and SMS gateways, bank endpoints. Per-socket binding plus a LAN-bound proxy, with per-host routing rules so you choose which hosts go80 npm4MIT