Skip to main content
Glama
cyanheads

@cyanheads/cisa-cybersecurity-mcp-server

by cyanheads

Version License Docker MCP SDK npm TypeScript Bun

Install in Claude Desktop Install in Cursor Install in VS Code

Framework

Public Hosted Server: https://cisa-cybersecurity.caseyjhand.com/mcp


Overview

CISA's vulnerability data in one place: the Known Exploited Vulnerabilities catalog with its remediation deadlines, per-CVE SSVC decision points, ICS advisories back to 2010, and CISA's latest alerts. Check a scan's worth of CVEs against KEV in one call, find what's overdue for a vendor, and work out BOD 26-04 timelines. No API key required.

Tools

Tool

Description

cisa_list_reference

Decode the input vocabulary (BOD 26-04 timelines, KEV fields, SSVC values, sectors, ID formats, severity bands) and report what data the server holds

cisa_check_cve_status

Check up to 200 CVE IDs against KEV in one call: deadlines, overdue status, ransomware and forensic-triage flags, cited directive

cisa_search_kev

Search KEV by vendor, product, CWE, date added, due date, overdue status, ransomware linkage, forensic-triage tier, or directive

cisa_get_ssvc

Fetch CISA's published SSVC decision points per CVE and compute the BOD 26-04 timeline for a stated asset exposure

cisa_search_ics_advisories

Search ICS advisories by vendor, product, CVE, CWE, KEV membership, CVSS, severity, sector, series, dates, or free text

cisa_get_advisory

Read one ICS advisory: affected product versions, per-CVE CVSS and CWE, remediations, sectors, revision history

cisa_get_alerts

List CISA's latest items from its advisory, alert, or ICS advisory feed

Resources

Resource

Description

cisa://kev/{cveId}

One KEV catalog entry by CVE ID

cisa://advisory/{advisoryId}

One ICS advisory, flattened from CSAF 2.0

Both resources are fully covered by the tools above, so a tool-only client loses nothing.

Related MCP server: Security Recipes

Capability reference

cisa_list_reference tool

  • One required topic: directives, kev_fields, ssvc_values, sectors, advisory_id_formats, severity_bands, or sources; reads in-process state only, so it answers while other tools are failing

  • directives adds timelineTable (all 16 rows of BOD 26-04 Table 1, with remediationTimelineDays and forensicTriageRequired), definitions, and supersedes; sources reports the KEV catalogVersion, the advisory index's ready / documentCount / syncStatus, the SSVC cache TTL, and the cached feed windows


cisa_check_cve_status tool

  • Up to 200 cveIds per call, answered from the cached KEV snapshot with no upstream request; a CVE outside KEV comes back inKev: false, not as an error

  • Per CVE: dateAdded, dueDate, daysUntilDue, overdue, requiredAction, knownRansomwareCampaignUse, forensicTriage, cwes[], every URL in the entry's notes as references[] typed by kind, and a three-state directive (BOD 26-04, BOD 22-01, or null); the response echoes the catalog snapshot and the asOf date the deadlines were computed against

  • detail: "summary" trims each in-KEV record to the triage fields (dates, deadline status, directive, vendor and product labels, ransomware and forensic-triage flags), which keeps a full 200-CVE batch compact; full is the default


