Skip to content

Protocol commands

Common global behavior is documented in the CLI hub. The complete protocol command family follows; resource kinds are source-derived.

ssh postgres mysql kubernetes tcp mcp llm web web-egress

gdsgate ssh <target> [--exec [-- <ssh args>...]]

Requests an SSH access certificate for the resource named in <target> (parsed as user@resource or resource). The cert is issued by Authority on Allow and cached. Useful when you want to authorise up front before the native ssh invocation.

With --exec the command, once the cert is in place, replaces itself with ssh <target> and connects in one step: the SSH ProxyCommand wiring is passed inline, so the ~/.ssh/config fragment from ssh-config is not required. Any arguments after -- are forwarded verbatim to ssh, e.g.:

gdsgate --config ~/.gdsgate/client.toml ssh --exec web-01 -- -t 'tail -f /var/log/app.log'
Argument Default Purpose
<target> none user@resource or just resource.
--exec off After minting the cert, exec ssh <target> instead of returning.
-- <ssh args>... none Trailing args forwarded to ssh. Requires --exec.

gdsgate ssh-config [<host_pattern>]

Prints an OpenSSH client-config fragment to stdout that routes native ssh through gdsgate. The --config path of this gdsgate invocation is threaded into the generated ProxyCommand, so the native ssh reaches the same cluster you signed into.

gdsgate --config ~/.gdsgate/client.toml ssh-config '*.gds' > ~/.gdsgate/ssh_config
# then, before the first Host block of ~/.ssh/config:
#   Include ~/.gdsgate/ssh_config

A file of its own instead of an append: regenerating then rewrites it, where >> would leave the previous fragment in place and let the older of two matching blocks keep deciding. The include belongs before the first Host block, because OpenSSH keeps the first value it finds for each option. gdsgate up writes and includes this same file itself.

Argument Default Purpose
<host_pattern> *.gds OpenSSH Host pattern the fragment matches. Aliases under the pattern become the gdsgate resource id.

gdsgate proxy-ssh <resource>

The SSH ProxyCommand transport: relays this process's stdio to the resource's session over the cluster. Invoked by native ssh through ProxyCommand, and not directly. stdout is the SSH byte stream; logs go to stderr.

gdsgate db ls

Lists database resources you can view.

gdsgate db login <resource>

Authorise a database resource: mints and caches a short-lived access certificate for it.

gdsgate db proxy <resource> [--listen <addr>]

Runs a localhost relay for psql / mysql. Each connection to the listener is authorised independently (connect over the Database) and forwarded over the cluster to the database.

gdsgate db proxy prod-db --listen 127.0.0.1:5433 &
psql -h 127.0.0.1 -p 5433
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind. :0 picks an ephemeral port (logged).

gdsgate kube ls

Lists Kubernetes cluster resources you can view.

gdsgate kube login <cluster> [--server <url>]

Prints a kubeconfig fragment that wires kubectl to gdsgate through an exec credential plugin. Merge it into ~/.kube/config.

gdsgate kube login prod-cluster --server https://127.0.0.1:6443 \
    > ~/.kube/gdsgate-prod
Flag Default Purpose
--server <url> https://127.0.0.1:6443 The API server URL kubectl should target: the gdsgate Kubernetes listener, with kube proxy running on this same address.

The fragment carries this invocation's --config so the exec plugin (kube credentials) runs against the same cluster.

gdsgate kube credentials <cluster>

The exec credential plugin for kubectl. Prints an ExecCredential JSON on stdout. kubectl invokes it through the kubeconfig fragment above; do not run it by hand.

gdsgate kube proxy <cluster> [--listen <addr>]

Runs a localhost relay for kubectl. Each connection is authorised (connect over the KubernetesCluster) and forwarded to the connector, which reverse-proxies the real API with identity impersonation, and every request it forwards is decided again, on its own, by kubeRequest.

