From e7c6f128b32abfa2bfcf7a18579af3ebcaa2e61e Mon Sep 17 00:00:00 2001 From: Logan Besecker Date: Thu, 1 Oct 2026 09:45:48 -0700 Subject: [PATCH] Treat a JSON page at /llms.txt as absent Of 1,988 llms.txt files fetched in production, 1,962 open with a Markdown heading as the format specifies. Four are JSON: API hosts answering every path with a status document, served as text/plain. The HTML check caught single-page-app fallbacks but not these. Neither llms.txt nor AGENTS.md is JSON, and a status page carrying a timestamp would record a fake change on every weekly check. - A JSON content type, or a body that parses as JSON, counts as absent - Test reproduces the production case Closes #81 --- Pages affected: - [MCP server changelog](https://ai.mcpharbor.dev/changelog) -- kept free of fake llms.txt changes. Co-Authored-By: Claude Opus 5.5 --- lib/mcp_registry/documents.ex | 12 +++++++++++- test/mcp_registry/documents_test.exs | 7 +++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/mcp_registry/documents.ex b/lib/mcp_registry/documents.ex index c15c22f..b825805 100644 --- a/lib/mcp_registry/documents.ex +++ b/lib/mcp_registry/documents.ex @@ -414,7 +414,17 @@ defmodule McpRegistry.Documents do |> String.downcase() String.valid?(body) and not String.contains?(type, "html") and - not String.starts_with?(head, [" ["absent", "published"]}}] = changes() end + test "a JSON status page served at /llms.txt is not an llms.txt" do + # Seen in production: an API host answering every path with its health + # document, as text/plain. + serve(&text(&1, 200, ~s({"status":"ok","server":"mock-mcp-server"}))) + assert Documents.check(doc()) == :missing + end + test "an outage is not a removal" do d = doc() serve(&text(&1, 200, "# Acme\n"))