Skip to main content
Glama

Package & Dependency Intelligence API (x402)

A pay-per-call API selling npm, PyPI and crates.io (Rust) package health, dependency-graph, and vulnerability data to AI coding agents over the x402 payment protocol — plus an MCP server so agents in Claude Desktop/Cursor can call it and pay automatically.

Defaults to Base Sepolia testnet via the free public facilitator. Going to mainnet is an explicit config change (see Going to mainnet).

Endpoints

Raw passthrough of the upstream sources is free: npm, PyPI, crates.io, OSV and deps.dev are themselves free and unauthenticated, so charging for a relay of them prices against zero. What gets charged for is the consolidation — the score.

Endpoint

Method

Price

Returns

/v1/package/:ecosystem/:name

GET

free

Consolidated snapshot

/v1/vulns/:ecosystem/:name

GET

free

Known vulnerabilities (OSV.dev)

/v1/deps/:ecosystem/:name

GET

free

Dependency graph (deps.dev)

/v1/downloads/:ecosystem/:name

GET

free

Download counts

/v1/health/:ecosystem/:name

GET

$0.01

Health/risk score 0-100

/v1/batch

POST

$0.02

Batched health scores (≤50 packages)

:ecosystem is npm, pypi or crates. Also unpaid: /healthz, /v1/sample (canned example response), /.well-known/x402 (discovery manifest).

Free routes are rate limited to 60/min and 2000/day per caller — a runaway agent loop is how we would get our egress IP blocked by npm or OSV. Paid routes are exempt; their price is the limiter. Exceeding a limit returns 429 with Retry-After.

Tier, price, description, and discovery metadata all come from src/catalog.ts — edit there and the payment middleware, rate limiter, manifest, and Bazaar declarations stay in sync. tier is a required discriminant, so a new endpoint cannot default into being free.

Trusting the caller's address

The rate limiter counts per client IP, but the service sits behind a Worker proxy and a tunnel, so every request arrives from the same address. The proxy forwards the real one as x-stable-ip signed with PROXY_SECRET, and the origin honours it only when the secret matches. Anything else — wrong secret, no secret, or a request straight to the tunnel hostname — shares a single bucket. Without that signature a caller could forge a fresh address per request, or skip the proxy, and get unmetered upstream fan-out.

Set the same value in both places:

# .env for the origin, plus:
npx wrangler secret put PROXY_SECRET

The server warns at startup if it is missing on mainnet.

Related MCP server: versionator-mcp

Local setup (testnet)

npm install
npm run gen-wallet

gen-wallet prints two testnet-only keypairs — never fund these with real assets:

  • Seller — put its address in .env as PAY_TO (where payments land).

  • Buyer — put its private key in .env as BUYER_PRIVATE_KEY (used by the test script to simulate a paying agent).

Copy .env.example to .env and fill those in. Then fund the buyer with Base Sepolia USDC at faucet.circle.com (select Base Sepolia; no account needed). No testnet ETH is required — x402's exact scheme uses EIP-3009, so the buyer only signs off-chain and the facilitator pays gas.

npm run dev

Verify: curl http://localhost:4021/healthz → 200, and curl -i http://localhost:4021/v1/health/npm/express → 402 with payment instructions.

Test the payment flow

npm run test-buyer                              # GET /v1/health/npm/express (default)
npm run test-buyer -- /v1/deps/npm/express
npm run test-buyer -- /v1/batch

On Git Bash/Windows, prefix with MSYS_NO_PATHCONV=1 so the leading / isn't rewritten into a Windows path.

A request for a nonexistent package returns 404 without charging — the x402 middleware skips settlement entirely on any 4xx/5xx response, so failures are free.

MCP server (how agents consume this)

mcp-client/ is a standalone npm package (package-intel-mcp) — a stdio MCP server that runs on the buyer's machine. It is published separately from this server so an install does not drag in Hono and the x402 server stack; it imports nothing from src/.

It runs with no configuration at all. With no wallet it registers the four free tools (package_snapshot, package_vulns, package_deps, package_downloads). Requiring a funded hot wallet before the tool did anything was the single biggest adoption blocker, so that is now the default path, not an error.

claude mcp add package-intel -- npx -y package-intel-mcp

Setting X402_PRIVATE_KEY additionally registers package_health and package_batch_health, which call the paid endpoints and, on a 402, sign a USDC payment from that wallet and retry — the agent just sees data. A malformed key is a hard error rather than a silent drop back to free mode, since that would look like the paid tools vanishing for no reason.

