Security tooling has spent two decades optimizing for humans at terminals. CVE databases, exploit search engines, and threat intel feeds all speak CLI or web scraper. VulnFeed packages nine of these tools behind a Model Context Protocol server, exposing them as structured functions an agent can call. The interesting part is not the tools themselves but the adapter layer: how you handle rate limits, credential flow, state management, and partial failures when an LLM is making the requests instead of a DevOps engineer.
What VulnFeed Actually Does
VulnFeed reads your lockfile (package-lock.json, requirements.txt, go.sum), queries NVD and GitHub Advisory databases, filters to vulnerabilities in your actual dependency tree, scores them with EPSS (Exploit Prediction Scoring System), and returns fix recommendations. The MCP server exposes this as nine discrete tools:
scan_project- Parse lockfile, return prioritized CVE listcheck_package- Single package lookup across registrieslookup_cve- Fetch CVE details from NVDmonitor_project- Register project for continuous checkscheck_alerts- Poll for new CVEs since last scanupdate_deps- Generate upgrade commands for affected packageslist_projects- Enumerate monitored projectsget_epss_score- Fetch exploit probability for a CVEsearch_exploits- Query exploit databases
Each tool returns structured JSON. The agent decides which to call and in what order.
MCP as the Adapter Layer
Model Context Protocol defines how agents discover and invoke tools. The server publishes a manifest listing available functions, their parameters, and return schemas. The agent sends a tool call request with arguments. The server executes, returns typed data.
For VulnFeed, this means wrapping HTTP calls to NVD, GitHub’s GraphQL API, and EPSS feeds in a function signature. The MCP server becomes the translation layer between LLM function calling and external security APIs.
Key architectural decisions:
- Stateless tool calls - Each invocation is independent. No session state between
scan_projectandcheck_alerts. The agent must pass context (project ID, previous scan timestamp) explicitly. - Synchronous execution - Tools block until upstream APIs respond. No async polling or webhook callbacks. If NVD is slow, the agent waits.
- Credential injection - API keys for paid tiers live in the MCP server config, not in agent prompts. The server authenticates to upstream services, the agent just calls tools.
Rate Limiting and Quota Management
NVD’s public API allows 5 requests per 30 seconds without a key, 50 with one. GitHub Advisory has no published rate limit but throttles aggressively. EPSS data is a daily static file.
VulnFeed’s MCP server handles this with:
- Local caching - CVE details and EPSS scores cached for 24 hours. Repeated lookups hit local storage.
- Request coalescing - If two agents call
lookup_cvefor the same CVE within 5 seconds, the server deduplicates the upstream request. - Backoff on 429 - Exponential retry with jitter when rate limited. The tool call returns an error after three attempts.
The free tier enforces 10 scans per day per user. The paid tier is unlimited but still subject to upstream rate limits. The server tracks usage in a SQLite database keyed by user ID.
What breaks:
- If an agent loops on
scan_projectwithout checking the response, it burns through the daily quota in seconds. - If NVD is down, every CVE lookup fails. The agent must handle missing data gracefully or halt.
- If the MCP server crashes mid-scan, there is no resume mechanism. The agent must restart from scratch.
Authentication and Credential Flow
The agent does not hold API keys. The MCP server config file contains:
upstream:
nvd:
api_key: "your-nvd-key"
github:
token: "ghp_your-token"
user_auth:
method: "api_key"
header: "X-VulnFeed-Key"
When the agent calls a tool, it includes its VulnFeed API key in the request header. The MCP server validates this against its user database, then uses its own credentials to call NVD or GitHub.
This keeps secrets out of agent memory and logs. The tradeoff is that the MCP server becomes a credential chokepoint. If it is compromised, all upstream API keys leak.
Security boundaries:
| Layer | Trust Boundary | Failure Mode |
|---|---|---|
| Agent | Untrusted | Can call any exposed tool, cannot forge credentials |
| MCP Server | Trusted | Validates user API keys, holds upstream secrets |
| Upstream APIs | External | Rate limit, timeout, or return stale data |
| Local Cache | Trusted | May serve outdated CVE data if not invalidated |
Tool Response Structure
Each tool returns JSON matching a predefined schema. For scan_project:
{
"status": "success",
"scanned_packages": 847,
"vulnerabilities": [
{
"cve_id": "CVE-2024-29041",
"package": "express@4.17.1",
"severity": "HIGH",
"epss_score": 0.732,
"fix_version": "4.21.0",
"description": "Open redirect via malicious URL in res.location()"
}
],
"scan_timestamp": "2026-06-18T08:04:19Z"
}
If the scan fails partway through (NVD times out after 200 packages), the response includes:
{
"status": "partial",
"scanned_packages": 200,
"vulnerabilities": [],
"error": "NVD API timeout after 30s",
"resume_token": "pkg:847:200"
}
The agent can retry with the resume token, but VulnFeed does not currently implement resume logic. The token is reserved for future use.
Why this matters:
- Agents that expect complete data will misinterpret partial scans as clean.
- Agents that retry without checking
statuswill duplicate work. - Agents that log raw responses will leak package names and versions.
Observability and Debugging
The MCP server logs every tool call with:
- User ID
- Tool name
- Arguments (sanitized to remove sensitive paths)
- Response status
- Upstream API latency
- Cache hit/miss
Logs go to stdout in JSON format. No built-in tracing or distributed context propagation. If an agent makes 50 tool calls across 10 minutes, correlating them requires matching timestamps and user IDs manually.
Observability gaps:
- Why the agent chose to call
check_packageinstead ofscan_project. - How many retries happened before a tool call succeeded.
- Whether the agent acted on the returned CVE data or ignored it.
VulnFeed does not instrument the agent’s decision loop. You see tool calls and responses, not reasoning.
Deployment Shape
The MCP server runs as a standalone HTTP service. You can deploy it:
- Locally - Agent and server on the same machine, localhost communication.
- Centralized - One server, many agents, API key authentication.
- Embedded - Server bundled into the agent’s container, no network hop.
VulnFeed’s hosted version is centralized. You get an API key, configure your agent to call https://vulnfeed.novadyne.ai/mcp, and the server handles everything.
Failure modes:
- If the server is unreachable, all tool calls fail immediately. No local fallback.
- If the server is slow, agents wait. No timeout configuration exposed to users.
- If the server is overloaded, requests queue. No backpressure signal to agents.
When State Leaks Between Calls
The monitor_project tool registers a project for continuous scanning. It stores the lockfile hash and last scan timestamp in the server’s database. When you call check_alerts, the server compares the current CVE feed against the stored snapshot.
This is stateful. The server remembers your project across sessions. If the database is lost, all monitoring stops. If two agents monitor the same project, they share the same alert stream.
Implications:
- Agents cannot assume
check_alertsis idempotent. Calling it twice may return different results if new CVEs appeared. - Agents cannot delete monitored projects via tool calls. You must use the web UI or API.
- If the server migrates to a new database, all monitoring history is lost unless you export and restore.
Technical Verdict
Use VulnFeed’s MCP server when:
- You need to scan 50+ dependencies and prioritize by EPSS exploit probability without writing custom NVD integration.
- Your agents can tolerate 2-5 second tool call latency for upstream API queries.
- You accept centralized credential management and a single point of failure for security tooling.
- Your workflow includes retry logic for partial scan failures and rate limit backoff.
- You want continuous monitoring with daily CVE feed updates and can poll
check_alertsperiodically.
Avoid it when:
- You require sub-second tool call latency or need to scan dependencies in real-time CI pipelines.
- You need distributed tracing or visibility into agent reasoning (why it called which tool).
- You must resume partial scans mid-loop without restarting from scratch.
- You cannot accept a centralized server as a credential chokepoint or single point of failure.
- Your agents run in air-gapped environments without internet access to upstream CVE feeds.
The MCP server pattern works well for wrapping legacy security tools, but it inherits their latency, rate limits, and failure modes. The adapter layer is thin. When NVD is down, your agent is blind.