Skip to content

MCP ​

VulnGraph is also a Model Context Protocol server, so an AI agent (Cursor, Claude, Grok and others) can ask about the fleet, read the plan and record progress with the same API key it would use for the API.

Endpoint and auth ​

Endpointhttps://api.vulngraph.igentify.in/v1/mcp
AuthAuthorization: Bearer vg_live_… (an API key); a signed-in session also works
TransportStreamable HTTP, POST only, one JSON-RPC message per request, JSON answers (no SSE, no sessions)
Protocol2025-06-18 (also accepts 2025-03-26)
Methodsinitialize, notifications/initialized, ping, tools/list, tools/call
  • Send Content-Type: application/json and an Accept header that allows application/json. After initialize, clients send MCP-Protocol-Version; an unsupported value answers 400.
  • Browser requests must come from the VulnGraph web app (Origin check); other origins get 403. Requests without an Origin header (CLI tools, agents) are fine.
  • GET answers 405. Notifications answer 202 with no body.

Cursor ​

Put the key in an environment variable (never in the file), for example export VULNGRAPH_API_KEY=$(cat ~/.vulngraph/mcp-agent.key), then add this to ~/.cursor/mcp.json (or .cursor/mcp.json in a project):

json
{
  "mcpServers": {
    "vulngraph": {
      "url": "https://api.vulngraph.igentify.in/v1/mcp",
      "headers": { "Authorization": "Bearer ${env:VULNGRAPH_API_KEY}" }
    }
  }
}

The key page in the web app shows the same snippet under Use with MCP.

Other clients (stdio) ​

Clients that only start local stdio servers can use the mcp-remote bridge:

bash
sh -c 'exec npx -y mcp-remote https://api.vulngraph.igentify.in/v1/mcp \
  --header "Authorization:Bearer $(cat ~/.vulngraph/mcp-agent.key)"'

To try the server from a terminal:

bash
npx -y @modelcontextprotocol/inspector@latest --cli https://api.vulngraph.igentify.in/v1/mcp \
  --transport http --method tools/list \
  --header "Authorization: Bearer $VULNGRAPH_API_KEY"

Tools ​

There are 25 tools. Each one is one API endpoint and needs that endpoint's scope. tools/list shows only the tools your key's scopes allow, and every call is checked again. Read tools are marked readOnlyHint; write tools are marked non-destructive, and the two step tools are idempotent.

ToolScopeSame asUse for
portfolio_summaryfindings:readGET /portfolio/summaryHow bad is the fleet right now?
portfolio_start_herefindings:readGET /portfolio/start-hereWhat should we fix first?
portfolio_servicefindings:readGET /portfolio/serviceHow exposed is service X?
portfolio_advisoryfindings:readGET /portfolio/advisoryAre we affected by CVE/GHSA Y?
portfolio_packagefindings:readGET /portfolio/packageWhere do we use package Z?
portfolio_advisoriesfindings:readGET /portfolio/advisoriesList critical CVEs, or those with no fix
portfolio_nextfindings:readGET /portfolio/nextNext plan steps and what blocks them
portfolio_resolvefindings:readGET /portfolio/resolveUnsure how a name is spelled
portfolio_changesfindings:readGET /portfolio/changesWhat changed since the last scan?
portfolio_trendfindings:readGET /portfolio/trendAre we getting better?
list_profilesprofiles:readGET /profilesValid profile names
get_profileprofiles:readGET /profiles/{name}Repositories of a profile
list_runsruns:readGET /runsScan history
get_latest_runruns:readGET /runs/latestThe run answers come from; is a scan running?
get_runruns:readGET /runs/{runId}Poll one run
list_eventsruns:readGET /eventsCatch up on run and step changes
get_planplans:readGET /runs/{runId}/planThe plan, paged; decide_only for open choices
list_recorded_stepsplans:readGET /runs/{runId}/stepsWhat has been decided, which PRs are open
get_stepplans:readGET /runs/{runId}/steps/{rank}One step with its numbered Decide options
get_sketchsketches:readGET /runs/{runId}/sketchThe draft PR for a step (rank), or paged
get_run_logslogs:readGET /runs/{runId}/logsWhy did a run fail?
download_artifactartifacts:downloadGET /runs/{runId}/artifacts/{path}A whole run file
record_decisiondecisions:writePOST /runs/{runId}/steps/{rank}/decisionRecord the chosen Decide option
set_step_statusstep-status:writePOST /runs/{runId}/steps/{rank}/statusRecord in progress, PR opened or merged, skipped
start_runruns:createPOST /runsStart a new scan (only when asked)

Argument names follow the API parameters in snake_case (run_id, rank, pr_url, include_unfinished, decide_only, sketch_mode). Every tool publishes its JSON input schema in tools/list.

Results ​

  • A result is one text item holding compact JSON, the same body the API endpoint returns.
  • Portfolio tools keep the freshness fields (data_as_of, served_at, run_id, cached) and stay under 8 KB.
  • get_plan (up to 25 steps per page by default, up to 100) and get_sketch (10 per page, up to 50) return total_steps and next_cursor; pass next_cursor as cursor for the next page. A page holds fewer steps when they are large. The plan summary comes on the first page, without the per-repository CI time and reviewer maps (each step carries its own).
  • get_run_logs pages with nextCursor and prevCursor (100 lines by default).
  • download_artifact returns small text files (up to 32 KB) inline; for larger files it returns a download URL valid for 5 minutes.

Errors ​

CaseWhat you get
Unknown tool, invalid arguments (for example a bad rank or state)JSON-RPC error -32602 with a message naming the problem
Tool not allowed for the keyJSON-RPC error -32602, this key cannot use <tool>: missing scope <scope>
The endpoint answered an error (unknown run, 409, 429, …)A normal result with isError: true and the API error body as text
Answer too largeisError: true with a hint to narrow the request or page
Unknown methodJSON-RPC error -32601
Bad JSON, batch request, bad jsonrpcJSON-RPC error -32700 or -32600 with HTTP 400
Bad or missing keyHTTP 401 before any JSON-RPC handling

Limits and activity ​

Tool calls count against the key's rate limits exactly like the matching endpoint: reads as reads, record_decision and set_step_status as writes, start_run against runs per day. Protocol messages (initialize, tools/list, ping) do not count. Every tool call appears in the key's activity with the tool name.

VulnGraph documentation