osv-advisory-mcp-server

v0.3.0 pre-1.0

Query OSV.dev for package vulnerabilities, batch-audit dependency lists, and fetch full advisory records via MCP. STDIO or Streamable HTTP.

osv-advisory.caseyjhand.com/mcp
claude mcp add --transport http osv-advisory-mcp-server https://osv-advisory.caseyjhand.com/mcp
codex mcp add osv-advisory-mcp-server --url https://osv-advisory.caseyjhand.com/mcp
{
  "mcpServers": {
    "osv-advisory-mcp-server": {
      "url": "https://osv-advisory.caseyjhand.com/mcp"
    }
  }
}
gemini mcp add --transport http osv-advisory-mcp-server https://osv-advisory.caseyjhand.com/mcp
{
  "mcpServers": {
    "osv-advisory-mcp-server": {
      "command": "bunx",
      "args": [
        "mcp-remote",
        "https://osv-advisory.caseyjhand.com/mcp"
      ]
    }
  }
}
{
  "mcpServers": {
    "osv-advisory-mcp-server": {
      "type": "http",
      "url": "https://osv-advisory.caseyjhand.com/mcp"
    }
  }
}
curl -X POST https://osv-advisory.caseyjhand.com/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"curl","version":"1.0.0"}}}'

Tools

5

osv_list_ecosystems

Return the supported ecosystem identifier strings for osv_query_package and osv_query_batch: every ecosystem the OSV schema names that OSV.dev accepts at query time, plus GIT, as verified on 2026-09-24. Ecosystem strings are case-sensitive exact matches — passing "pypi" instead of "PyPI" returns an error from the API. Use this tool to discover valid ecosystem strings before querying, or to verify an ecosystem identifier from a lockfile format. The list is static and may lag ecosystems added after that date.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "osv_list_ecosystems",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {},
  "additionalProperties": false
}
view source ↗

osv_query_package

Query known vulnerabilities for a single package version using {name, ecosystem, version} or {purl, version?}; supply exactly one embedded or separate version. Returns all matching OSV advisories with severity (CVSS vectors), CVE aliases, affected version ranges, and the fixed versions listed for the queried package. Use osv_list_ecosystems to validate the ecosystem string before querying — ecosystem strings are case-sensitive exact matches and an invalid value returns an error, not empty results. For overflow, repeat the original input with page: overflow.page. Continue the same path with offset: page.nextOffset and revision: page.revision until nextOffset is null. Retrieve each entries[].deferred.path separately at offset zero without a revision. Do not pass the output page object as input. Set page.advisoryId to an announced ID to fetch its fields with fixes and severity for the queried package; retain advisoryId on subsequent pages. Pages are fresh lookups; restart a changed node without a revision. Transmission overflow and upstream truncated are separate; neither confirms clean.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "osv_query_package",
    "arguments": {}
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "pattern": "\\S",
      "description": "Exact package name in its ecosystem."
    },
    "ecosystem": {
      "type": "string",
      "pattern": "\\S",
      "description": "Case-sensitive ecosystem identifier from osv_list_ecosystems."
    },
    "version": {
      "type": "string",
      "pattern": "\\S",
      "description": "Exact package version, never a range."
    },
    "purl": {
      "description": "PURL alternative to name and ecosystem; supply one embedded or separate version.",
      "type": "string"
    },
    "page": {
      "description": "Repeat the original input with page: overflow.page first; later select path, offset: page.nextOffset and revision: page.revision. Retain advisoryId when set.",
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "maxLength": 1024,
          "pattern": "^(?:\\/(?:[^~]|~[01])*)?$",
          "description": "Field pointer announced by overflow or entries[].deferred.path; empty string selects the root. Keep the same path while following nextOffset."
        },
        "offset": {
          "default": 0,
          "description": "Start at zero; on later calls set this to the previous page.nextOffset until it is null. Text offsets count Unicode code points.",
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "revision": {
          "description": "Use page.revision only when continuing the same path. Omit on the first call to any deferred child path; restart without it after stale_page_revision.",
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        },
        "advisoryId": {
          "description": "ID from this query’s advisory list. Retain this ID when continuing its fields with fixes and severity for the original package.",
          "type": "string",
          "maxLength": 1024
        }
      },
      "required": [
        "path",
        "offset"
      ],
      "additionalProperties": false
    }
  },
  "additionalProperties": false
}
view source ↗

