pkg-oracle
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@pkg-oracleVerify the npm package 'express' before I install it."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
pkg-oracle — Dependency Trust Oracle
A pay-per-call MCP (Model Context Protocol) server that verifies an npm or PyPI package before an AI coding agent writes it into a manifest. Monetized per call with the real x402 protocol (signed EIP-3009 authorizations, settled through Coinbase's hosted facilitator) in USDC on Base — no API keys, no signup, no dashboard. An agent calls the tool, pays a fraction of a cent, gets a verdict.
Why this exists
AI coding agents hallucinate package names and skip the verification a human developer would normally do — they check one thing ("does this name resolve?") and if it resolves, they install it. That gap is now an active attack surface known as slopsquatting: attackers register the package names LLMs are statistically likely to hallucinate, then wait.
verify_package closes that gap with a single tool call that:
Confirms the package actually exists on its registry (npm or PyPI).
Cross-references OSV.dev for known CVEs affecting the resolved version.
Pulls the package's OpenSSF Scorecard via deps.dev (branch protection, code review practices, maintenance signal, ...).
Runs a Levenshtein-distance typosquat check against a curated list of high-value popular package names, combined with the package's publish age — a near-miss spelling that's also brand new is the exact shape of a typosquat/slopsquat attack.
It returns one synthetic verdict an agent can act on without reasoning about four different data sources itself: ALLOW, WARN, or BLOCK.
Related MCP server: MCP Package Hero
Architecture
Agent (Claude, Cursor, custom SDK / x402-aware MCP client)
│ MCP tools/call verify_package (_meta["x402/payment"] once paid)
▼
StreamableHTTPServerTransport (fresh per request, stateless mode)
│
▼
McpServer → verify_package
│
├─ under free tier? ──▶ raw handler (no charge)
│
└─ else ──▶ x402 payment wrapper (@x402/mcp)
│
├──▶ CDP facilitator: verify signed payment, settle on-chain
└──▶ raw handler
│
├──▶ registry.ts (registry.npmjs.org | pypi.org)
├──▶ osv.ts (api.osv.dev)
├──▶ depsdev.ts (api.deps.dev — OpenSSF Scorecard)
└──▶ typosquat.ts (fast-levenshtein vs. curated popular list)
│
▼
oracle.ts aggregates → { verdict, findings[] }Payment gating happens per MCP tool, not per HTTP route — initialize
and tools/list are never charged, only an actual verify_package call
past the free tier is.
Quickstart
npm install
cp .env.example .env # RECIPIENT_WALLET + CDP_API_KEY_ID/SECRET are required, even in dev
npm run build
npm startOr for local iteration with hot reload:
npm run devUnlike most values in .env.example, RECIPIENT_WALLET and the two CDP
credentials have no safe placeholder — the resource server authenticates
against CDP's real hosted facilitator at boot, regardless of environment.
There's no way to run this server against fake/mock payment infrastructure.
The server listens on PORT (default 3000) and exposes:
Endpoint | Method | Purpose |
|
| MCP tool calls — |
|
| Streamable HTTP protocol completeness (no-ops) |
|
| Liveness check, always free |
Environment variables
See .env.example for the full list with defaults.
Variable | Default | Meaning |
| (dev-only burn address) | Base L2 wallet that receives USDC payments — required |
| (none — required) | Coinbase Developer Platform API key ID |
| (none — required) | Coinbase Developer Platform API key secret |
|
| Price per call once the free tier is spent |
|
| Free calls per wallet/IP before payment is required |
|
| Timeout for registry/OSV/deps.dev calls |
|
| Age under which a package is "new" |
|
| Max Levenshtein distance still flagged |
The verify_package tool
Input schema:
{
"ecosystem": "npm | pypi",
"name": "string (required)",
"version": "string (optional — exact version to check)"
}Example call and response:
// request
{ "ecosystem": "npm", "name": "expres" }
// response (verdict text + machine-readable JSON in content[])
{
"verdict": "WARN",
"findings": [
{
"code": "TYPOSQUAT_NAME_SIMILARITY",
"message": "\"expres\" is close (distance 1) to the popular package \"express\". ..."
}
],
"registry": { "exists": true, "ageDays": 4800, "...": "..." },
"osv": { "vulnerabilities": [], "highestSeverity": "UNKNOWN" },
"scorecard": { "overallScore": 1.5, "sourceRepo": "github.com/..." },
"typosquat": { "suspected": true, "distance": 1, "redFlag": false }
}When no version is given, the oracle resolves the registry's latest
published version internally before querying OSV/deps.dev — querying OSV
with no version at all returns every vulnerability ever disclosed for the
package, patched or not, which would make a long-lived, well-maintained
package like lodash permanently read as BLOCK. A CHECKED_LATEST_VERSION
finding tells you which version was actually evaluated.
Verdict logic (first match wins)
BLOCK — the name doesn't exist on the registry at all (the strongest possible hallucination/slopsquat signal).
BLOCK — a pinned version was requested but doesn't exist.
BLOCK — near-miss of a popular package name and published within
NEW_PACKAGE_THRESHOLD_DAYS.BLOCK — a known CRITICAL or HIGH severity vulnerability applies.
WARN — a MODERATE/LOW/UNKNOWN vulnerability, a new package without a typosquat match, an older near-miss name, or a low OpenSSF Scorecard.
ALLOW — nothing above fired.
Monetization: x402 on Base, via the CDP facilitator
verify_package is wrapped with @x402/mcp's createPaymentWrapper in
src/mcpServer.ts — the real x402 "exact" scheme, not
a homegrown variant:
The caller is identified by
Authorization: Bearer <wallet>(or anX-Wallet-Addressheader), falling back to the client IP Fly's edge proxy reports if neither is present. This identity is self-declared, not verified — nothing stops a client from rotating the header to claim a fresh free allowance.FREE_TIER_LIMITdefaults to5specifically because of this: the free tier is a landing ramp, not an authenticated quota, sized to keep casual abuse cheap to give away rather than to be unbeatable.The first
FREE_TIER_LIMITcalls per identity run the raw handler directly, no payment involved — a tool that requires payment on the very first call never gets tried by an agent, and never gets adopted.Past the free tier, a call without a payment payload gets a payment error carrying a standard x402
PaymentRequireddescriptor (scheme: "exact",network: "eip155:8453",payTo: RECIPIENT_WALLET,amount: "3000"). Any x402-aware MCP client —x402MCPClientfrom@x402/mcp, or an agent SDK with built-in x402 support — signs an EIP-3009transferWithAuthorization(no gas, no waiting for confirmation) and retries with the payload in_meta["x402/payment"]. The server verifies the signature and settles the on-chain transfer through CDP's facilitator, then runs the tool.
Funds are never custodied by Coinbase. The facilitator only verifies
the client's signature and submits the resulting transfer on-chain
(payTo is RECIPIENT_WALLET, resolved at server startup from your own
env var) — CDP never holds the money mid-flight.
Settling through CDP's hosted facilitator (as opposed to a generic one)
is also what makes verify_package auto-discoverable in the
x402 Bazaar: the
bazaarResourceServerExtension registered on the resource server plus the
declareDiscoveryExtension({ toolName: "verify_package", ... }) call in
mcpServer.ts get indexed automatically the first time a real payment
settles — there's no separate registration step.
Client configuration
pkg-oracle speaks MCP over Streamable HTTP, so any MCP-compatible client
pointed at http://<host>:<port>/mcp works for the free tier. Paying past
the free tier requires an x402-aware MCP client. Below are the common
integrations.
Claude Desktop / Cursor (free tier only)
{
"mcpServers": {
"pkg-oracle": {
"type": "http",
"url": "http://localhost:3000/mcp",
"headers": {
"Authorization": "Bearer 0xYourAgentWalletAddress"
}
}
}
}Neither ships a built-in x402 signer today, so once the free tier is spent these clients will surface the payment-required error as a tool failure rather than paying automatically.
Custom agent with x402 support
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
import { wrapMCPClientWithPaymentFromConfig } from "@x402/mcp";
import { ExactEvmScheme } from "@x402/evm/exact/client";
const mcpClient = new Client({ name: "my-agent", version: "1.0.0" });
await mcpClient.connect(
new StreamableHTTPClientTransport(new URL("http://localhost:3000/mcp")),
);
// account: any viem-compatible signer holding USDC on Base
const x402Client = wrapMCPClientWithPaymentFromConfig(mcpClient, {
schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(account) }],
});
const result = await x402Client.callTool("verify_package", {
ecosystem: "npm",
name: "expres",
});
if (result.paymentMade) {
console.log("Paid:", result.paymentResponse?.transaction);
}autoPayment: true (the default) signs and retries automatically once a
payment-required error is received — no manual 402 handling needed.
Docker
docker build -t pkg-oracle .
docker run -p 3000:3000 \
-e RECIPIENT_WALLET=0xYourWalletAddress \
-e CDP_API_KEY_ID=your-cdp-key-id \
-e CDP_API_KEY_SECRET=your-cdp-key-secret \
-e FREE_TIER_LIMIT=5 \
pkg-oracleThe image is a multistage, non-root, production-only build (dev dependencies and TypeScript source are stripped from the final layer).
Despliegue en producción (Fly.io)
fly.toml ya está configurado para desplegar directamente desde el
Dockerfile — HTTPS automático, health check contra /health. Pasos:
# 1. Instala flyctl y autentícate (una sola vez)
curl -L https://fly.io/install.sh | sh
fly auth login
# 2. Desde la raíz del proyecto: crea la app (usa el fly.toml existente)
fly launch --no-deploy # detecta fly.toml, no lo sobreescribas si pregunta
# 3. Configura los secretos (nunca los pongas en fly.toml ni los commitees)
fly secrets set RECIPIENT_WALLET=0xTuWalletReal
fly secrets set CDP_API_KEY_ID=tu-cdp-key-id
fly secrets set CDP_API_KEY_SECRET=tu-cdp-key-secret
# 4. Despliega
fly deploy
# 5. Verifica
curl https://tu-app.fly.dev/healthTu servidor queda con TLS ya resuelto en el dominio *.fly.dev que Fly
asigne (o el dominio custom que configures con fly certs add) — sin eso,
x402 no tiene sentido: el resource del reto de pago necesita ser una URL
real y segura para que un cliente x402 confíe en ella.
Antes de escalar a más de una máquina: el contador freemium vive en
memoria (LRU) por proceso. Con min_machines_running = 1 (el valor por
defecto en fly.toml) esto no es un problema. Si escalas horizontalmente,
un mismo wallet obtendría FREE_TIER_LIMIT llamadas gratis por
instancia en vez de en total — en ese punto, mueve el contador a Redis
(Fly ofrece Upstash Redis como addon) antes de subir min_machines_running.
Known limitations / honest scope notes
Popular-package list is curated, not a live top-1000 feed. It's a hand-picked shortlist of the highest-value typosquat targets in each ecosystem (
src/services/popularPackages.ts), not a synced download-rank API. Good enough to catchexpres→express; won't catch a typo of a mid-tier package outside the list. Syncing against npm's/PyPI's real download-rank data on a cron is the natural next step.The free-tier counter is in-memory (LRU), not persisted — it resets on restart and doesn't share state across multiple server instances. Fine at
min_machines_running: 1(the default); back it with Redis before scaling horizontally (see Despliegue en producción above).Payment replay protection is delegated to the protocol itself — the EIP-3009
noncein each signed authorization is enforced on-chain by USDC's contract, and CDP's facilitator rejects already-settled or expired authorizations. Nothing custom to maintain here.Claude Desktop and Cursor have no built-in x402 signer — they work fine for the free tier, but a payment-required response surfaces as a tool failure rather than being paid automatically. Use an x402-aware MCP client (see Client configuration) to actually pay past the free tier.
CVSS-vector severity estimation is a conservative heuristic, used only when OSV doesn't supply an explicit
database_specific.severitystring (see the doc comment insrc/services/osv.ts).
This server cannot be installed
Maintenance
Related MCP Servers
- Alicense-qualityCmaintenanceAn 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.Last updated3MIT
- AlicenseAqualityDmaintenanceA comprehensive MCP server for checking package versions and rating package quality across Python (PyPI), JavaScript/TypeScript (npm), Dart (pub.dev), and Rust (crates.io) ecosystems.Last updated5MIT
- AlicenseAqualityCmaintenanceAn MCP server that queries 19 package registries (npm, PyPI, crates.io, etc.) to retrieve the latest version of packages and their metadata.Last updated211MIT
- Alicense-qualityCmaintenanceMCP server for checking packages against an AI-aware vulnerability database, including CVEs, slopsquatting, CISA KEV, and MCP-server trust profiles.Last updatedElastic 2.0
Related MCP Connectors
Scans MCP servers for tool poisoning, prompt injection and supply chain risks.
Security scanner for MCP servers. Detect vulnerabilities, prompt injection, and tool poisoning.
Supply chain risk scoring for npm, PyPI, Cargo, and Go. 9 tools. Behavioral signals.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/julian-martin89/pkg-oracle'
If you have feedback or need assistance with the MCP directory API, please join our Discord server