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.
Organization API token (default, recommended)
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.
- In the BestDefense web UI, generate a pentest organization API token for
your org. It carries the
pentest:runscope and is revocable at any time. - Set it as the plugin’s
api_tokenconfig (/plugin→ configure). The plugin passes it to the container as theBD_PENTEST_TOKENenvironment variable. - 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.
Device-flow secure mode (optional)
Section titled “Device-flow secure mode (optional)”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.
Switch to the wrapper
Section titled “Switch to the wrapper”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}" } } }}Log in and check status
Section titled “Log in and check status”/bestdefense-pentest:login/bestdefense-pentest:statuslogin 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.
How the token stays fresh
Section titled “How the token stays fresh”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.
Endpoint discovery
Section titled “Endpoint discovery”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.