live-docs-mcp
# live-docs-mcp
A local-only MCP server that gives AI coding agents up-to-date
documentation for a specific library or tool while they're
implementing a feature — a context7-style capability that runs
entirely on your machine, with no hosted backend.
## Usage
Add it to your MCP client's server config, the same way you'd add any
other `npx`-based MCP server:
```json
{
"mcpServers": {
"live-docs": {
"command": "npx",
"args": ["-y", "live-docs-mcp"]
}
}
}
```
## Tools
- **search_library({ query })** — find a documented library by name
or alias. Returns `{ id, name, description, score, versions? }[]`
— `versions` lists the available version keys when a library has
more than one documented version.
- **search_docs({ libraryId, topic, version?, limit? })** — search a
library's documentation by topic, using the `id` from
`search_library`. If the library has multiple versions, `version`
is required — omitting it (or passing one that doesn't match)
returns an error listing the available keys; passing one for a
library that isn't versioned is also an error. Returns
`{ version?, results: { heading, snippet, sourceUrl, score }[] }`
— `version` is present only when the library is versioned.
## How it works
Each supported library has a config entry (`docsUrl`, `llmsTxtUrl`,
`llmsFullTxtUrl`, `githubUrl`, `npmPackage`, ...). When `search_docs`
is called, the server fetches documentation for that library in this
order, using the first one that resolves:
1. `llmsFullTxtUrl`
2. `llmsTxtUrl`
3. `docsUrl`, if it points directly at a markdown file
4. The repo's readme from `githubUrl`, as a last resort — `README.md`
by default, or the exact path set in `githubReadmePath` if the
repo uses a different filename or casing (e.g. `Readme.md`)
**`githubBranch` is required whenever `githubUrl` is set** — there is
no default-branch guessing of any kind. A config with `githubUrl` and
no `githubBranch` fails to load.
Beyond that first "seed" page, the server also resolves and fetches
additional pages, up to a fixed cap: markdown links found within an
`llmsTxtUrl`/`llmsFullTxtUrl` seed (restricted to links on the same
origin as the seed), and/or files under a configured `githubDocsPath`
in the library's GitHub repo. Both sources are best-effort — a failed
extra page is simply skipped and never breaks the request.
Fetched content is cached on disk (in your OS's standard cache
directory) for 24 hours by default, so repeat lookups are instant.
Override the TTL with the `LIVE_DOCS_MCP_TTL_MS` environment variable
(milliseconds).
## Multiple versions
A library with more than one actively-documented version (e.g.
Express 4.x and 5.x) can declare a `versions` map instead of its own
flat source fields — each version gets its own independent
`docsUrl`/`llmsTxtUrl`/`llmsFullTxtUrl`/`githubUrl`/`githubBranch`/`githubDocsPath`:
```json
{
"id": "widget",
"name": "Widget",
"versions": {
"v1": { "docsUrl": "https://widget.dev/v1/docs.md" },
"v2": { "docsUrl": "https://widget.dev/v2/docs.md" }
}
}
```
`versions` and the flat source fields are mutually exclusive on one
entry — set one or the other, never both. A `versions` map must have
at least one entry. There is no default version: `search_docs` always
requires an explicit `version` for a versioned library.
## Adding your own libraries
Built-in libraries live in this package. To add or override an entry
— for an internal/private library, or to patch a built-in's URLs —
create a JSON file at your OS's standard config directory, e.g. on
Linux: `~/.config/live-docs-mcp/tools.json`:
```json
[
{
"id": "my-internal-lib",
"name": "My Internal Lib",
"docsUrl": "https://docs.internal.example.com/my-lib",
"llmsTxtUrl": "https://docs.internal.example.com/my-lib/llms.txt",
"githubUrl": "https://github.com/acme/my-lib",
"githubBranch": "develop",
"githubDocsPath": "docs"
}
]
```
- `githubBranch` — the branch or tag to use for GitHub-based fetches.
**Required whenever `githubUrl` is set** — there is no default
branch guessing.
- `githubDocsPath` — a path within the repo (relative to its root) to
search for additional markdown docs, e.g. `"docs"`.
- `githubReadmePath` — the exact path to the repo's readme file, if it
isn't `README.md` (e.g. `"Readme.md"`). Optional; defaults to
`"README.md"`.
An entry whose `id` matches a built-in overrides that built-in's
fields; any other `id` is added alongside the built-ins. The merged
result is re-validated as a whole, so combining an override with a
built-in in a way that violates the schema (e.g. adding `versions` to
a builtin that already has flat fields set, or vice versa) causes the
**entire** user config file to be rejected — with an error logged to
stderr — falling back to built-ins only, rather than silently applying
a partial or broken merge.
**Upgrading note:** if your existing override sets `githubUrl` without
`githubBranch`, it now fails to load — the old implicit `main`/`master`
fallback no longer exists. Add an explicit `githubBranch` to fix it.
## Development
```bash
npm install
npm test # run the test suite
npm run build # compile to dist/
npm run dev # run the server directly from source via tsx
```
TDQS
Scored across 2 tools
search_library targets finding a library by name, while search_docs targets searching within a library's documentation by topic. The two tools have clearly distinct purposes and are complementary rather than overlapping.
Both tool names follow the same search_<noun> snake_case pattern. The naming is predictable and clearly indicates action and target.
Two tools is on the low end for a documentation-focused server, but each tool covers a distinct step in the lookup workflow. It feels minimal yet coherent.
The surface is limited to search operations; there is no way to list libraries, retrieve full documentation content, or navigate doc structure. Agents may be able to find relevant topics but cannot fetch the actual documentation content.