cd /news/ai-agents/show-hn-an-mcp-server-for-manpages · home › topics › ai-agents › article
[ARTICLE · art-163431] src=chainguard.dev ↗ pub= topic=ai-agents verified=true sentiment=↑ positive

Show HN: An MCP Server for Manpages

Chainguard SVP of Engineering Dustin Kirkland launched man.cgr.dev, a site publishing every manual page in Chainguard OS — 59,419 documents from 1,286 packages across three package repositories, rebuilt nightly from signed apks — along with an MCP server exposing five tools (search_docs, get_man_page, resolve_xref, list_package_docs, get_package_info) so AI agents can query documentation directly. Each page is available as HTML, Markdown (append .md), original roff (append .raw), and a JSON manifest (append .json), with version-pinned permanent URLs and cross-references resolved against the corpus, of which 91% land on a real page. Kirkland, who built the Ubuntu Manpage Repository at Canonical in 2008, framed the shift as documentation now being read by agents in editors and terminals rather than humans typing into a search box.

read7 min views2 publishedNov 3, 2026
Show HN: An MCP Server for Manpages
Image: source

Dustin Kirkland SVP, Engineering

20 years of manual pages on the web #

In 2008, I was a brand-new engineer on the Ubuntu Server Team at Canonical, and my starter project was the Ubuntu Manpage Repository: a website that rendered every manual page in all of Ubuntu as static, searchable HTML. It is still live today, at manpages.ubuntu.com.

That site was built for the era of search engine optimization. The reader we had in mind was a developer typing a question into a search box, and the goal was for the answer to be an Ubuntu manual page. It worked. It had a large, measurable effect on how accessible, usable, and developer-friendly Ubuntu felt — because the documentation for whatever you were running was one search away, instead of buried in a package you hadn’t installed.

So, I have been thinking about manual pages on the web for almost 20 years. And the reader has changed. Today, a human with a search box is the least likely thing to be looking for an answer in documentation. Rather, it’s an agent, in your editor or your terminal, working on your behalf, and it needs what that site gave people, in a form a machine can use.

James Brown told us it’s a man’s, man’s, man’s world. Twenty years on, it still is. Only now, the readers are agents.

That’s why we built man.cgr.dev. It has every manual page in Chainguard OS rendered as HTML, as you’d expect. It also has the original roff source and a Markdown version of every page. More importantly, it has an MCP server, so the same documentation is machine-readable and searchable from within your own AI development environment and by your agents.

Every manual page in Chainguard OS #

man.cgr.dev publishes every manual page in Chainguard OS — 59,419 documents from 1,286 packages across all three of our package repositories (and counting), rebuilt every night from the signed apks that actually make up the distribution.

The short form, man.cgr.dev/man/bash.1, takes you to the current page. Every page also has a permanent address, and from there you can access it in four ways:

| HTML | man.cgr.dev/os/bash/5.3-r14/man1/bash.1 | | Markdown | Append .md | | Original roff | Append .raw | | JSON manifest — package, version, content digests | Append .json |

Put latest in place of the version to follow the current release, or leave the version pinned and get the same answer next year.

Cross-references work. git-commit(1) mentions git-add(1), and that mention is a link you can click. Links are resolved against the corpus itself rather than guessed when the page is built, and 91% of references land on a real page. A manual page that cites 12 others and links to none of them is a dead end, and the web solved that problem in 1993.

Manual pages, built for agents #

Here’s what makes this different from manpages.ubuntu.com, and from Debian’s excellent equivalent: it is built for agents first.

There is an MCP server at with five tools:

search_docs find pages across the corpus
get_man_page fetch one, at an exact version
resolve_xref resolve a cross-reference the way a human would
list_package_docs everything a given package documents
get_package_info which versions of a package have docs

