Skip to main content
Glama

volter-tunnel

CI License: Apache 2.0

An open-source, WebSocket-based HTTP/WS reverse tunnel — an ngrok / Cloudflare-Tunnel alternative whose headline feature is a free, stable, reservable subdomain that survives reconnects. Built on Cloudflare Workers + Durable Objects, so idle tunnels cost ~nothing.

📖 Documentation: https://volter-ai.github.io/volter-tunnel/

volter-tunnel login --host https://your-relay        # GitHub login, no OAuth app
volter-tunnel --port 3000 --tunnel-id my-app         # → https://my-app.your-relay

Why it exists: reserve a friendly subdomain once and keep it; expose a local port over HTTP, streaming, and WebSocket; gate it with basic-auth/JWT; embed the tunneled app in an iframe (it strips frame-ancestors/X-Frame-Options — no other OSS tunnel does this); inspect every request live. See dev-docs/DECISIONS.md for the full rationale.

Install

bun add @volter/tunnel        # client library + CLI (runs under Bun)

Related MCP server: zrok-mcp

CLI

volter-tunnel login [--gist] [--host <url>]          # prove a GitHub identity, save an api token
volter-tunnel --port 3000 [--tunnel-id my-app]       # expose a local port; prints the URL (+ QR)
volter-tunnel whoami                                  # your account + usage
volter-tunnel usage [--json]                          # your current spend (today / month)
volter-tunnel reservations [--json]                   # your stable ids + capacity
volter-tunnel release <tunnel-id>                     # release one of your stable ids
volter-tunnel tokens [--json]                         # device credentials (metadata only)
volter-tunnel token <restore|revoke> <token-id>       # recover or retire one device
volter-tunnel account <list|usage|create|limits|suspend|resume> [slug] \
  [--day-usd N] [--month-usd N]                       # admin ops (needs the root token)

Common run flags: --host <relayUrl>, --basic-auth user:pass, --auth-not-required, --no-qr.

Library

import { createTunnel } from '@volter/tunnel/client';

const tunnel = await createTunnel({
  port: 3000,
  host: 'https://your-relay',
  tunnelId: 'my-app',              // → https://my-app.your-relay
});
console.log(tunnel.url);
// … later
tunnel.close();

And a typed client for the relay's management/self-service API:

import { VolterClient } from '@volter/tunnel/client';

const client = new VolterClient({ host: 'https://your-relay', token });
const me = await client.whoami();          // { slug, name, usage }
await client.releaseReservation('old-app');           // self-service; own ids only
await client.listDeviceTokens();                      // safe metadata; no secrets/hashes
await client.restoreDeviceToken('host-token-id');     // recover a selected host credential
await client.createAccount({ slug: 'x', dayUsd: 10 });   // root token

MCP server (for AI agents)

@volter/tunnel-mcp exposes account/usage/abuse operations as MCP tools (whoami, usage, reservation and device-token self-service, account_*, reports, waitlist, revoke_reservation):

VOLTER_HOST=https://your-relay VOLTER_TOKEN=<token> bunx @volter/tunnel-mcp

Architecture

A monorepo with one shared protocol contract consumed by both sides:

packages/core/   @volter/tunnel-core — the wire protocol (message union + frame
                 codec + DTOs). Pure, dependency-free, 100% covered.
client/          @volter/tunnel — core ← transport ← sdk (createTunnel +
                 VolterClient) ← cli (the bin).
packages/mcp/    @volter/tunnel-mcp — MCP server over the SDK.
server-cf/       Cloudflare Worker + Durable Objects relay (primary). One DO per
                 tunnelId holds the hibernatable control socket → idle = free.

The protocol lives in core and nowhere else, so the client and relay can't drift — a change to the contract is type-checked on both sides.

Run a relay locally

To try a tunnel end-to-end with no hosted account, run the relay locally and point the client at it:

cd server-cf && npm install && npm run dev   # wrangler dev --local (real workerd)
# then, in another shell:
volter-tunnel --port 3000 --host http://127.0.0.1:8787 --auth-not-required

Packages build to Node-consumable JS via bun run build and publish on a version tag. See dev-docs/PUBLISHING.md.

Develop

bun install
bun run typecheck                                  # client + core + mcp
cd packages/core && bun test                       # protocol (100% gate)
cd packages/mcp  && bun test                       # MCP tools
bun test ./test                                    # client SDK + CLI
cd server-cf && npm install && npx vitest run      # relay (real workerd, no mocks)

See CONTRIBUTING.md. Deploy your own relay with the self-hosting guide (source: docs/self-hosting/deploy.md).

License

Apache-2.0 © Volter.

Related MCP Connectors

Related MCP Servers