cisa_search_kev tool

  • Filters AND together: vendorProject and product (CISA's own labels, not CPE names), nameContains, cwe, cveIdPrefix, dateAddedFrom / dateAddedTo, dueBefore / dueAfter, overdue, ransomware, forensicTriage, directive (BOD 26-04 / BOD 22-01 / none); up to 100 per page (default 25) with an opaque cursor; sorts by dateAdded (default) or dueDate

  • Reports totalCount and appliedFilters; a zero-hit result names the filter responsible and what dropping it restores. nameContains searches a-z and 0-9 after folding case and accents, and the notice names any other characters it dropped

  • Typed errors: catalog_unavailable (retryable), invalid_date_range, empty_search_text


cisa_get_ssvc tool

  • Up to 50 cveIds per call, each a live Vulnrichment lookup, plus assetExposure: publicly_exposed, not_publicly_exposed, or unknown (default, returns both arms)

  • Per CVE: found, exploitation, automatable, technicalImpact, cvss and cwes where CISA published them, and bod2604.timelines[] (tableRow, remediationTimelineDays, forensicTriageRequired); a KEV entry adds kevAssigned, plus assignmentAgrees when an exposure was stated

  • A CVE with no enrichment is found: false with guidance; enrichment_source_unavailable (retryable) fires only when every fetch fails


cisa_search_ics_advisories tool

  • Full-text q over titles, vendor names, and product names, plus vendor, product (case-insensitive substrings), cve, cwe, inKev, cvssMin / cvssMax, severity, sector, series (ICSA / ICSMA), publisher (coordinator / other), publishedFrom / publishedTo, revisedFrom / revisedTo; sorts by revised (default), published, maxCvss, or relevance (needs q); up to 50 per page (default 20) with an opaque cursor

  • Results carry advisoryId, up to 20 cves with cveCount, kevCves, maxCvss with severityDerived, sectors, url, csafUrl, and attribution, plus totalCount and appliedFilters; a zero-hit result names the filter responsible. If the KEV snapshot isn't loaded, kevCves is left out and says so

  • Typed errors: mirror_not_ready, mirror_busy, and catalog_unavailable (retryable), mirror_unavailable, invalid_cvss_range, invalid_date_range, relevance_sort_without_query, empty_search_text


cisa_get_advisory tool

  • advisoryId (optional revision suffix), optional sections (advisory, summary, products, vulnerabilities, revisionHistory, references, acknowledgments), cves to pick vulnerability entries, and productIds to pick exact, case-sensitive product definitions; cves and productIds imply their sections

  • Returns kind: "full", or kind: "outline" (per-section byte sizes plus the CVE IDs) when a read without sections exceeds 24,000 bytes; re-call with sections

  • An ID not in the index returns found: false with guidance, indexCheckpoint, and indexLastSyncedAt; the guidance notes when the advisory may be newer than the index

  • Typed errors: mirror_not_ready and mirror_busy (retryable), mirror_unavailable, unknown_section, unknown_cve, cves_need_vulnerabilities_section, unknown_product_id, product_ids_need_products_section


cisa_get_alerts tool

  • feed: advisories (default), alerts, or ics; limit up to 30, the upstream window size; since (YYYY-MM-DD) filters within that window and cannot reach past it

  • Items carry title, link, pubDate, summary (HTML stripped, capped at 1,200 characters, flagged by summaryTruncated), and on ICS items an advisoryId for cisa_get_advisory; window reports itemCount, oldest, newest, and upstreamWindowSize

  • Every response carries fetchedAt and stale; if a refresh fails, the last window is returned as stale with retry guidance, and a stale empty result doesn't prove nothing was published. With no cached window, feed_unavailable (retryable)


cisa://kev/{cveId} resource

  • One KEV record as application/json, the same shape as a cisa_check_cve_status result under the default detail: "full"; a CVE not in KEV is a not-found error

  • Listing returns the 30 most recently added entries; cveId completes from the snapshot, up to 100 suggestions


cisa://advisory/{advisoryId} resource

  • One flattened advisory as application/json, with the same 24,000-byte outline-on-overflow as cisa_get_advisory; the template takes no sections, cves, or productIds, so follow an outline up with the tool

  • Listing returns the 30 most recently revised advisories; advisoryId completes from the index, up to 100 suggestions

Features

Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.

CISA-specific:

  • Four public sources, no account or key: the KEV JSON feed, Vulnrichment, the CSAF ICS advisory repository, and CISA's RSS feeds

  • None of them offers search, so filters run locally: KEV from an in-memory snapshot polled for changes, ICS advisories from a SQLite index with FTS5. Date filters take real calendar dates in YYYY-MM-DD

  • A bad KEV refresh is rejected and the last valid snapshot stays in use; with none, reads return retryable catalog_unavailable

  • The KEV, SSVC, and alert tools serve from the first request while the advisory index seeds in the background

  • BOD 26-04 Table 1 ships as data, so a computed timeline is a table lookup over published decision points. It is not a compliance determination, and it is reported beside CISA's KEV due date, never reconciled with it

Agent-friendly output:

  • Provenance on every response: the KEV catalog version and asOf date, the index checkpoint behind a search, and url, csafUrl, and attribution on every advisory

  • Discriminated outputs: a three-state directive, typed references[].kind, found / inKev booleans, severityDerived on a band upstream never published, and typed error reasons with recovery hints

  • Empty results and upstream gaps explain themselves: a zero-hit search names the filter responsible, and filters that hit a known gap (sector notes only from 2017, CVSS v2-only advisories, no KEV revision timestamps) say so. See Known Limitations

Getting started

Public Hosted Instance

A public instance is available at https://cisa-cybersecurity.caseyjhand.com/mcp — no installation required. Point any MCP client at it via Streamable HTTP:

{
  "mcpServers": {
    "cisa-cybersecurity-mcp-server": {
      "type": "streamable-http",
      "url": "https://cisa-cybersecurity.caseyjhand.com/mcp"
    }
  }
}

Self-Hosted / Local

Add the following to your MCP client configuration file. No API key is required.

{
  "mcpServers": {
    "cisa-cybersecurity-mcp-server": {
      "type": "stdio",
      "command": "bunx",
      "args": ["@cyanheads/cisa-cybersecurity-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with npx (no Bun required):

{
  "mcpServers": {
    "cisa-cybersecurity-mcp-server": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@cyanheads/cisa-cybersecurity-mcp-server@latest"],
      "env": {
        "MCP_TRANSPORT_TYPE": "stdio",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}

Or with Docker:

{
  "mcpServers": {
    "cisa-cybersecurity-mcp-server": {
      "type": "stdio",
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "MCP_TRANSPORT_TYPE=stdio",
        "-v", "cisa-mirror:/usr/src/app/.mirror",
        "ghcr.io/cyanheads/cisa-cybersecurity-mcp-server:latest"
      ]
    }
  }
}

For Streamable HTTP, set the transport and start the server:

MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp

Prerequisites

  • Bun v1.4.0 or higher (or Node.js v24+).

  • No credentials. Every upstream source is keyless and public.

Installation

  1. Clone the repository:

git clone https://github.com/cyanheads/cisa-cybersecurity-mcp-server.git
  1. Navigate into the directory:

cd cisa-cybersecurity-mcp-server
  1. Install dependencies:

bun install

Configuration

Every variable is optional; the server runs correctly with none of them set.

Variable

Description

Default

CISA_KEV_REFRESH_CRON

Cron for the KEV refresh poll; off disables it.

*/30 * * * *

CISA_CSAF_MIRROR_PATH

Path to the ICS advisory SQLite index.

<user cache dir>/cisa-cybersecurity-mcp-server/csaf.sqlite3

CISA_CSAF_MIRROR_AUTO_INIT

Seed the index in the background on first run.

true

CISA_CSAF_REFRESH_CRON

Cron for the advisory refresh (also runs once at startup); off disables both.

17 */6 * * *

CISA_VULNRICHMENT_CACHE_TTL_SECONDS

TTL for a cached SSVC record.

21600

CISA_FEED_CACHE_TTL_SECONDS

TTL for a parsed RSS feed window.

900

CISA_HTTP_TIMEOUT_MS

Per-request timeout for every upstream fetch, in ms.

30000

MCP_TRANSPORT_TYPE

Transport: stdio or http.

stdio

MCP_HTTP_PORT

HTTP server port.

3010

MCP_SESSION_MODE

HTTP session mode: stateless, stateful, or auto.

stateless

MCP_AUTH_MODE

Authentication: none, jwt, or oauth.

none

MCP_LOG_LEVEL

Log level (debug, info, warning, error, etc.).

info

LOGS_DIR

Directory for log files (Node.js only).

<project-root>/logs

STORAGE_PROVIDER_TYPE

Storage backend for the SSVC cache: in-memory, filesystem, or supabase.

in-memory

OTEL_ENABLED

Enable OpenTelemetry.

false

See .env.example for the full list of optional overrides.

Running the server

Local development

  • Build and run:

    # One-time build
    bun run rebuild
    
    # Run the built server
    bun run start:stdio
    # or
    bun run start:http
  • Run checks and tests:

    bun run devcheck   # Lint, format, typecheck, security
    bun run test       # Vitest test suite
    bun run lint:mcp   # Validate MCP definitions against spec

ICS advisory index

The two ICS tools and the advisory resource read a local SQLite index of the CSAF corpus at CISA_CSAF_MIRROR_PATH, defaulting to your user cache directory. On first run the server builds it in the background; until it is ready those surfaces return a retryable mirror_not_ready, and cisa_list_reference with topic sources shows progress. If the path cannot be opened, the ICS surfaces fail with a non-retryable mirror_unavailable and every other tool keeps working.

Processes sharing one index take turns syncing it. For containers, CI, or seeding out of band (CISA_CSAF_MIRROR_AUTO_INIT=false, and CISA_CSAF_REFRESH_CRON=off to leave refreshes to you), run the scripts directly:

bun run mirror:init      # full build, idempotent, safe to re-run after an interrupt
bun run mirror:refresh   # requires a completed mirror:init; fetches changed documents only
bun run mirror:verify    # readiness, sync status, checkpoint, count, content version, SQLite integrity; non-zero on failure

A transient SQLite lock returns retryable mirror_busy; retry shortly. After a partial refresh, applied rows stay readable and failed documents are retried next time; sources reports syncStatus: partial and failedDocumentCount, and mirror:refresh and mirror:verify exit non-zero.

Docker

docker build -t cisa-cybersecurity-mcp-server .
docker run --rm -p 3010:3010 -v cisa-mirror:/usr/src/app/.mirror cisa-cybersecurity-mcp-server

The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/cisa-cybersecurity-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them. The image sets CISA_CSAF_MIRROR_PATH=/usr/src/app/.mirror/csaf.sqlite3; mount a volume over /usr/src/app/.mirror so the advisory index survives a container recreation; the image ships the mirror:* scripts for docker exec <container> bun run mirror:refresh.

Project structure

Directory

Purpose

src/index.ts

createApp() entry point: wires the four services, schedules the refresh jobs, registers the surface.

src/config

Server-specific environment variable parsing and validation with Zod.

src/mcp-server/tools

Tool definitions (*.tool.ts).

src/mcp-server/resources

Resource definitions (*.resource.ts).

src/mcp-server/schemas

Output schemas and renderers shared by the KEV and advisory tools and resources.

src/reference

Static reference data: BOD 26-04 Table 1, canonical sector names, CVSS bands.

src/services/kev-catalog

KEV JSON feed: snapshot, derived indexes, conditional refresh.

src/services/vulnrichment

Per-CVE SSVC enrichment fetch with a TTL cache.

src/services/csaf-mirror

The ICS advisory index: schema, ingest, normalization, queries.

src/services/cisa-feeds

The three RSS feeds, parsed and cached on a TTL.

scripts/

Build, checks, and the mirror:* commands.

tests/

Unit, integration, fuzz, and smoke tests mirroring src/.

Development guide

See CLAUDE.md/AGENTS.md for development guidelines and architectural rules, and docs/design.md for the as-built specification. The short version:

  • Handlers throw, framework catches — no try/catch in tool logic

  • Use ctx.log for request-scoped logging, ctx.state for tenant-scoped storage

  • Register new tools and resources via the barrels in src/mcp-server/*/definitions/index.ts

  • Wrap external sources: validate raw → normalize to a domain type → return the output schema; never fabricate a field the upstream omitted

Contributing

Issues are welcome. Run checks and tests before submitting:

bun run devcheck
bun run test

License

Apache-2.0 — see LICENSE for details.

The license covers this code, not the data it serves. KEV entries are US Government work in the public domain and Vulnrichment is CC0-1.0, but the CSAF repository declares no license and many advisories republish vendor text, so check reuse rights at each advisory's url before redistributing it. This project is not affiliated with or endorsed by CISA or the Department of Homeland Security.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides CVE lookup, search, and exploit intelligence from public vulnerability sources (NVD, CISA KEV, EPSS) for AI agents to produce remediation guidance without consuming LLM tokens for data fetching.
    1
    MIT
  • F
    license
    Not graded
    quality
    B
    maintenance
    Enables querying official CVE List V5 records enriched with CISA KEV data, including single or batch CVE lookups and required-action guidance for known exploited vulnerabilities.
    -
  • A
    license
    A
    quality
    A
    maintenance
    Enables any MCP client to look up CVE intelligence — severity summaries, filtered searches, and full per-CVE detail fusing NVD, MITRE-CNA pre-NVD, CISA KEV, EPSS, and GitHub GHSA data — alongside a Shodan-derived internet-exposure footprint showing how many internet-facing services run a version mapping to a given CVE. It is free, keyless, and read-only, and distinguishes verified zeros from unassessed or failed lookups.
    16
    765 npm
    8
    MIT