gdsgate kube proxy prod-cluster --listen 127.0.0.1:6443 &
kubectl --context prod-cluster get pods
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate tcp ls

Lists raw-TCP resources you can view (Redis, internal HTTP, …).

gdsgate tcp proxy <resource> [--listen <addr>]

Localhost relay for any TCP client.

gdsgate tcp proxy redis-cache --listen 127.0.0.1:6390 &
redis-cli -p 6390 ping
Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate mcp ls

Lists MCP-server resources you can view.

gdsgate mcp proxy <resource> [--listen <addr>]

Localhost MCP endpoint. The connector gates each tools/call, resources/read and prompts/get against the policy before it reaches the backend, and filters tools/list to the tools the policy lets you view (viewTools); every call is audited.

The endpoint answers both shapes an MCP client comes in:

  • Streamable HTTP, protocol revision 2026-07-28. Give the client the URL and nothing else.
  • stdio, for a client that starts a program rather than dialling a URL, where the program is gdsgate mcp bridge.
gdsgate mcp proxy tools-mcp --listen 127.0.0.1:8765 &
# MCP client over Streamable HTTP: http://127.0.0.1:8765/
# MCP client over stdio: command `gdsgate mcp bridge 127.0.0.1:8765`

The endpoint refuses any request carrying an Origin header, and any whose Host is not its own loopback address, the two halves of the DNS rebinding attack that reaches local ports from a web page. GET and DELETE are answered 405: revision 2026-07-28 removed the standalone event stream and protocol-level sessions, so an Mcp-Session-Id a client sends is ignored and never echoed.

Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

gdsgate mcp bridge <endpoint>

Speaks an endpoint's stdio framing over this process's own stdin and stdout, for an MCP client that can only start a program. <endpoint> is the host:port gdsgate mcp proxy printed.

// in the client's MCP server configuration
{
  "command": "gdsgate",
  "args": ["mcp", "bridge", "127.0.0.1:8765"]
}

A byte pipe and nothing else: it parses nothing and decides nothing, and every request through it is authorized at the connector exactly as it would be without it. Replacing it, patching it or skipping it changes no decision, which is why nothing is checked in it.

gdsgate web proxy <resource> [--listen <addr>]

Localhost relay onto an HTTP(S) resource: a kind = "web" application, or the one kind = "web-egress" way out named on your grant. There is no web ls: gdsgate ls shows web resources beside every other kind.

gdsgate web proxy grafana --listen 127.0.0.1:0 &
# open http://127.0.0.1:<port>/ in a browser

For an application the connector terminates HTTP and reverse-proxies each request under the application's own name, so its Host, cookies, redirects and links are its own rather than the address printed above. For a way out the listener speaks the shape HTTP defines for a forward proxy, an absolute target in the request line or CONNECT, so it is pointed at with a client's proxy setting (curl -x http://127.0.0.1:<port> https://github.com), not opened in a browser; gdsgate delegate --exec does this automatically for a program, see Endpoints: what the program is given above.

Flag Default Purpose
--listen <addr> 127.0.0.1:0 Local host:port to bind.

See Configuration → The web lane and Policy → HTTP(S) application routes.

gdsgate web trust [--quiet]

Prints the certificate root the resident client signs an application's own domain with, when [client].intercept_names and a catalogued native_name agree on one. See Resident client → An application's own name. The certificate goes to stdout; an explanation of what installing it means goes to stderr, so gdsgate web trust --quiet > gdsgate-local-root.crt produces a plain file and an interactive run still prints the paragraph.

Makes a root for this machine if there is none, since running the command is already the decision to install one, and installs nothing: it prints the commands for the system trust store, NSS and Firefox, and how to undo each of them. What is installed is the certificate this command prints and nothing else; the file under ~/.gdsgate holds the private key too, and a trust store's own directory is world-readable.

Flag Default Purpose
--quiet off Print only the certificate, with no explanation on stderr.

ls login proxy

ls login credentials proxy

ls proxy

ls proxy bridge

proxy trust