{
  "mcpServers": {
    "package-intel": {
      "command": "npx",
      "args": ["-y", "package-intel-mcp"],
      "env": { "X402_PRIVATE_KEY": "0x..." }
    }
  }
}

X402_PRIVATE_KEY is the agent operator's wallet, funded with USDC on NETWORK. Use a dedicated low-balance wallet — it is a hot key that spends automatically.

To run it from source against a local server: npm run mcp.

Getting an agent to actually call it

Installing a tool does not make an agent reach for it. A line in the consuming repo's AGENTS.md / CLAUDE.md / .cursor/rules does, on every relevant task — that is the mechanism that produces recurring invocation, not registry listings. mcp-client/README.md ships a copy-paste block for this.

GitHub Action

action.yml publishes this repository as a dependency-review action. On a pull request that touches package.json, requirements*.txt or Cargo.toml, it looks up every newly added dependency and comments with advisories, deprecation, staleness and missing licences.

name: Dependency review
on:
  pull_request:
    paths: ["**/package.json", "**/requirements*.txt", "**/Cargo.toml"]

permissions:
  contents: read
  pull-requests: write

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0        # needed: the action diffs base against head
      - uses: adam121393/package-intel@v1
        with:
          fail-on: critical     # none | low | moderate | high | critical

Uses the free endpoints only — no wallet, no API key, no signup. Zero runtime dependencies, so adding it to a pipeline is not a supply-chain ask.

Input

Default

Purpose

fail-on

none

Fail the check at this severity or above

comment

true

Post and update a PR comment

github-token

${{ github.token }}

Needs pull-requests: write

api-url

hosted service

Override to run against your own instance

Two behaviours worth knowing. Only added dependencies are reviewed, not version bumps of existing ones, so the comment does not become noise people learn to scroll past. And advisories are scoped to a version: an exact pin is checked as written, while a range is checked against the package's current release. That distinction matters — querying without a version returns every advisory ever filed, which reports a fully patched lodash as critical.

A dependency that cannot be looked up is never a failure. An upstream outage must not block an unrelated pull request.

Coinbase CDP setup

Two different CDP credentials, easy to conflate:

Credential

Needed for

CDP_API_KEY_ID + CDP_API_KEY_SECRET

The facilitator — verifying and settling payments

CDP_WALLET_SECRET

The wallet SDK — creating/controlling CDP-managed accounts

Receiving payments needs only a public address. The server never holds key material to get paid — CDP_WALLET_SECRET is only for npm run cdp-wallet.

# 1. Add CDP_API_KEY_ID + CDP_API_KEY_SECRET to .env, then:
npm run cdp-check          # verifies keys, prints which networks CDP actually serves

# 2. Add CDP_WALLET_SECRET, then create a TEE-backed receiving account:
npm run cdp-wallet                  # prints an address to use as PAY_TO
npm run cdp-wallet -- --faucet      # also request Base Sepolia test funds

cdp-check exists because CDP's docs list supported networks as "Base, Polygon, Arbitrum, World, Solana" without saying whether Base Sepolia is included, and /supported requires auth. It answers that empirically and tells you whether the testnet rehearsal below is possible.

Rehearsing the CDP path on testnet

If cdp-check reports Base Sepolia is supported, set USE_CDP_FACILITATOR=true while leaving NETWORK=eip155:84532. You then exercise the real CDP credentials and settlement path against test funds. If it isn't supported, leave the flag unset — the CDP path will first run on mainnet, so make that first payment a small one.

Going to mainnet

  1. Receiving wallet — use a dedicated address (ideally from npm run cdp-wallet), never a personal wallet. Only the public address goes in PAY_TO.

  2. Set NETWORK=eip155:8453. The server switches to the CDP facilitator automatically and refuses to boot without CDP keys, rather than silently using a testnet facilitator.

  3. Set PUBLIC_URL to the real origin so the manifest advertises reachable URLs.

  4. Deploy (below), then make 2–3 real settled payments — the CDP Bazaar only catalogs a service after its first successful settlement.

Start small and confirm settlement on BaseScan against your PAY_TO address before promoting the endpoint anywhere.

Deploy (Railway)

railway.json is included (Nixpacks, npm run start:api, /healthz health check). Push the repo, create a Railway project from it, and set the environment variables from .env.example in Railway's variables UI — not in a committed file. Point uptime monitoring at /healthz.

