Skip to main content

Installation

npm install -g @thornguard/cli
Requires Node.js 18 or later. After installation, the thornguard command is available globally.

Authentication

thornguard auth login

Store your ThornGuard license key in the platform keyring.
thornguard auth login
You will be prompted to paste your license key (starts with THORN-). The key is stored securely in:
  • macOS: Keychain (security CLI)
  • Linux: freedesktop.org Secret Service (secret-tool)
  • Windows: DPAPI-encrypted credential file
Options:
FlagDescription
--license-env NAMERead the license from environment variable NAME instead of prompting

thornguard auth logout

Remove the stored license key from the keyring.
thornguard auth logout

Profile Management

Profiles store connection metadata locally. Secrets (license key, upstream tokens) are kept in the platform keyring, never in profile files.

thornguard profile add <name>

Create a new connection profile.
thornguard profile add my-server \
  --display-name "My Server (Protected)" \
  --target-url https://my-server.com/mcp \
  --upstream-auth-mode bearer \
  --upstream-token-env MY_TOKEN \
  --vendor-name "My Vendor" \
  --intel-enabled
Required:
FlagDescription
--target-url URLThe upstream MCP server URL (must be HTTPS)
Optional:
FlagDescription
--display-name TEXTHuman-friendly label for client configs (supports spaces and special characters)
--kind client|serviceProfile type (default: client)
--transport MODETransport preference: http-first (default), sse-first, http-only, sse-only
--upstream-auth-mode none|bearerWhether the upstream server requires auth (default: none)
--upstream-token-env NAMERead the upstream bearer token from environment variable NAME instead of prompting
--vendor-name NAMEVendor name for advisory intelligence
--repo-url URLRepository URL for dependency intelligence
--status-page-url URLStatus page URL for availability intelligence
--intel-enabledEnable advisory intelligence for this profile
--intel-disabledDisable advisory intelligence
--notes TEXTFree-text notes

thornguard profile update <name>

Update an existing profile. Only the provided flags are changed; everything else is preserved.
thornguard profile update my-server --display-name "New Display Name"
The upstream bearer token is only re-prompted if --upstream-token-env is explicitly provided or no token exists yet.

thornguard profile remove <name>

Delete a profile and its stored upstream token.
thornguard profile remove my-server
FlagDescription
--delete-remoteAlso delete the connection from the ThornGuard management API

thornguard profile list

List all saved profiles.
thornguard profile list
thornguard profile list --json

thornguard profile show <name>

Show full details of a profile.
thornguard profile show my-server
thornguard profile show my-server --json

Running & Config Generation

thornguard run <name>

Launch the MCP bridge for a profile. This is the command that MCP clients invoke — you typically don’t run it manually.
thornguard run my-server
FlagDescription
--server-url URLOverride the ThornGuard proxy URL (default: https://thorns.qwady.app)

thornguard print-config

Generate or apply client-specific MCP configuration. Print to stdout:
thornguard print-config --client claude my-server
Apply directly to client config file:
thornguard print-config --client claude my-server --apply
The --apply flag merges the profile into the client’s config file, preserving existing settings. If a --display-name is set on the profile, it’s used as the server label in the config.
FlagDescription
--client NAMERequired. Target client: claude, vscode, cursor, zed
--applyWrite directly to the client’s config file instead of printing
Config file locations (macOS):
ClientPath
Claude Desktop~/Library/Application Support/Claude/claude_desktop_config.json
Cursor~/.cursor/mcp.json
VS Code~/Library/Application Support/Code/User/settings.json
Zed~/.config/zed/settings.json

Discovery & Protection

thornguard scan

Discover all MCP servers configured across your MCP clients. Read-only — never modifies any config files.
thornguard scan
thornguard scan --client claude
thornguard scan --unprotected-only
thornguard scan --json
Example output:
Client  Server                      Status              Upstream
------  --------------------------  ------------------  ---------------------------------
claude  GitHub Copilot (Protected)  Protected (CLI)     https://api.githubcopilot.com/mcp
claude  Filesystem                  Local (not proxy.)  --
cursor  Slack MCP                   Unprotected         https://mcp.slack.com/sse
FlagDescription
--client NAMEScan only one client: claude, vscode, cursor, zed
--protected-onlyShow only ThornGuard-protected servers
--unprotected-onlyShow only unprotected servers
--jsonOutput as JSON array
Server statuses:
StatusMeaning
Protected (CLI)Uses thornguard run — fully managed by ThornGuard CLI
Protected (Bridge)Uses mcp-remote through thorns.qwady.app — manual header config
UnprotectedRemote MCP server with no ThornGuard protection — can be protected
Local (not proxyable)Local stdio server (e.g., python, node) — cannot be proxied

thornguard protect

Interactive wizard that protects an unprotected remote MCP server with one command.
thornguard protect
thornguard protect --client claude
thornguard protect --yes
Flow:
  1. Scans all clients for unprotected remote MCP servers
  2. Presents a numbered list
  3. You select a server
  4. The CLI extracts its upstream URL, creates a ThornGuard profile, and rewrites the client config
  5. The original server name is preserved with “(Protected)” appended
FlagDescription
--client NAMEOnly scan a specific client
--yesSkip confirmation prompt
Local stdio servers (e.g., python -m my_server) cannot be proxied through ThornGuard. These are shown during scan but skipped during protect.

Diagnostics

thornguard doctor <name>

Run connectivity and configuration checks for a profile.
thornguard doctor my-server
Checks performed:
  • ThornGuard proxy health
  • Target URL format validation
  • CLI authentication status
  • License key API validation
  • Upstream bearer token presence (if required)
  • Advisory intelligence refresh (if enabled)
FlagDescription
--server-url URLOverride the ThornGuard proxy URL

thornguard status <name>

Show the current status and advisories for a profile.
thornguard status my-server
thornguard status my-server --refresh
FlagDescription
--refreshForce an advisory refresh before showing status
--server-url URLOverride the ThornGuard proxy URL

Environment Variables

VariableDescription
THORNGUARD_CONFIG_DIROverride the config directory (default: ~/.thornguard)
THORNGUARD_SECRET_BACKENDForce secret backend: keychain (default) or file
THORNGUARD_ALLOW_INSECURE_PLAINTEXTSet to 1 to allow the file backend (required for CI/testing)

Examples

Protect GitHub Copilot MCP

# Store license
thornguard auth login

# Create profile with a pretty name
GITHUB_TOKEN=ghp_your_token_here \
thornguard profile add github-copilot \
  --display-name "GitHub Copilot (Protected)" \
  --target-url https://api.githubcopilot.com/mcp \
  --upstream-auth-mode bearer \
  --upstream-token-env GITHUB_TOKEN \
  --vendor-name GitHub

# Apply to Claude Desktop
thornguard print-config --client claude github-copilot --apply

# Verify
thornguard doctor github-copilot

Protect a Custom MCP Server (No Upstream Auth)

thornguard profile add my-internal-tools \
  --display-name "Internal Tools" \
  --target-url https://tools.mycompany.com/mcp

thornguard print-config --client cursor my-internal-tools --apply

Discover and Protect Existing Servers

If you already have MCP servers configured, the fastest path is scan then protect:
# See what's configured across all your clients
thornguard scan

# Interactively protect an unprotected server
thornguard protect
The protect wizard handles profile creation, config rewriting, and name preservation automatically.