Skip to main content

vulkro mcp serve

Run Vulkro as a Model Context Protocol server. Once configured, Claude Desktop, Cursor, Windsurf, Continue, VS Code's MCP client, and any other JSON-RPC 2.0 MCP client can call the scanner directly from inside the editor: tell the model "scan this project" and it will invoke Vulkro, parse the findings JSON, and walk through them inline.

The sibling subcommand vulkro mcp-audit audits MCP host configs (kept at its original top-level path for backwards compatibility) and is unrelated to mcp serve.

Usage

vulkro mcp serve # stdio transport (default)
vulkro mcp serve --port 9100 # SSE transport on http://127.0.0.1:9100/sse

Flags

FlagDescriptionDefault
--port <PORT>When set, binds an HTTP listener on 127.0.0.1:<PORT> and exposes /sse (event stream) and /messages (POST endpoint for JSON-RPC requests). When omitted, the default stdio transport is used.(omitted, stdio)

Exit codes

CodeMeaning
0Clean shutdown. The host closed stdin (stdio mode) or Ctrl-C was hit (SSE mode).
1The server started but encountered a feature refusal on a tool call that the caller treated as fatal.
2Operational error: bind failure, transport-level IO error, bad argument to mcp serve.

Tools exposed

Five tools are surfaced over JSON-RPC. Schemas are advertised via the standard tools/list method; the per-tool input shape below matches what hosts render in the tool picker.

scan_project({path, format?})

Run a full Vulkro scan on the project root at path and return the standard JSON output. The result carries a top-level scan_id field that subsequent get_findings calls can use to re-filter without re-scanning.

FieldTypeRequiredDescription
pathstringyesAbsolute path to the project root.
format"json" | "summary"nojson (default) returns the full ScanResult; summary returns a compact stats-only view.

scan_file({path})

Detect the project containing path, run the scanner, and return only the findings whose source file matches.

FieldTypeRequiredDescription
pathstringyesAbsolute path to a source file.

explain({rule_id})

Return a markdown explainer for the named rule. Accepts:

  • OWASP-category slugs (api1-broken-object-level-auth, ...)
  • MCP-audit rules (MCP-001 ... MCP-006)
  • Extension-audit rules (EXT-001 ... EXT-003)
  • Supply-chain compromise families (SUP-COMPROMISE-001 ... SUP-COMPROMISE-005)

Same content the CLI vulkro explain <ID> produces, rendered as portable markdown (no ANSI).

list_rules()

Enumerate every rule Vulkro knows about. Returns { id, title, owasp_category, owasp_category_display, severity, description, rule_page } for each. The OWASP catalogue, MCP-audit rules, extension-audit rules, and supply-chain compromise families are all included in one call.

get_findings({scan_id, severity?})

Re-read findings from a prior scan_project call using the returned scan_id. Optionally filter by severity.

FieldTypeRequiredDescription
scan_idstringyesA scan_id returned by a prior scan_project call in the same MCP session.
severity"critical" | "high" | "medium" | "low" | "info"noWhen set, return only findings at this severity. Case-insensitive.

Wiring it up

Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS), ~/.config/Claude/claude_desktop_config.json (Linux), or %APPDATA%\Claude\claude_desktop_config.json (Windows) and add a mcpServers.vulkro entry:

{
"mcpServers": {
"vulkro": {
"command": "vulkro",
"args": ["mcp", "serve"]
}
}
}

Restart Claude Desktop. The tool picker should now list five vulkro_* tools. Ask the assistant "scan this project" with a project directory open and the model will call scan_project with the path.

Cursor

Edit ~/.cursor/mcp.json and use the same shape:

{
"mcpServers": {
"vulkro": {
"command": "vulkro",
"args": ["mcp", "serve"]
}
}
}

Restart Cursor.

Windsurf

Edit ~/.windsurf/mcp.json (or ~/.codeium/windsurf/mcp_config.json on older versions):

{
"mcpServers": {
"vulkro": {
"command": "vulkro",
"args": ["mcp", "serve"]
}
}
}

Restart Windsurf.

Continue (VS Code)

Continue reads MCP server config from ~/.continue/mcp.json. The shape is identical:

{
"mcpServers": {
"vulkro": {
"command": "vulkro",
"args": ["mcp", "serve"]
}
}
}

Reload the Continue extension.

VS Code MCP client

The VS Code MCP client reads from ~/.vscode/mcp_settings.json (or ~/.vscode-server/mcp_settings.json in Remote setups). Same shape.

Transport details

Stdio is the default because every major MCP host launches its servers as child processes and talks JSON-RPC over the standard streams. The server reads one JSON-RPC request per line on stdin and writes one response per line on stdout; stderr is reserved for the optional VULKRO_MCP_LOG=1 trace stream.

The SSE transport (opt-in via --port) binds an HTTP listener on 127.0.0.1:<port> only (never 0.0.0.0). Clients POST JSON-RPC requests to /messages and read responses from a long-lived GET /sse stream. The server emits an event: endpoint SSE message on connection with the POST endpoint path; subsequent responses arrive as event: message payloads.

Environment variables

NameEffect
VULKRO_MCP_LOG=1Emit per-request trace lines on stderr. Off by default so the stdio JSON-RPC stream stays clean of side-band output.
VULKRO_OFFLINE=1Disable any outbound HTTP call during scans triggered through the MCP surface. Same semantics as the top-level scan subcommand.

Other VULKRO_* variables honoured by vulkro scan (e.g. VULKRO_QUIET_PRESET_HINT, VULKRO_GIT_BLAME, VULKRO_AUTH_MIDDLEWARE_NAMES) apply transparently to scans triggered through the MCP surface.

Read-only by design

There is no apply_fix, no write_file, no tool that mutates the user's repo. Read-only is a brand promise: vulkro fix already prints diffs to stdout for the user to apply by hand, and the MCP surface holds that line.

  • Desktop console: the same scanner exposed through a local web app instead.
  • vulkro mcp-audit: audit MCP host configs for supply-chain and credential-handling risks (the inverse direction: scan the configs that launch MCP servers, rather than be one).
  • vulkro explain: the per-rule explainer that backs the MCP explain tool.