Getting listed

  • CDP Bazaar — automatic once on mainnet via the CDP facilitator, after the first settled payment. Each route already declares discovery metadata with a valid sample input (npm/express); this matters because the Bazaar probes with that input and only indexes endpoints that answer 402 — a placeholder ecosystem would 400 and never list.

  • /.well-known/x402 — already served, for agentic.market / x402scan / x402-list.

  • MCP registries — publish to the official MCP Registry, then Glama, Smithery, PulseMCP.

Notes

  • Caching: in-process LRU with TTLs from 1h (vulns) to 24h (downloads/deps). On upstream failure a stale value is served with stale: true rather than erroring.

  • Validation before payment: unsupported ecosystems 400 in middleware before the payment check, so they're never charged.

  • Version-scoped vulnerabilities: health scores query OSV for the resolved current version. Querying without a version returns every advisory in the package's history, which badly misrepresents maintained packages.

  • pypistats rate limits aggressively (429 after a couple of rapid calls). Download counts are best-effort: a failure omits that field rather than failing the request. Warm the cache for popular packages if this matters.

  • The health score in src/domain/health.ts is a documented v1 heuristic — tune the weights as real usage data arrives.

Available Tools

4 tools
package_depsA
Read-only

Get the dependency graph for an npm, PyPI or crates.io (Rust) package: direct and transitive dependencies with versions and counts, with deprecated direct dependencies flagged. Free, no payment required.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPackage name, e.g. 'express', 'requests', or 'serde'
versionNoOptional exact version; defaults to latest
ecosystemYesPackage ecosystem: 'npm', 'pypi', or 'crates' (crates.io / Cargo, for Rust)

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already cover read-only and open-world hints. The description adds meaningful context: it specifies the output includes direct/transitive dependencies with versions, counts, and deprecated flags, and also notes the service is free. This goes beyond the schema and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence that immediately states the tool's purpose. It includes only essential information, with the 'Free' note being compact and useful. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description adequately explains the return information: direct and transitive dependencies, versions, counts, and deprecated flags. It covers supported ecosystems and the optional version parameter. Minor gaps like error behavior or depth limits are not addressed, but the core is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (ecosystem, name, version) already documented including enums and examples. The description adds no additional parameter-level details beyond repeating the ecosystem types, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the verb 'Get' and resource 'dependency graph' for npm, PyPI, or crates.io packages. It differentiates from siblings by focusing on dependency analysis rather than snapshots, vulnerabilities, or download statistics.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool (when you need dependency graphs for supported ecosystems), but it does not explicitly name alternatives or state when not to use it. Sibling tools are not referenced, though their purposes are distinct.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

package_downloadsA
Read-only

Get download counts for an npm, PyPI or crates.io (Rust) package over a time range. Free, no payment required.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPackage name, e.g. 'express', 'requests', or 'serde'
rangeNonpm only; PyPI returns last-week, crates.io returns a 90-day total
ecosystemYesPackage ecosystem: 'npm', 'pypi', or 'crates' (crates.io / Cargo, for Rust)

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint:true and openWorldHint:true, so the safety profile is known. The description adds 'Free, no payment required,' which is a helpful behavioral trait beyond annotations. However, it does not disclose the ecosystem-specific behavior of the 'range' parameter (e.g., PyPI returns only last-week, crates.io returns a 90-day total), leaving that to the schema. This is not a contradiction but a moderate gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two short sentences, front-loaded with the core action, and contains no unnecessary filler. Every word adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with no output schema and full parameter schema coverage, the description is adequate. It clearly states the core purpose, and the schema fills in the ecosystem-specific range behavior. It does not mention return format or limitations beyond what's in the schema, but neither is required for such a straightforward use case.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with detailed descriptions for all three parameters, including the important caveats about 'range'. The description itself adds no parameter-specific meaning beyond what the schema provides, so the baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') and resource ('download counts for an npm, PyPI or crates.io package'), making the tool's functionality immediately clear. It also distinguishes itself from sibling tools like package_snapshot, package_vulns, and package_deps, which address different concerns.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states what the tool does but offers no explicit guidance on when to use it over alternatives or when not to. The sibling names (snapshot, vulns, deps) make the comparison obvious, but the usage context is implied rather than directly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

package_snapshotA
Read-only

