Appearance
MCP Server
Vuln Scanner also speaks MCP directly, so AI tools like Claude Code, Claude Desktop, and Cursor can read your findings and trigger scans without leaving your editor or terminal. It's the same data as the Public API, just reachable as MCP tools instead of REST calls — same API keys, same organization scoping.
Connecting
Create an API key from Settings → API Keys (owner-only) if you don't already have one — see Public API for details.
https://your-instance below means the API's own origin — in production this is the single public domain everything (web app, /v1/*, /mcp) is served from behind Caddy, so there's nothing to think about there. Running locally against a dev setup, the API and the web app are two different ports (API on :3000, the Vite dev server on :5173) — point MCP clients at the API's port (http://localhost:3000/mcp), not the one you browse the web app on, or you'll get a 404.
Claude Code
bash
claude mcp add --transport http vuln-scanner https://your-instance/mcp \
--header "Authorization: Bearer vsk_..."Claude Desktop
Claude Desktop's config file only accepts stdio servers (command/args/env) — it has no url/headers entry for a remote HTTP server like this one. Bridge it with mcp-remote:
json
{
"mcpServers": {
"Vuln Scanner": {
"command": "npx",
"args": [
"mcp-remote",
"https://your-instance/mcp",
"--header",
"Authorization:${AUTH_HEADER}"
],
"env": {
"AUTH_HEADER": "Bearer vsk_..."
}
}
}
}Other clients (Cursor, etc.)
Most other MCP clients accept a remote HTTP server directly as a url + headers entry, without needing the mcp-remote bridge — consult that client's own docs for its exact config shape, but the URL and Authorization: Bearer vsk_... header are the only two things it needs.
Available tools
| Tool | Equivalent to |
|---|---|
list_repositories | GET /v1/repositories |
get_repository | GET /v1/repositories/:id |
list_scans | GET /v1/repositories/:id/scans |
trigger_scan | POST /v1/repositories/:id/scans |
get_scan | GET /v1/scans/:id |
list_findings | GET /v1/findings (same severity/status/repositoryId/search filters) |
get_finding | GET /v1/findings/:id |
A natural use: ask your AI tool something like "what critical findings are open in my payments repo?" or "trigger a scan and tell me what changed" — it resolves the repository, calls the right tools, and reads the results back to you.
Notes
- Every response is scoped to the organization the API key belongs to, exactly like
/v1/*— there's no way to read across organizations regardless of what a key can see. - The connection is stateless: each tool call is authenticated and served independently, so there's nothing to keep alive or reconnect if your client restarts.
- Same rate limit as the REST API — 60 requests per minute per organization.