osv_get_vulnerability

Fetch the full advisory record for an OSV vulnerability ID. Returns the complete record: summary, full details text, CVE aliases, all affected packages and version ranges, fix versions, CVSS severity vectors, CWE weakness IDs, and references. Use when osv_query_package or osv_query_batch returns a vuln ID and you need the full advisory context — affected packages or remediation guidance. For overflow, repeat the original input with page: overflow.page. Continue the same path with offset: page.nextOffset and revision: page.revision until nextOffset is null. Retrieve each entries[].deferred.path separately at offset zero without a revision. Do not pass the output page object as input. Every page is a fresh lookup; restart a changed node without a revision. Transmission overflow and upstream truncation are separate; neither confirms clean.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "osv_get_vulnerability",
    "arguments": {
      "id": "<id>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "page": {
      "description": "Repeat id with page: overflow.page first; then select path, offset: page.nextOffset, revision: page.revision. Start deferred child paths without a revision.",
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "maxLength": 1024,
          "pattern": "^(?:\\/(?:[^~]|~[01])*)?$",
          "description": "Field pointer announced by overflow or entries[].deferred.path; empty string selects the root. Keep the same path while following nextOffset."
        },
        "offset": {
          "default": 0,
          "description": "Start at zero; on later calls set this to the previous page.nextOffset until it is null. Text offsets count Unicode code points.",
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "revision": {
          "description": "Use page.revision only when continuing the same path. Omit on the first call to any deferred child path; restart without it after stale_page_revision.",
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        }
      },
      "required": [
        "path",
        "offset"
      ],
      "additionalProperties": false
    },
    "id": {
      "type": "string",
      "pattern": "^[A-Za-z][A-Za-z0-9_]*-\\S(.*\\S)?$",
      "description": "One exact, complete OSV advisory ID from any OSV source database, matched case-sensitively. Prefixes include \"GHSA-\" (GitHub), \"PYSEC-\" (PyPI), \"RUSTSEC-\" (Rust), \"GO-\" (Go), \"DSA-\"/\"DLA-\" (Debian), \"USN-\" (Ubuntu), \"RHSA-\" (Red Hat), and \"CVE-\". No wildcards or partial IDs — take IDs from osv_query_package or osv_query_batch results. Example: \"GHSA-29mw-wpgm-hmr9\"."
    }
  },
  "required": [
    "id"
  ],
  "additionalProperties": false
}
view source ↗

osv_query_batch

