image-delta-mcp
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., "@image-delta-mcpcompare cgr.dev/chainguard/nginx to docker.io/library/nginx:latest"
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.
image-delta-mcp — UNOFFICIAL: built as interview prep, not affiliated with or endorsed by Chainguard.
An MCP server over Chainguard's public, free-tier image data that answers, inside Claude Code:
"What changed between these two versions of this image, and what CVEs did we shed?"
It shells out to three standard supply-chain tools — crane
(tags/digests/manifests), cosign (SPDX SBOM
attestations), and grype (registry-direct CVE
scanning) — wraps them in strict validation, rate limiting, and a digest-keyed
cache, and exposes four small tools to any MCP client.
Guardrails (why this exists and what it will not do)
Unofficial. Interview-prep project. Not affiliated with, endorsed by, or representing Chainguard in any way.
Free-tier public data only.
cgr.devfree-tier images, their public Sigstore attestations, and public upstream registries. No gated catalog access, no scraping.Polite to registries. Every registry-touching call goes through a token bucket (4 burst, 1/s refill) and a digest-keyed on-disk cache under
.cache/, so repeated queries do not hammer cgr.dev or Docker Hub.Honest about gaps. Missing SBOMs, unresolvable platforms, free-tier tag limitations, and scanner-database freshness are reported in
data_gapsfields — never papered over as empty-but-successful results.
Related MCP server: MCP Image Compare Server
The four tools
Tool | Question it answers |
| What tags exist, with digests and created dates — plus how many historical digests are publicly recoverable from signature tags. |
| Package-level delta (added / removed / version-changed) between two refs, from the SPDX SBOM attestations attached to each digest. |
| CVEs shed and introduced between two refs, from identical registry-direct grype scans. |
| The money tool: a Chainguard image vs. its upstream equivalent, CVE counts side by side. |
Refs are tags (latest) or digests (sha256:<64 hex>); platform defaults to
linux/amd64 (linux/arm64 supported).
Real demo results (run 2026-07-21, grype DB of 2026-07-21)
These are actual outputs from npm run smoke on this machine — no numbers
below are invented, and they will drift as images and the vulnerability
database update.
1. "What CVEs did we shed?" — cgr.dev/chainguard/node, an older digest vs latest
Older ref sha256:0029ab60fc5a… (created 2023-01-14) → latest
sha256:c002402b3552… (created 2026-07-17):
454 CVEs → 2 CVEs
447 CVE instances shed (16 Critical, 127 High, 100 Medium, 15 Low, 189 Unknown)
1 introduced (1 Medium), 1 retained
packages: 189 added, 2 removed, 17 version-changedThe older digest was recovered from public signature tags (sha256-*.sig) —
the free tier exposes only rolling tags, but 7,697 historical index digests
of node are publicly enumerable and diffable this way.
2. Chainguard vs upstream — cgr.dev/chainguard/nginx vs docker.io/library/nginx:latest
cgr.dev/chainguard/nginx:latest 0 CVEs
docker.io/library/nginx:latest 340 CVEs (21 Critical, 58 High, 86 Medium, 7 Low, 103 Negligible, 65 Unknown)Same scanner, same database, same platform (linux/amd64), both
registry-direct — an apples-to-apples scanner comparison, not an official
vendor count.
The 3-minute demo script (inside Claude Code)
"What CVEs did we shed moving chainguard/node from
sha256:0029ab60fc5a…to latest?" → clean shed/introduced delta with the package changes behind it."Compare chainguard/nginx to docker.io/library/nginx." → the zero-CVE claim reproduced live from public data by a tool an agent can call.
Close: built in a day on hardened template conventions, 144 tests, externally reviewed — and an agent can call this before choosing a base image.
Architecture
Claude Code (stdio, primary) optional: Streamable HTTP (127.0.0.1, Bearer auth)
│ │
└────────────► McpServer (4 tools, zod-validated inputs)
│
validate.ts │ tight regexes for image/tag/digest/platform,
(before any │ checked BEFORE anything is spawned
spawn) ▼
exec.ts ── execFile ONLY, binary allowlist {crane, cosign, grype},
│ per-arg character checks, hard timeouts + SIGKILL,
│ bounded output buffers
▼
rate-limit.ts (token bucket) ──► crane / cosign / grype ──► registries
│
cache.ts — digest-keyed on-disk cache (.cache/):
immutable entries for digest-addressed content
(manifests, configs, SBOMs), TTL entries for tag
lists (30m), tag→digest (15m), grype scans (24h)Data flow for a diff: tag/digest → index digest (crane digest) → platform
image digest (crane manifest) → SBOM (cosign download attestation,
predicate https://spdx.dev/Document, with legacy .sbom-attachment
fallback) and CVEs (grype registry:image@digest -o json) → pure diff logic
(src/diff.ts).
Honest limitations
Free tier only sees rolling tags.
latest,latest-dev, etc. Versioned tags are a paid feature; "older refs" here are historical digests recovered from public signature tags, which are unordered and must be dated individually.CVE counts are scanner-relative. grype against its daily DB — not Chainguard's advisory feed, not an official count from either vendor. Numbers move as the DB updates; scans are cached up to 24h.
Upstream images have no SBOMs.
diff_packagesworks where SBOM attestations exist (Chainguard images); for most upstream images it reports a data gap instead.SBOM parity. Chainguard SBOMs are per-platform in-toto attestations; very old digests may predate them (legacy attachment fallback included, but some gaps remain and are reported as such).
Attestations are downloaded, not verified.
cosign download attestationfetches; it does not verify signatures against Fulcio/Rekor. A production version wouldcosign verify-attestationagainst Chainguard's identity.grype's own registry traffic is not rate-limited by this server's token bucket (it pulls layers internally). The bucket gates how often scans start; the 24h scan cache keeps repeats near zero.
Install & run
Prereqs: Node >= 20 and the three binaries:
brew install crane cosign grypeBuild and test:
npm install
npm test # 144 vitest tests — fully offline, binaries mocked
npm run build
npm run smoke # the real pipeline against public registries (network!)Claude Code (stdio — primary mode)
claude mcp add image-delta -- node /absolute/path/to/image-delta-mcp/dist/index.jsor in .mcp.json:
{
"mcpServers": {
"image-delta": {
"command": "node",
"args": ["/absolute/path/to/image-delta-mcp/dist/index.js"]
}
}
}Optional HTTP mode (hardened, off by default)
IMAGE_DELTA_API_KEY="$(openssl rand -hex 24)" PORT=3900 node dist/index.js --http
# POST /mcp with Authorization: Bearer <key>; binds 127.0.0.1; /healthz unauthenticatedRefuses to start without a key (>= 16 chars). Timing-safe Bearer comparison, per-IP token bucket, 2 MB body cap, stateless transport.
Env: IMAGE_DELTA_CACHE_DIR overrides the cache location (default .cache/
in the package root).
Quality gate
144 vitest tests (validation, exec safety, rate limiting, cache, SBOM and grype parsing, diff logic, all four tools against a mocked registry, MCP end-to-end over an in-memory transport, HTTP auth/limits integration). Tests never touch the network.
Integration smoke script (
scripts/smoke.mjs) exercises the real pipeline; the demo numbers above are its output.Adversarial security self-review + external Codex review — findings and fixes recorded in SECURITY-REVIEW.md.
This server cannot be installed
Maintenance
Related MCP Servers
- FlicenseNot gradedqualityNot gradedmaintenanceEnables intelligent file and folder comparison with advanced text normalization, duplicate detection, and line-level diff analysis. Provides secure workspace-constrained file operations with CRC32-based exact matching and smart text comparison capabilities.
- AlicenseAqualityDmaintenanceEnables pixel-perfect image comparison and visual regression testing via tools to compare local images, screenshots, and URLs with detailed diff statistics.3423MIT
- AlicenseNot gradedqualityFmaintenanceTransforms code diffs into beautiful visual comparisons with support for GitHub Gist sharing and local file output (HTML/PNG).1812MIT
- AlicenseAqualityCmaintenanceEnables read-only binary diff and fingerprinting of files without writing to disk, providing structured diffs and per-section SHA-256 hashes.3MIT
Related MCP Connectors
Verify PyPI and npm packages, symbols, and version diffs against real artifacts. Free, no account.
Generate SBOMs, scan vulnerabilities, and analyze dependencies from local projects or Git repos.
Check exact npm/PyPI upgrades for evidence-backed breaking changes; query APIs and components.
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/joepangallo/image-delta-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server