A small docs MCP server: search, retrieve, and keep track of the source A developer built two small TypeScript MCP stdio servers, tailwind-docs-mcp and hermes-docs-mcp, that let AI agents search, retrieve, and list documentation pages without an embedding service or vector database. Each server exposes search, get, and list tools, with a source-specific MDX parser and a scorer that weights title and slug matches over body mentions and recognizes utility families like bg-red-500 for background-color. The developer notes search is a navigation step rather than a substitute for reading the full page, since snippets can omit warnings or conditions. An agent can remember an API that no longer matches the project in front of it. Giving it documentation helps, but the source matters: the newest documentation and the documentation for an installed version are not necessarily the same. I use two small TypeScript servers to make that distinction explicit: tailwind-docs-mcp https://github.com/seppegadeyne/tailwind-docs-mcp reads Tailwind's documentation source, while hermes-docs-mcp https://github.com/seppegadeyne/hermes-docs-mcp prefers a local Hermes documentation tree and falls back to GitHub. Both expose search, retrieval, and listing over MCP stdio. Neither needs an embedding service or vector database. The interesting engineering is in parsing the documentation, ranking a useful page above an incidental mention, and knowing when the index is stale. Each server has three tools: | Job | Tailwind | Hermes | |---|---|---| | Find candidate pages | search tailwind docs | search hermes docs | | Read one page | get tailwind doc | get hermes doc | | Browse available slugs | list tailwind docs | list hermes docs | Search returns titles, slugs, source URLs, and snippets. The agent selects a slug and retrieves the page before answering. Listing helps when it does not know the right terminology; Hermes also supports filtering by section. I prefer this to returning an entire manual for every question. Search is a navigation step, though, not a substitute for reading the page. A snippet can omit a warning or the condition that makes an example valid. Unknown slugs return an MCP error with suggested matches. Neither server needs a tool that writes into the consuming project's files. Tailwind's adapter reads MDX under src/docs in tailwindlabs/tailwindcss.com . It extracts exported titles and descriptions, headings, recognizable utility classes, and literal API-table rows. It removes selected MDX wrappers to produce Markdown-like content. This is a source-specific parser, not an MDX runtime. It does not execute documentation components. Computed tables and unusual component syntax can lose information, and the cleanup can alter code-like expressions. Use the linked documentation page when exact presentation or a complete generated example matters. The search scorer gives title and slug matches more weight than body mentions. It also recognizes utility families: a color utility such as bg-red-500 gets a boost toward background-color . That domain knowledge matters because many unrelated examples contain background classes. A plain text match can find a real occurrence on the wrong reference page. During verification, this call to search tailwind docs ranked background-color first: {"query":"bg-red-500 background","limit":3} Then retrieve the selected page with get tailwind doc : {"slug":"background-color"} Those calls were executed against the pinned server. They show one working query, not a search-quality benchmark across the whole documentation set. You need Git, npm, Node.js 20 or newer, and an MCP client that can launch stdio servers. GitHub access is needed for the default remote sources. A local documentation directory avoids those runtime fetches; Node and the server's npm dependencies are still required. These are Bash commands for Linux, macOS, or WSL. Native Windows is not tested here. Start in a directory where you want the checkouts: git clone https://github.com/seppegadeyne/tailwind-docs-mcp.git cd tailwind-docs-mcp git checkout --detach 072985944b26721d3c8d8161255fdde97da5f47e npm ci --ignore-scripts npm test npm run build cd .. git clone https://github.com/seppegadeyne/hermes-docs-mcp.git cd hermes-docs-mcp git checkout --detach 0decc76d0d9a4f5b54ffa8b73c4dcc9f5d9c018b npm ci --ignore-scripts npm test npm run build The locked installs and builds passed during verification on Linux with Node 25.2.1 and npm 11.6.2. Tailwind's three tests and Hermes's 15 tests passed. These suites check parser and search behavior using fixtures; the separate MCP smoke tests exercised discovery and real remote retrieval. If you have not installed Hermes yet, my guide on Voltti walks through installing Hermes with the desktop app or terminal https://voltti.ai/en/insights/install-hermes-desktop-app-or-terminal . Return here once your client is ready; the configuration below connects it to the documentation servers. For an existing Hermes client, merge the following into its configuration, using your own absolute paths. The syntax follows the official MCP guide https://hermes-agent.nousresearch.com/docs/user-guide/features/mcp . mcp servers: tailwind-docs: command: node args: "/absolute/path/to/tailwind-docs-mcp/dist/cli.js" timeout: 180 connect timeout: 60 enabled: true hermes-docs: command: node args: "/absolute/path/to/hermes-docs-mcp/dist/cli.js" timeout: 180 connect timeout: 60 enabled: true Check discovery before asking a model to use the tools: hermes mcp test tailwind-docs hermes mcp test hermes-docs Discovery alone does not verify indexing: loading happens when a documentation tool is called. Follow it with the search and retrieval examples. Other clients need their own configuration format. Hermes's adapter checks HERMES DOCS DIR , then its conventional local checkout location, and otherwise reads website/docs from NousResearch/hermes-agent on GitHub. Unlike the Tailwind local loader, the Hermes loader walks nested directories and accepts both Markdown and MDX. It reads simple frontmatter metadata, derives slugs from paths, preserves fenced code, and converts Docusaurus admonitions into text markers. Its parser does not implement every frontmatter feature; a custom route declared in metadata is not necessarily the path-derived URL it returns. A local tree can correspond to the installed software, provided you point it at that installation and account for local modifications. The GitHub fallback follows main . It does not promise that the returned docs describe your installed release. The fallback was exercised with an empty home directory and no local override. Search, retrieval, and listing succeeded. The actual list response began: Hermes Agent docs: 3 of 440 pages installed commit unknown . That unknown matters. The current commit helper inspects a local Git checkout; it does not attach a resolved remote SHA to fallback content. The wording says “installed commit” even on the remote path. Do not interpret it as verified version provenance. For a known page, this is the argument to get hermes doc : {"slug":"user-guide/features/mcp"} The Glama listing https://glama.ai/mcp/servers/seppegadeyne/hermes-docs-mcp provides discovery, not evidence of a successful hosted deployment. The standalone test establishes that the source loader works without a local Hermes checkout. Hosting still needs the runtime, a transport arrangement, and network access. Both remote loaders cache their index in process memory without a time-based refresh. Restarting the process rebuilds it on the next request. Hermes caches its local index for 60 seconds; Tailwind rereads its local directory on each load. For reproducible documentation, check out the upstream doc repository at a chosen commit and point the server at it. These are illustrative environment-variable examples; replace the paths with actual documentation directories and start the command from the corresponding server checkout: TAILWIND DOCS DIR=/absolute/path/to/tailwindcss.com/src/docs npm start HERMES DOCS DIR=/absolute/path/to/hermes-agent/website/docs npm start Set those variables in the client's server environment for normal MCP use. An explicitly configured but invalid Hermes directory fails locally rather than silently selecting GitHub. Pinning the MCP adapter does not pin remotely fetched docs. The current loaders request the tree and individual files through moving main references, so an upstream change during indexing could mix revisions. They also fetch pages with Promise.all ; they do not implement bounded concurrency or a persistent disk cache. A network failure can prevent the index from loading. Start with a normalized page record and tests for your source format. Preserve its URL, source path, and code examples. Build a small query set with expected reference pages, including terms that occur in many examples. The live Hermes query mcp servers , for example, ranked a plugin guide first during verification. Lexical scoring is understandable, but it still needs evaluation. Before distributing a corpus, check the documentation's own license and attribution requirements. Public source access is not a blanket redistribution license. Treat retrieved text as reference material, not instructions that grant the agent new permissions. For a production adaptation, I would resolve one source SHA before fetching, report it with results, bound fetch concurrency, and define an explicit refresh policy. Those are improvements to make, not features to assume these versions already have. The small tool surface is reusable. The parser, ranking rules, and version policy are the parts that need to fit the documentation you are serving.