Fetch llms.txt and AGENTS.md weekly, and put their changes in changelogs - #76
Merged
Merged
Conversation
GitHub webhooks need admin rights or an installed App, which this registry has for almost no repository, and websites serving llms.txt have no webhooks at all. So each document is polled weekly with conditional requests: an unchanged file costs a 304 and no body. - llms.txt from the listing's website, else its verified namespace domain - AGENTS.md from the root of a GitHub repository - Keyed by URL: a document many listings share is fetched once, recorded once, and shown on every listing that points at it website_url is the publisher's say-so, so fetching it is guarded: https only, every redirect hop must resolve to a public address, bodies stream with a 256 KB cap, and an HTML page at /llms.txt counts as absent. First fetch is a baseline. An outage records nothing and keeps what was known; a file that appears or disappears is recorded as such. Closes #75 --- Pages affected: - [MCP server changelog](https://ai.mcpharbor.dev/changelog) -- now includes llms.txt and AGENTS.md changes. - [MCP Harbor](https://ai.mcpharbor.dev/) -- registry home and search. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
Closes #75. Follows #74.
Polling, not webhooks
A GitHub webhook requires admin rights on the repository, or a GitHub App its owner installs. This registry has neither for almost any of its tens of thousands of repositories, and llms.txt is served by websites that have no webhooks at all. So each document is checked weekly with conditional requests (
If-None-Match,If-Modified-Since) — an unchanged file answers304with no body. Verified against raw.githubusercontent.com before building on it.What's fetched
com.cloudflare→cloudflare.com).io.github.*names an account, not a site, so it gets none.raw.githubusercontent.com/<owner>/<repo>/HEAD/AGENTS.mdDocuments are keyed by URL, not listing: many listings share one llms.txt, and it is fetched once, recorded once, and shown on every listing that points at it. A
server_documentslink table, rebuilt daily, says which listing points where, so a listing's changelog, its kind counts and the sitemap all pick document changes up in SQL.Fetching URLs publishers choose
website_urlis whatever a publisher typed, so every fetch is treated as hostile until checked:169.254.169.254would have this server read cloud metadata for it. Redirects are followed by hand so every hop gets the same check, not only the first. Covers RFC 1918, loopback, link-local, CGNAT, benchmarking, multicast, IPv6 ULA/link-local, and IPv4-mapped IPv6.200What's recorded
First fetch: baseline, nothing recorded. A changed body: lines added and removed (
List.myers_difference, blank lines dropped, capped at 200 lines). A file appearing where one was confirmed absent, or vanishing where one was present: recorded as such. An outage — timeout, 5xx, a bot filter's 403 — records nothing and keeps what was known. An outage is not a removal.On the page, document changes render as a diff block with the file's URL rather than as chips, since they're lines of prose.
Running it
Documents.Scheduler: a batch of 100 every five minutes at concurrency 4, rediscovery daily. On in production unlessDOCUMENTS_ENABLED=false; never under test.Tests: 226 passing on three seeds, including a private resolver, a redirect into a private range, plain http, the size cap, the SPA fallback and an outage.
Pages affected:
🤖 Generated with Claude Code