Point Claude, or anything else that speaks MCP, at it, and the model stops guessing about flags. Ask any assistant: “What does --exclude do for this tool?”, and you get an answer drawn from training data that may be two years stale, for a version you are not running, with no signal about which. Worse, assistants increasingly operate inside minimal container images. Those are exactly the environments where the documentation has been deliberately left out, because manual pages live in -doc subpackages that nobody installs into production.

So the agent is working precisely where the manual isn’t. man.cgr.dev puts the accurate answer, for the exact version the image ships, one query away.

Version-exactness is the whole point #

Most documentation on the internet describes a version of the software. Ours describes the version, because every document is extracted from a specific signed apk, and the package and version are recorded on every page and in every JSON manifest.

Documents enter the corpus one way only: as an apk, checked against a signed APKINDEX before anything parses it. There is no upload API, no scraper, no hand-curated content. If a page is on the site, it came out of a package we built and signed.

Exactness has to hold in both directions. Adding a page when a package gains one is easy. The harder case is when a package stops shipping a page. A build with no manual page has nothing to ingest, so a naive pipeline never notices and keeps serving the old page as current. Ours notices. When a build drops a page, latest stops serving it, and the older version stays readable at its pinned address — because some of you are still running it.

Complete, and only what we may publish #

“Every manual page” is a promise about packaging as much as about a website. Manual pages belong in a -doc subpackage. When a package ships them somewhere else, they are either missing from the site or duplicated across it. So we went through the distribution and fixed the packaging: more than 150 recipes now split their documentation properly. That includes clang(1) for every LLVM stream from 14 through 23, and the Rust toolchain. We also removed copies of man pages that had been vendored into unrelated packages.

Then we made sure it stays fixed. A lint now runs on every change to the package definitions, so a package that has been split correctly cannot quietly regress. We also fixed the man-page detection in melange, our package build tool, so the build itself can flag misplaced pages.

Publishing everything also means knowing what we are allowed to publish. Every document records its license, and we read all of them. There is no GFDL anywhere in the corpus — the classic manual-page redistribution trap. The handful of pages under proprietary or source-available licenses (BUSL, SSPL, Elastic, and vendors’ proprietary terms) are withheld, and that rule matches by license, not by package. A rule written by package class would have hidden roughly 450 openly licensed Azul Zulu OpenJDK pages to protect two proprietary ones.

We are letting the crawlers in. On purpose. #

robots.txt, sitemaps, llms.txt, canonical URLs, JSON-LD: all present, all deliberately permissive to AI crawlers.

That is roughly the opposite of where the rest of the web is heading, and it is a considered position, not an oversight. What is public, well-structured, and widely linked today is what models are trained on tomorrow. If we want assistants to give good answers about Chainguard OS in two years, now is the time to publish authoritative, machine-readable documentation.

We also made every page public and unauthenticated, including the manual pages for our enterprise packages. You do not need a Chainguard account to read how our software works. That was a deliberate call, and an easy one. Documentation you have to log in to read is documentation no model will ever learn from, and no engineer will ever find at 2 a.m.

How it is built, briefly #

renders the HTML. The Markdown is derived from that HTML rather than generated separately, so the two cannot drift apart. The orchestration is written in Go. manpages.debian.org has used this same architecture since 2017, for the same reasons. We evaluated the cost of writing our own roff renderer and rejected it, mostly because 42.7% of the corpus defines its own macros, so a fixed macro table would not be enough. You need a roff interpreter, and a good one already exists.

The whole corpus renders in about 20 seconds on one core. The slow part is down packages, not parsing them. On the serving side, a cold instance answers its first request in about 0.2 seconds, because the nightly crawl ships a prebuilt snapshot of the catalog rather than making the first visitor wait while it is built.

Try it #

Trying out our agent-ready manual pages is easy:

  • Humans: Visitman.cgr.dev.
  • Agents: Point your MCP client athttps://man.cgr.dev/mcp
  • Every page is also .md ,.raw , and.json

Share this article

── more in #ai-agents 4 stories · sorted by recency
── more on @chainguard 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/show-hn-an-mcp-serve…] indexed:0 read:7min 2026-11-03 · —