From 2ad80684adfb86913c92dc041fac1f4786910403 Mon Sep 17 00:00:00 2001 From: Ajay Krishnan Date: Fri, 26 Jun 2026 23:58:08 -0700 Subject: [PATCH] Fix local docs source refresh --- docker/docs/entrypoint.sh | 26 ++++++++++++++++++++++---- scripts/release-check | 17 ++++++++++++++++- scripts/smoke-docs.mjs | 11 +++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/docker/docs/entrypoint.sh b/docker/docs/entrypoint.sh index 97534b0..a36526a 100644 --- a/docker/docs/entrypoint.sh +++ b/docker/docs/entrypoint.sh @@ -46,10 +46,28 @@ for source_url in $sources; do done if [ -d "$local_sources_dir" ]; then - python -m http.server "$local_sources_port" \ - --bind 127.0.0.1 \ - --directory "$local_sources_dir" \ - >/tmp/context-kit-local-sources.log 2>&1 & + python - "$local_sources_port" "$local_sources_dir" >/tmp/context-kit-local-sources.log 2>&1 <<'PY' & +import functools +import http.server +import sys + + +class LocalSourceHandler(http.server.SimpleHTTPRequestHandler): + def send_head(self): + # llms-txt-mcp 0.2.0 treats 304 responses from local sources as fetch + # failures, so serve machine-local docs as plain 200 responses. + for header in ("If-Modified-Since", "If-None-Match"): + if header in self.headers: + del self.headers[header] + return super().send_head() + + +port = int(sys.argv[1]) +directory = sys.argv[2] +handler = functools.partial(LocalSourceHandler, directory=directory) +with http.server.ThreadingHTTPServer(("127.0.0.1", port), handler) as server: + server.serve_forever() +PY local_sources_pid="$!" if ! python - "$local_sources_port" <<'PY' import sys diff --git a/scripts/release-check b/scripts/release-check index 7ec46a3..2aaf9f1 100755 --- a/scripts/release-check +++ b/scripts/release-check @@ -21,11 +21,26 @@ export CONTEXT_KIT_DATA_DIR="${tmp_dir}/data" export CONTEXT_KIT_PROJECT_DIR="${ROOT}" export CONTEXT_KIT_SEARXNG_PORT="$(pick_port)" export CONTEXT_KIT_DOCS_PORT="$(pick_port)" -export CONTEXT_KIT_DOCS_SOURCES="config/sources.default.txt" export CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR="${tmp_dir}/local-sources" +export CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT="8769" +local_sources_profile="${tmp_dir}/sources.local.txt" +export CONTEXT_KIT_DOCS_SOURCES="config/sources.default.txt ${local_sources_profile}" +export CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL="http://127.0.0.1:${CONTEXT_KIT_DOCS_LOCAL_SOURCES_PORT}/release-fixture/llms.txt" export CONTEXT_KIT_WEB_SEARCH_IMAGE="context-kit/web-search-mcp:${release_id}" export CONTEXT_KIT_DOCS_IMAGE="context-kit/docs-mcp:${release_id}" +mkdir -p "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture" +printf '%s\n' \ + '# Release Check Local Source' \ + '' \ + '> Exercises machine-local llms.txt serving and refresh behavior.' \ + '' \ + '## MCP' \ + '' \ + '- [Model Context Protocol](https://modelcontextprotocol.io/)' \ + > "${CONTEXT_KIT_DOCS_LOCAL_SOURCES_DIR}/release-fixture/llms.txt" +printf '%s\n' "${CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL}" > "${local_sources_profile}" + cleanup() { docker compose -p "${CONTEXT_KIT_COMPOSE_PROJECT}" -f compose.yml down -v --remove-orphans >/dev/null 2>&1 || true docker image rm "${CONTEXT_KIT_WEB_SEARCH_IMAGE}" "${CONTEXT_KIT_DOCS_IMAGE}" >/dev/null 2>&1 || true diff --git a/scripts/smoke-docs.mjs b/scripts/smoke-docs.mjs index 5453da3..75d59cb 100644 --- a/scripts/smoke-docs.mjs +++ b/scripts/smoke-docs.mjs @@ -1,6 +1,7 @@ import { requireToolSuccess, runSmoke } from "./mcp-smoke-client.mjs"; const live = process.env.CONTEXT_KIT_LIVE_CHECKS === "1"; +const localSourceSmokeUrl = process.env.CONTEXT_KIT_LOCAL_SOURCE_SMOKE_URL; runSmoke({ usage: "usage: node scripts/smoke-docs.mjs [args...]", @@ -21,6 +22,16 @@ runSmoke({ docs_sources: "pass" }; + if (localSourceSmokeUrl) { + requireToolSuccess("docs_refresh/local_source_first", await client.callTool("docs_refresh", { + source: localSourceSmokeUrl + })); + requireToolSuccess("docs_refresh/local_source_second", await client.callTool("docs_refresh", { + source: localSourceSmokeUrl + })); + result.local_source_refresh = "pass"; + } + if (live) { const query = requireToolSuccess("docs_query", await client.callTool("docs_query", { query: "Model Context Protocol documentation",