Run docs-mcp as a long-lived shared HTTP service #1
Reference in New Issue
Block a user
Delete Branch "feat/docs-mcp-shared-http"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refactors context-docs from per-call stdio spawn to a long-lived Streamable HTTP MCP service so concurrent clients share one indexer / one Chroma writer.
What changes for users
bin/context-kit startonce;context-kit-docs-mcpstays up.type: remote, Claude Codetype: http) connect directly tohttp://127.0.0.1:8776/mcp— no per-call docker spawn.bin/context-kit docsstill works for stdio-only clients as a thinmcp-proxybridge.7dto24hnow that re-embedding is cheap (the model stays loaded across calls).CONTEXT_KIT_DOCS_PORT,CONTEXT_KIT_DOCS_HTTP_URL,CONTEXT_KIT_DOCS_PREINDEX.Why
The previous design spawned a fresh
docs-mcpcontainer per MCP call, paying full cold-start cost (embedding model load + Chroma open) and racing with concurrent clients for the same Chroma writer. The publish audit surfaced 50+ orphan containers as the visible symptom.How
docs-mcpleaves themcpprofile, getscontainer_name,restart: unless-stopped, healthcheck, and127.0.0.1:8776host port. Runs as host UID/GID so bind mounts stay user-owned.mcp-proxy==0.12.0and an entrypoint that frontsllms-txt-mcp's stdio as Streamable HTTP. Reads sources from a flat file. Disables eager preindex by default.startgenerates the sources file and waits for/status;docsbecomes anmcp-proxy --transport streamablehttpbridge;doctorandstatussurface the new endpoint.Verified
bash -n,sh -n,compose config -qall clean/statusreturns 200context-docs was previously spawned per call as a fresh stdio container, which meant every MCP request paid full cold-start cost (embedding model load + Chroma open) and concurrent clients raced for the same Chroma writer. The 50+ orphan container build-up I saw during the publish audit was the visible symptom. This refactor runs docs-mcp as one long-lived service: - compose: docs-mcp leaves the 'mcp' profile, gets container_name, restart: unless-stopped, healthcheck, and a host port (127.0.0.1:8776 by default). Runs as the host UID/GID so bind mounts don't end up root-owned. - docker image: adds mcp-proxy (0.12.0) and an entrypoint that fronts llms-txt-mcp's stdio as Streamable HTTP. Reads sources from a flat file mounted at /etc/context-kit/docs-sources.txt. Disables eager preindex by default; callers refresh on demand via the docs_refresh tool. Set CONTEXT_KIT_DOCS_PREINDEX=1 to restore eager behavior. - bin/context-kit: 'start' brings up the docs service alongside SearXNG, generates the sources file from CONTEXT_KIT_DOCS_SOURCES, and waits for the HTTP endpoint to become ready (up to 180s for first-run model download). 'docs' still works for stdio-only clients but is now a thin mcp-proxy bridge onto the shared HTTP service. 'doctor' and 'status' both surface the new endpoint. - install snippets: context-docs is now 'type: remote'/'type: http' pointing at ${CONTEXT_KIT_DOCS_HTTP_URL}. HTTP-capable MCP clients bypass the bridge entirely. snippets/*.json and the install command output stay byte-identical. - docs and .env.example updated for new vars (CONTEXT_KIT_DOCS_PORT, CONTEXT_KIT_DOCS_HTTP_URL, CONTEXT_KIT_DOCS_PREINDEX) and the new 24h TTL default (down from 7d; the long-lived service makes shorter defaults cheap). Verified end-to-end: - compose config -q, bash -n, sh -n all clean - HTTP /status returns 200 - stdio bridge returns initialize + tools/list with the same 3 tools (docs_sources, docs_refresh, docs_query) - doctor passes all 10 checks including the new HTTP probe - web-search and repomix MCP handshakes still work - redaction-check clean - install JSON valid for both targets + --absolute