Repository navigation
Add find_image_equivalent to the AI Docs MCP server - #4101
Merged
matthewhelmke merged 1 commit intoSep 30, 2026
Conversation
A headless Claude Code test found that search usually surfaces dfc's image mappings but hands them off unreliably: the matching line can fall outside the returned snippet, and in one run the model misread a correct snippet and invented details. A lookup returns one labeled answer instead. find_image_equivalent follows dfc's own matching order (pkg/dfc/dfc.go): the reference with and without its tag, the last path segment, the name with any Docker Hub host and library/ removed, then prefix patterns such as nodejs*. It returns the Chainguard image name and a pull reference of the form cgr.dev/<your-organization>/<image>, and never presents the public cgr.dev/chainguard namespace as the place to pull it. generate_package_catalog.py now writes dfc's image mappings to package-mappings.json under image_mappings, a new key, so it cannot be mistaken for the image list the old catalog carried under images. Tests take their ground truth from data/package-mappings.yaml, parsed separately, and cover every exact mapping plus tags, digests, Docker Hub hosts, prefix patterns, pinned tags, and registry ports. The prefix, Docker Hub, and digest tests each fail with their rule removed. The unit-test job now installs PyYAML for them. Refs DOCS-138 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
This was referenced Sep 30, 2026
matthewhelmke
merged commit Sep 30, 2026
0137e7d
into
matthewhelmke/docs-138-remove-image-tools
8 checks passed
matthewhelmke
deleted the
matthewhelmke/docs-138-find-image-equivalent
branch
September 30, 2026 14:13
Collaborator
Author
|
This change moved into #4099, so this PR shows as merged into #4099's branch rather than into Why: this PR was stacked on #4099. On its own, #4099's search-only instructions still led some AI tools to guess image names, and |
matthewhelmke
added a commit
that referenced
this pull request
Sep 30, 2026
…ngs (#4099) The AI Docs MCP server's image tools served year-old data. ServiceNow's AI tool got back image references that don't exist, such as `cgr.dev/chainguard/victoriametrics` (ZD 11898), and that still reproduced on the live server today. This PR removes those tools and tells connecting clients to use `cg-oci` instead, which reads the registry live and was documented in #4053. It also adds `find_image_equivalent`, which answers "what Chainguard image replaces X?" from the Dockerfile Converter mappings with a reference the reader can actually pull. In a test with a real AI tool, correct answers went from 19 of 24 to 24 of 24. Unpullable `cgr.dev/chainguard/...` references went from 20 of 24 answers to none. ## Changes **Remove the image tools and frozen sources** (DOCS-138, DOCS-139, DOCS-140) - Removes `get_image_docs`, `list_images`, and `check_image_freshness`, along with the registry client and image parsing behind them. All three depended on an `images-private` README snapshot that was uploaded by hand on 2025-08-12. The automated export never succeeded. - Adds MCP `instructions`, sent at `initialize`, that point clients to `cg-oci`, `cg-apk`, and `cg-versions`. - Stops compiling image READMEs and courses into the bundle. Courses already contributed no content, because the 2025-08-12 tarball didn't match the compiler's expected layout. - Drops the workflow's GCS download step. The only other thing it downloaded, the edu export, was extracted and never read. GCP auth stays for Artifact Registry, Cloud Run, and the bundle upload. - Renames `generate_image_catalog.py` to `generate_package_catalog.py` and ships its output as `package-mappings.json`. The build still ships `image-catalog.json` with the same content, so existing `CATALOG_PATH` settings keep working. - The bundle drops from about 14.9 MB to 4.5 MB. **Compile the dfc mappings into the bundle again** (fixes DOCS-174) - The compiler reads the committed `data/package-mappings.yaml`, which the nightly `autodocs-platform` job copies from dfc. The unmaintained GCS dfc object is no longer used. - The section uses the compiler's page signature, so search results link to the Package and image name mappings page. A missing file now prints a warning instead of passing silently. **Search: match "image" in queries to "Container" in titles** - With the image READMEs gone, "python image" stopped finding "Getting started with the Python Chainguard Container." A title-only synonym brings it back. - Known limit: a page whose body contains the literal phrase, such as "nginx image," still collects the existing exact-phrase bonus and can outrank the matching guide. **Add `find_image_equivalent`, and point clients at the pullable reference form** This came out of review testing and was folded in from #4101. I ran headless Claude Code against a local server, with only the AI Docs tools available, on 24 upstream images whose Chainguard name differs from the upstream one: | | Search only | With `find_image_equivalent` | | --- | --- | --- | | Correct image | 19 / 24 | **24 / 24** | | Tool calls per question | 1 to 4 | 1 | | Answers giving `cgr.dev/chainguard/<image>` | 20 | **0** | | Answers giving `cgr.dev/<your-organization>/<image>` | 0 | **24** | Each of the five search misses was a confident wrong answer: - In two runs, the model skipped the server because the first instructions said it had "no container image data." - In two runs, the matching line fell outside the returned snippet. - In one run, the model misread a correct snippet and invented details. All 21 `cgr.dev/chainguard/<target>` references the model printed are refused to anonymous callers at the token endpoint. - **`find_image_equivalent(image)`** follows dfc's own matching order, from `pkg/dfc/dfc.go`: 1. The reference with and without its tag. 2. The last path segment alone. 3. The name with any Docker Hub host removed, with and without `library/`. 4. Prefix patterns such as `nodejs*`. It returns the image name, a `cgr.dev/<your-organization>/...` reference with any tag the mapping pins, the matched key, and a pointer to `cg-oci` for checking entitlement. - **`generate_package_catalog.py`** writes dfc's 397 image mappings under a new `image_mappings` key, so they can't be confused with the old catalog's image list. - **The server instructions and the bundle's DFC section** say the mappings are available, name the tool, and give the reference form `cgr.dev/<your-organization>/<image>`. - **The `unit-test` job** installs PyYAML, because the new tests read their ground truth from the YAML file. **Also** - `compile_docs.py` gets a formatting-only `black` commit first; its AST is unchanged. Without it, the pre-commit hook would reformat the whole file inside the real change. - `quick-start-guide.md` gets its existing lint errors fixed. It now passes through the same cleaning step as every page, so its markdownlint directive stays out of the bundle. - Fixes the image reference in `extract.sh`'s usage line (`cgr.dev/chainguard/ai-docs` doesn't exist). The docs pages follow in #4100, merged right after this one. ## Testing - `pytest scripts/test_mcp_server.py scripts/test_mcp_transport.py scripts/test_compile_docs.py`: 45 passed. - The new tests check the exact tool set, the instructions, the DFC section against the committed YAML, the synonym, and `find_image_equivalent`. - The image lookup tests take ground truth from `data/package-mappings.yaml`, parsed separately. They cover all 394 exact mappings, plus tags, digests, Docker Hub hosts, prefix patterns, pinned tags, and registry ports. - The synonym, DFC, prefix, Docker Hub, and digest tests each fail when their change is reverted. - Compiled a real bundle and catalog locally: 4.47 MB, 626 pages, no image markers, 683 package mappings, and both catalog filenames byte-identical. - Ran the server over HTTP against those files: - `tools/list` returns the documentation tools, and `initialize` carries the instructions. This run predates the `find_image_equivalent` commit, which the 24-run test and CI's `smoke-test` and `unit-test` jobs cover. - `find_package_equivalent("build-essential")` returns `build-base`. - A dfc search returns the new section and its page URL. - Calling `list_images` returns `Unknown tool`. - Built the container with the real artifacts. `smoke-test-mcp.sh` passes, `verify` passes, and `extract` writes both catalog files with valid checksums. ## After merge The `scripts/**` push trigger redeploys the hosted server. The served download at `/downloads/chainguard-complete-docs.md` shrinks at the next nightly publish. Until then, the real-bundle tests run against the old committed bundle, which still passes. Refs DOCS-138, DOCS-139, DOCS-140 Fixes DOCS-174 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Created in collaboration with Claude Code running Opus 5.5 on 2026-09-30. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
matthewhelmke
added a commit
that referenced
this pull request
Sep 30, 2026
…e-tool replacements (#4100) The AI Docs page now documents the four tools the server keeps. It also includes a table that sends anyone who relied on the removed image tools to the live replacements from #4053. Developer Resources, which covered the same product and had drifted, is merged in. **Merge after #4099.** This page describes the server as #4099 leaves it, including the `find_image_equivalent` tool, which was folded into #4099 from #4101. ## Changes **`/platform/mcp-servers/ai-docs/`**, retitled "AI Docs: Chainguard documentation for AI tools" - Documents five tools, including `find_image_equivalent`. - A new "Image references" section explains that most Chainguard images are pulled from `cgr.dev/<your-organization>/<image>`, and that the public `cgr.dev/chainguard` namespace serves only a free subset. - A new "Container image data" section has a table mapping each task to its former AI Docs tool and its replacement: - `get_image_docs`: the Chainguard Containers Directory, or `get_config` and `get_apko_config` on `cg-oci` - `list_images`: `list_repos` on `cg-oci` - `check_image_freshness`: `list_tags` and `get_manifest` on `cg-oci`, or `registry_tags_list` on `cg-api` - `find_package_equivalent`: unchanged, with `cg-apk` for package versions - A dated note records the removal. We can delete the note and the "Former AI Docs tool" column once migrators have moved on. - "Image catalog" becomes "Package catalog" and covers `package-mappings.json` and its earlier name, `image-catalog.json`. The standalone and Claude Desktop examples use the new name. - The `check_image_freshness` example becomes a dfc image-mapping example. - A new "Use the documentation without a server" section holds the offline content from Developer Resources: a direct link to the download, which that page never had, plus container `verify` and `extract`, `cosign verify`, and how to load the bundle into an AI tool. It notes that the bundle is larger than most tools can hold in one conversation. - Adds a troubleshooting entry for an AI tool that can't find image details. **`/developer-resources/`** - Deleted and turned into an alias of the AI Docs page. The page repeated the AI Docs tool list and Claude Desktop configuration, and its copies had drifted: it still claimed Alpine support. - Its roughly 50 example prompts are dropped. The per-tool prompts and the bundle's own usage guide cover the same ground. - The sidebar's **AI Docs Bundle** link now points to `#use-the-documentation-without-a-server`. **Other pages** - **MCP servers overview:** no longer says AI Docs searches image READMEs, and points to `cg-oci` for image data. - **AI documentation security:** lists the two remaining sources (edu pages and the dfc mappings), drops the provisional dfc note, and says a clone is all the compiler needs. - **Directory name:** the AI Docs page now uses "Chainguard Containers Directory" instead of "Images Directory." ## Testing - `hugo --gc --minify` builds clean. `/developer-resources/` redirects to `/platform/mcp-servers/ai-docs/`. - Every link and fragment in the article body of the three changed pages resolves against the build, including the sidebar link. - The migration table and note render correctly; there's no literal shortcode text. - `check-related-pages` found no page that needs this change. The Kiro and Cursor pages still say "Chainguard Images directory." That belongs to a sitewide naming sweep, so this PR leaves them alone. Refs DOCS-138, DOCS-174 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- Created in collaboration with Claude Code running Opus 5.5 on 2026-09-30. --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
find_image_equivalent, which answers "what Chainguard image replaces X?" from the Dockerfile Converter's mappings, and returns a reference the reader can actually pull. We tested it against a real AI tool. Before the change, 5 of 24 answers named the wrong image and 20 of 24 gave acgr.dev/chainguard/...reference that anonymous pulls are refused. After it, 24 of 24 named the right image, and every answer gave acgr.dev/<your-organization>/...reference.Stacked on #4099. Merge order: #4099, then this PR, then #4100 (docs).
Why a tool, not search
I ran headless Claude Code against a local server, with only the AI Docs tools available, on 24 upstream images whose Chainguard name differs from the upstream one:
find_image_equivalentcgr.dev/chainguard/<image>cgr.dev/<your-organization>/<image>Each of the five search misses was a confident wrong answer:
Separately, I probed all 21
cgr.dev/chainguard/<target>references the model printed, and the token endpoint refuses every one to anonymous callers.Changes
find_image_equivalent(image)follows dfc's own matching order, frompkg/dfc/dfc.go:library/.nodejs*.It returns the image name, a
cgr.dev/<your-organization>/...reference with any tag the mapping pins, the matched key, and a pointer tocg-ocifor checking entitlement. With no match, it says what dfc would do (keep the image's own name) and points to the Directory.generate_package_catalog.pywrites dfc's 397 image mappings under a newimage_mappingskey. Reusingimageswould confuse them with the old catalog's image list.The server instructions name the tool.
The
unit-testjob installs PyYAML, because the new tests read their ground truth from the YAML file.Testing
pytest: 45 passed.data/package-mappings.yaml, parsed separately from the code under test.Refs DOCS-138
🤖 Generated with Claude Code
Created in collaboration with Claude Code running Opus 5.5 on 2026-09-30.