Skip to content

Authenticating Vortex MCP

Vortex MCP supports two ways to authenticate. The organization API token is the default and works everywhere; the device-flow secure mode is optional and keeps no static token on disk.

Section titled “Organization API token (default, recommended)”

This path runs the container directly with a token you supply — no wrapper, no keychain, no browser. It works in any MCP client, headless, in CI, and on WSL2.

  1. In the BestDefense web UI, generate a pentest organization API token for your org. It carries the pentest:run scope and is revocable at any time.
  2. Set it as the plugin’s api_token config (/plugin → configure). The plugin passes it to the container as the BD_PENTEST_TOKEN environment variable.
  3. If you’re on a dedicated stack, also set api_url, e.g. https://pentest.<your-stack>.bestdefense.io.

For a direct-MCP or CI setup, pass the token as BD_PENTEST_TOKEN directly — see Configuration and CI integration.

The resource server validates the token at /oauth/introspect on every request, so your org’s entitlement is enforced on every call even though the token is long-lived.

Prefer to keep no static bearer on disk? Use the host wrapper (bin/bd-pentest-cli) instead of running Docker directly. It runs the OAuth 2.0 device flow (RFC 8628) and stores only the refresh token in your OS keychain, minting a short-lived access token per request.

Point the MCP server’s command at the wrapper (replace the bestdefense-pentest server in your .mcp.json):

{
"mcpServers": {
"bestdefense-pentest": {
"command": "${CLAUDE_PLUGIN_ROOT}/bin/bd-pentest-cli",
"args": ["mcp-serve"],
"env": { "BD_PENTEST_API_URL": "${user_config.api_url}" }
}
}
}
/bestdefense-pentest:login
/bestdefense-pentest:status

login prints a URL and a code; approve it in your browser. status shows your org, tier, pentest seats, and remaining deep-scan credits. Re-run login only if status reports the session expired.

A long session or a deep scan can outlive a single access token. The wrapper runs a host loopback token broker that the container reads per request over host.docker.internal, so the executor always has a fresh access token (≤ 900 seconds). bd-web rotates refresh tokens and detects reuse, so the wrapper persists each new refresh token before using it.

You only ever set api_url. The wrapper discovers the OAuth endpoints from it: RFC 9728 (protected-resource metadata) points to the authorization server, and RFC 8414 (authorization-server metadata) yields the device-authorization and token endpoints. You never hand-build an endpoint URL.

Secure mode needs python3 on the host with keyring and httpx. Headless Linux and WSL2 have no keychain by default — see Troubleshooting for the one-time setup, or just use the API-token path.