feat: mcp docs search tools - #289
Merged
Merged
Conversation
Adds SearchDocs and GetDoc as always-advertised gateway tools, so an agent can answer "how does CIPP do X" instead of guessing. Every other tool returns tenant data; these explain the product, which is what a model needs before it knows which data tool to reach for. Leaving them to be discovered via SearchTools would mean already suspecting the docs exist. The GitBook tree ships in the image (~2 MB of markdown) rather than being fetched from docs.cipp.app: there is no GitBook search API, llms-full.txt is capped at 100 of the 427 pages, and a crawl would put outbound internet in the request path. Shipping it also version-matches the docs to the build, and results still carry live docs.cipp.app links. Indexing lives in CIPPSharp for two measured reasons. Tokenising the corpus in PowerShell took 26s against ~2s in .NET, and the index is a host-scoped static, so it builds once per host rather than once per runspace - a PowerShell $script: cache would have rebuilt it for every worker in the pool. Retrieval is BM25 over heading-delimited sections with domain synonyms and fuzzy matching; results deep-link to the heading that matched. Link derivation is pinned against all 427 published URLs. One rule is not guessable from a path: a folder with no README.md is a GitBook grouping folder and is dropped from the URL, so email/resources/management/equipment/edit.md is served at email/management/equipment/edit. Seven pages would otherwise have had confidently wrong links. Pages GitBook does not publish get a GitHub link and no docsUrl rather than a URL that 404s. Also mounts docs/ into the dev containers at the same path the image uses, and un-excludes docs/ from the context-root .dockerignore - that file is what Dockerfile.release resolves to, so without it the release build fails on the new COPY while dev builds fine.
Update `Get-CippDocsRoot` to prefer `CIPPDocsPath` and only accept candidate folders that actually contain markdown, preventing empty `backend/Docs` mountpoints from shadowing real docs and causing zero-result searches. Align dev compose files to mount docs at `/app/Docs` and set `CIPPDocsPath`, add targeted Pester coverage for docs root selection behavior, and refresh the generated OpenAPI spec to reflect related endpoint metadata updates.
Config/DocsPublishedPages.txt decides whether a SearchDocs result gets a docs.cipp.app link or falls back to GitHub, and only docs.cipp.app/llms.txt knows which pages are actually live. Until now that list was whatever someone last committed, so a page published after the snapshot stayed unlinkable until a human remembered to re-run the script. A build-docspages stage now refreshes it from the live site and overwrites the committed copy in the image, alongside how openapi.json and function-parameters.json are already generated. The committed file becomes the fallback rather than the source of truth. The fetch must never take the build down with it, so -AllowFallback warns and leaves the committed list in place instead of throwing. That covers both a failed request and a request that succeeds but parses to nothing - a captive portal or an error page answers 200 with a body yielding zero slugs, and overwriting a good list with that would strip the docs link off every result. ARG BUILD_DATE is declared in the stage purely to bust the layer cache. Its only other inputs are the script and the committed list, so without it Docker would reuse an earlier layer and ship a stale list despite the stage existing. The stage is tiny and independent, so unlike the version args near the frontend build it invalidates nothing expensive.
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.
No description provided.