Query vulnerabilities for multiple packages in one call — the primary tool for dependency audits, SBOM scanning, and lockfile triage. Pass up to 1000 mixed {name, ecosystem, version} tuples and {purl, version?} identifiers, with exactly one embedded or separate version per PURL. Each entry in the response corresponds positionally to the input. Each finding includes CVE aliases for chaining to nist-nvd-mcp-server for CVSS scoring. Large replies retain the complete summary. For overflow, repeat the original packages array with page: overflow.page. Continue the same path with offset: page.nextOffset and revision: page.revision until nextOffset is null. Retrieve each entries[].deferred.path separately at offset zero without a revision. Do not pass the output page object as input. /results/17 selects original input row 17, even when earlier rows failed. Pages are fresh lookups and do not recompute the initial summary; restart a changed node without a revision. Transmission overflow and upstream truncated are separate; neither confirms clean.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "osv_query_batch",
    "arguments": {
      "packages": "<packages>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "page": {
      "description": "Repeat the original packages array with page: overflow.page first. Continue using path, offset: page.nextOffset and revision: page.revision. /results/17/... keeps original row index 17; start deferred children without a revision.",
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "maxLength": 1024,
          "pattern": "^(?:\\/(?:[^~]|~[01])*)?$",
          "description": "Field pointer announced by overflow or entries[].deferred.path; empty string selects the root. Keep the same path while following nextOffset."
        },
        "offset": {
          "default": 0,
          "description": "Start at zero; on later calls set this to the previous page.nextOffset until it is null. Text offsets count Unicode code points.",
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "revision": {
          "description": "Use page.revision only when continuing the same path. Omit on the first call to any deferred child path; restart without it after stale_page_revision.",
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        }
      },
      "required": [
        "path",
        "offset"
      ],
      "additionalProperties": false
    },
    "packages": {
      "minItems": 1,
      "maxItems": 1000,
      "type": "array",
      "items": {
        "anyOf": [
          {
            "type": "object",
            "properties": {
              "name": {
                "type": "string",
                "pattern": "\\S",
                "description": "Exact package name in its ecosystem."
              },
              "ecosystem": {
                "type": "string",
                "pattern": "\\S",
                "description": "Case-sensitive ecosystem identifier from osv_list_ecosystems."
              },
              "version": {
                "type": "string",
                "pattern": "\\S",
                "description": "Exact package version, never a range."
              },
              "purl": {
                "description": "Use purl instead of the tuple, never together with name or ecosystem.",
                "type": "string"
              }
            },
            "required": [
              "name",
              "ecosystem",
              "version"
            ],
            "additionalProperties": false,
            "description": "Exact package tuple."
          },
          {
            "type": "object",
            "properties": {
              "purl": {
                "type": "string",
                "description": "Complete Package URL, such as pkg:pypi/[email protected]. Supply its version either here or separately, exactly once."
              },
              "version": {
                "description": "Exact version only when the PURL does not embed one.",
                "type": "string",
                "pattern": "\\S"
              }
            },
            "required": [
              "purl"
            ],
            "additionalProperties": false,
            "description": "PURL alternative with exactly one version source."
          }
        ],
        "description": "One package to audit."
      },
      "description": "Packages to audit. One entry per dependency. Positional: result[i] corresponds to packages[i]."
    }
  },
  "required": [
    "packages"
  ],
  "additionalProperties": false
}
view source ↗

osv_query_commit

Query known vulnerabilities for one full Git commit hash (40 hexadecimal SHA-1 or 64 hexadecimal SHA-256 characters, case-insensitive). Abbreviated hashes are rejected. Returns advisory summaries, record-wide severity and GIT ranges with repositories and ordered fix events; use osv_get_vulnerability for full records. No package-specific fixedVersions are inferred. For overflow, repeat the original input with page: overflow.page. Continue the same path with offset: page.nextOffset and revision: page.revision until nextOffset is null. Retrieve entries[].deferred.path separately at offset zero without a revision. Do not pass the output page object as input. Pages are fresh lookups; restart a changed node without a revision. Transmission overflow and upstream truncated are separate; neither confirms clean.

read
invocation
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "osv_query_commit",
    "arguments": {
      "commit": "<commit>"
    }
  }
}
schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "commit": {
      "type": "string",
      "pattern": "^(?:[a-fA-F0-9]{40}|[a-fA-F0-9]{64})$",
      "description": "Full Git commit hash: 40 SHA-1 or 64 SHA-256 hex characters, case-insensitive."
    },
    "page": {
      "description": "Repeat the original commit with page: overflow.page first, then select path, offset: page.nextOffset and revision: page.revision.",
      "type": "object",
      "properties": {
        "path": {
          "type": "string",
          "maxLength": 1024,
          "pattern": "^(?:\\/(?:[^~]|~[01])*)?$",
          "description": "Field pointer announced by overflow or entries[].deferred.path; empty string selects the root. Keep the same path while following nextOffset."
        },
        "offset": {
          "default": 0,
          "description": "Start at zero; on later calls set this to the previous page.nextOffset until it is null. Text offsets count Unicode code points.",
          "type": "integer",
          "minimum": 0,
          "maximum": 9007199254740991
        },
        "revision": {
          "description": "Use page.revision only when continuing the same path. Omit on the first call to any deferred child path; restart without it after stale_page_revision.",
          "type": "string",
          "pattern": "^[a-f0-9]{64}$"
        }
      },
      "required": [
        "path",
        "offset"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "commit"
  ],
  "additionalProperties": false
}
view source ↗