REST API
Package intelligence API
MCP for agents, GET /api/npm/{package} for scripts. Same JSON: safe version picks (stable-preferred, prerelease when needed), policy, OSV, publisher, optional release notes.
Overview
Agents: add the MCP server + Cursor rule (below). The tool npm_package_suggest returns the same JSON as GET /api/npm/{package}: safe version picks with channel (stable or prerelease), publisher, policy, OSV batch metadata, warnings. Install the exact semver from the response. Never @latest before SafeVersion.
Getting started is copy-paste. Full HTTP reference and playground: Endpoint.
Getting started
Three things: MCP config → rule file → (optional) AGENTS.md. Restart Cursor after MCP changes.
1. MCP
Save as .cursor/mcp.json at the repo root (or merge safeversion into existing mcpServers).
Remove the whole headers object if you don’t use API keys. You can use Authorization: Bearer … instead of X-API-Key, same as the REST API.
{
"mcpServers": {
"safeversion": {
"type": "streamableHttp",
"url": "https://safeversion.com/api/mcp",
"headers": {
"X-API-Key": "YOUR_API_KEY"
}
}
}
}UI alternative: Settings → Tools & MCP → type streamableHttp → URL https://safeversion.com/api/mcp → same headers if needed.
Tool surface: npm_package_suggest with package, optional current, releaseNotes (matches REST query params).
2. Cursor rule
Download safeversion-dependencies.mdc → save as .cursor/rules/safeversion-dependencies.mdc. Keep alwaysApply: true in the frontmatter.
Or copy the same content from the block below.
---
description: MCP-first. Call SafeVersion before dependency adds/upgrades; no @latest
alwaysApply: true
---
# SafeVersion before dependency changes
## Workflow
1. **Call SafeVersion.** Use the MCP tool **`npm_package_suggest`** with the package name. For upgrades, pass **`current`** as the **exact** installed semver.
2. **Read the response.** Check **`warnings`** and **`security`** (`dataStatus` reflects OSV batch success, not a global "all clear") before editing `package.json` or running installs.
3. **Install the exact version.** Use the **exact** version the tool indicates (e.g. **`latestSafe`** for new deps; **`smallestSafeUpgrade`** or **`latestSafe`** when upgrading. Compare both when `current` is set). Prefer pinned versions over floating ranges when acting autonomously.
4. **No safe recommendation.** Stop and explain; do not invent a version.
## Do not
Do **not** run `npm install <pkg>@latest`, `pnpm add <pkg>@latest`, `yarn add <pkg>@latest`, `bun add <pkg>@latest`, or equivalent **before** calling SafeVersion.
If SafeVersion (MCP or API) errors or is unreachable, **do not** fall back to arbitrary installs.
## Without MCP
Use **`GET https://safeversion.com/api/npm/{package}`** with `Accept: application/json`. Encode scoped names (`encodeURIComponent`). Add **`?current=`** (exact semver) for upgrades. Fields match the MCP tool output.
**Scope:** Adding, removing, or bumping npm dependencies in `package.json` and lockfiles.
3. AGENTS.md (optional)
Repo root AGENTS.md; merge if you already have one.
# Dependencies (SafeVersion) Before adding or upgrading npm packages, call the SafeVersion MCP tool **npm_package_suggest** (pass **current** with the exact installed semver when upgrading). Read **warnings** and **security** (field **dataStatus** is OSV batch health, not a global all-clear). Do not run npm install <pkg>@latest, pnpm add <pkg>@latest, or equivalent before SafeVersion. Install the **exact** version from the response. If there is no safe recommendation, stop and explain why. Setup: https://safeversion.com/docs#getting-started
Endpoint
Path
GET /api/npm/{package}
{package} is a single URL segment. Use percent-encoding for scoped names, e.g. @types/node → %40types%2Fnode. The playground builds this for you.
Alternate name query
You may pass ?name= to override the path segment (decoded the same way). If both are empty after trim, the API returns 400.
Query parameters
| Name | Type | Required | Description |
|---|---|---|---|
| name | string | No | Optional override for the package name (instead of the path segment only). |
| current | string | No | Installed version as exact semver. When valid, the response includes smallestSafeUpgrade: the lowest safe version strictly greater than current. Invalid semver → 400. |
| releaseNotes | flag | No | When 1, true, or yes (case-insensitive), the response may include a releaseNotes object with summaries fetched from GitHub for tags matching latestSafe and smallestSafeUpgrade. Expect slower responses; entries may be missing if the repo has no matching release. |
Response body
On success you get a JSON object with the fields below. Omitted keys mean “not applicable” (for example smallestSafeUpgrade appears only when you passed current).
| Field | Meaning |
|---|---|
| package | Display name from the packument (fallback: requested name). |
| requestedCurrent | Echo of normalized current when supplied. |
| latestSafe | Newest safe version, preferring stable over prerelease. Each version object includes channel ("stable" or "prerelease"),satisfies (policy checks passed), and publisher when known. null if no safe version exists. |
| smallestSafeUpgrade | With current: lowest safe version > current, or null if none. Omitted entirely without current. |
| policy | minAgeDays tells you how many days after publish a version must be before it can qualify as “safe” for this API. |
| security | provider: "osv", assessedAt ISO timestamp, dataStatus available when the OSV batch succeeded or unavailable if it failed. This describes data availability only. Use warnings and each version's satisfies for actionable context. |
| links | npm URL, optional repository, and when GitHub is known + current is set: compareToLatestSafe / compareToSmallestSafeUpgrade compare URLs. |
| identity | Canonical package name and packument-level author when present. Per-version publisher data lives on each latestSafe / smallestSafeUpgrade object directly. |
| releaseNotes | Present when requested: optional entries for latestSafe and smallestSafeUpgrade with tag, summary, and URL. |
| warnings | Human-readable issues: empty age window, OSV failure, no clean versions, etc. |
Each safe version includes version, publishedAt (ISO), channel ("stable" or "prerelease"), satisfies (e.g. ["ageWindow", "osvClean"]), and publisher when known.
Errors
| Status | Body | When |
|---|---|---|
| 400 | { "error": "Missing package name" } | No usable name from path or query. |
| 400 | { "error": "Invalid semver for query parameter current" } | Malformed current. |
| 404 | { "error": "Package not found" } | Registry returned 404. |
| 502 | { "error": "Could not read package metadata" } | Oversized or invalid packument JSON. |
| 502 | { "error": "Registry request failed" } | Non-OK response from npm registry. |
| 504 | { "error": "Upstream request timed out" } | The request did not finish in time (upstream work exceeded the timeout). |
| 500 | { "error": "Internal server error" } | Unexpected failure. |
Interactive examples
Each playground runs a real fetch to the same host you opened the docs on. Use the sidebar under Interactive examples to jump between recipes.
Baseline: latest safe
When to use: You only need the newest “safe” version and general policy / security context. Omit current so smallestSafeUpgrade is not computed.
Must be a valid semver string when set.
→ /api/npm/react
With current version
When to use: You know what is installed and want the next safe bump (e.g. for PR bots or dashboards). Pass a valid semver as current to populate smallestSafeUpgrade and compare links when a GitHub repo exists on the packument.
Must be a valid semver string when set.
→ /api/npm/react?current=18.0.0
Scoped package
When to use: Scoped packages must occupy a single path segment; the playground encodes @scope/name automatically for the request URL.
Must be a valid semver string when set.
→ /api/npm/%40types%2Fnode?current=20.0.0
Release notes
When to use:You want human-readable release text alongside version picks. Responses are slower and release bodies may be absent depending on the package's GitHub tags and rate limits.
Must be a valid semver string when set.
→ /api/npm/semver?current=7.5.0&releaseNotes=1
Beta-only package fallback
When to use: Packages that only publish prereleases. The API prefers stable but when none exist, latestSafe will have channel: "prerelease".
Must be a valid semver string when set.
→ /api/npm/workflow