Get a consolidated snapshot of an npm, PyPI or crates.io (Rust) package: latest version, license, description, repository, weekly downloads, maintainers, last publish date, and deprecation status. Free, no payment required.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPackage name, e.g. 'express', 'requests', or 'serde'
ecosystemYesPackage ecosystem: 'npm', 'pypi', or 'crates' (crates.io / Cargo, for Rust)

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations provide readOnlyHint and openWorldHint, so the read-only nature is already disclosed. The description adds value by stating 'Free, no payment required,' which is a meaningful operational detail, and by listing the exact data points returned. It does not mention potential rate limits or registry availability, but given the annotation coverage, this is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences long, front-loads the primary purpose, and each sentence adds distinct value: the first clarifies the tool's output, the second addresses a potential user concern (cost). No unnecessary words or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description explicitly enumerates the return fields (version, license, description, repository, downloads, maintainers, publish date, deprecation status). Combined with the annotations (read-only, open-world) and a clear ecosystem enum in the schema, the description provides a complete and actionable picture of the tool's behavior and results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides full descriptions for both parameters (name and ecosystem) with 100% coverage. The tool description mentions the ecosystems and examples like 'express' in the schema, but adds no additional parameter meaning beyond what the schema provides. Thus the baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Get') and clearly identifies the resource ('a consolidated snapshot of an npm, PyPI or crates.io package') and the scope (a list of eight specific data points). It distinguishes itself from sibling tools like package_vulns and package_downloads by offering a general overview rather than a focused sub-topic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for obtaining a general package overview, but it does not explicitly mention when to use this tool over alternatives like package_vulns, package_deps, or package_downloads. There is no 'when to use' or 'instead of' guidance, so guidance is reasonable but not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

package_vulnsA
Read-only

List known vulnerabilities (OSV.dev) for an npm, PyPI or crates.io (Rust) package. Pass a version to scope results to that version; omit it to see every advisory ever filed against the package. Free, no payment required.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesPackage name, e.g. 'express', 'requests', or 'serde'
versionNoOptional exact version, e.g. '5.2.1'
ecosystemYesPackage ecosystem: 'npm', 'pypi', or 'crates' (crates.io / Cargo, for Rust)

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint. The description adds valuable context beyond this: the data source (OSV.dev), version scoping behavior, and the note that it is free (no payment required). It does not contradict any annotations and covers the key behavioral aspects for a read-only enumeration tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences, front-loaded with the primary purpose, then clarifies the key behavioral nuance (version scoping), and ends with a useful cost-related note. Every sentence earns its place; no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool, the description covers the essential aspects: purpose, source, version behavior, and cost. It doesn't describe the return format, but with no output schema and a clear 'list' verb, this is a minor gap. The description is complete enough for an agent to select and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already describes all three parameters. The description adds meaningful semantics for the version parameter by explaining the difference between passing a version (scope to that version) and omitting it (see all advisories). This goes beyond the schema's minimal description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') with a clear resource ('known vulnerabilities') and explicitly specifies supported ecosystems (npm, PyPI, crates.io). It distinguishes itself from sibling tools like package_snapshot, package_deps, and package_downloads by focusing on vulnerabilities.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context: use this tool to check security vulnerabilities for a package. It explains the optional version parameter and the behavior when omitted, providing practical usage guidance. It doesn't explicitly mention alternatives or exclusions, but the purpose is so distinct that the usage context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 4 tool updates
    • First observedpackage_deps
    • First observedpackage_downloads
    • First observedpackage_snapshot
    • First observedpackage_vulns

TDQS

A4.3/5.0
Disambiguation5/5

Each tool targets a distinct aspect of package intelligence: snapshot (overview), vulns (security), deps (dependencies), and downloads (popularity). No two tools overlap in purpose.

Naming Consistency5/5

All tools follow a consistent package_<topic> pattern with lowercase snake_case. The naming is predictable and uniform across the set.

Tool Count5/5

Four tools is well-scoped for a package intelligence server, covering the core facets without unnecessary bloat. Each tool earns its place.

Completeness5/5

The four tools provide comprehensive read-only coverage of package metadata, vulnerabilities, dependencies, and downloads, leaving no obvious gaps for the stated purpose.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    An MCP server for searching, inspecting, and evaluating NPM packages through health scoring and license risk assessments. It provides comprehensive package analysis including maintenance status, popularity trends, and security vulnerability reports to help users make informed dependency decisions.
    3
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    An MCP server that queries 19 package registries (npm, PyPI, crates.io, etc.) to retrieve the latest version of packages and their metadata.
    21
    1
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP server for comprehensive PyPI package intelligence, providing tools for dependency analysis, security scanning, health scoring, license compliance, and trend tracking.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server that checks npm and PyPI package health, providing maintenance signals, version info, CVE counts, and alternative suggestions.
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/adam121393/package-intel'

If you have feedback or need assistance with the MCP directory API, please join our Discord server