lichtblick-docs-mcp
Official# @lichtblick/docs-mcp
MCP server exposing the Lichtblick documentation and the @lichtblick/suite extension API to AI agents
## Tools
| Tool | Purpose |
| -------------------- | ----------------------------------------------------------------------- |
| `docs_search` | Full-text search over docs and guides, returns sections with URL anchor |
| `docs_fetch` | Full markdown of a page, by path or URL |
| `docs_list` | All pages with path and summary, optionally filtered by section |
| `extension_api_get` | TypeScript declaration and doc comments of a `@lichtblick/suite` symbol |
| `extension_api_list` | All symbols exported by `@lichtblick/suite` |
Each page is also exposed as an MCP resource: `lichtblick-docs://<path>`.
## How it works
- **Docs**: on first use, reads `llms.txt` from the docs site (generated by `docusaurus-plugin-llms`), fetches
each page's `.md` route (generated by `docusaurus-plugin-copy-page-button`) and builds an in-memory
[MiniSearch](https://github.com/lucaong/minisearch) index of `##`/`###` sections. No build step or release is needed when the docs change.
- **Extension API**: parses the TypeScript sources shipped in the pinned `@lichtblick/suite` dependency, following
the re-exports of `src/index.ts`.
- **Transport**: stdio. The client spawns the process; no port is opened. All tools are read-only.
## Setup
Requires Node.js 22.12+ with `npx` on the `PATH` seen by the client. The client starts the server with `npx`, which
downloads the pre-built package from npm: nothing is cloned or compiled on your machine. Pin a version (replace
`0.1.0` with the [latest release](https://www.npmjs.com/package/@lichtblick/docs-mcp)) so updates are explicit.
### VS Code (GitHub Copilot)
Add the server to `.vscode/mcp.json` in a workspace, or to the user configuration (**MCP: Open User
Configuration**):
```json
{
"servers": {
"lichtblick-docs": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@lichtblick/docs-mcp@0.1.0"]
}
}
}
```
Start it from **MCP: List Servers** (or the **Start** action shown above the entry) and use Copilot Chat in agent
mode.
### Cursor
Add to `~/.cursor/mcp.json` (all projects) or `.cursor/mcp.json` (one project):
```json
{
"mcpServers": {
"lichtblick-docs": {
"command": "npx",
"args": ["-y", "@lichtblick/docs-mcp@0.1.0"]
}
}
}
```
### Claude Code
```bash
claude mcp add lichtblick-docs --scope user -- npx -y @lichtblick/docs-mcp@0.1.0
```
Or add the Cursor snippet above to `.mcp.json` at the project root.
### Agent instructions
Agents sometimes answer from memory or the web even when the server is available. Copy
[agent-instructions.md](agent-instructions.md) into the repository's `.github/copilot-instructions.md`, `AGENTS.md`
or `CLAUDE.md` so they call the tools first.
### Notes
- **Updates**: change the pinned version in the configuration and restart the server. Unpinned
(`@lichtblick/docs-mcp`) uses whatever version is in the npm cache.
- **Checking that it is used**: the chat shows each tool call (for example `docs_search`) with its input and output.
If the agent answers from the web instead, ask it to use the Lichtblick docs tools, or reference a tool directly
(`#docs_search` in VS Code). The server also logs every tool call to stderr, shown in the client's MCP output log.
- **Verifying the package**: `npm audit signatures` only checks packages installed in the current project, not
packages run with `npx`. To verify the provenance of this package, install the pinned version in a temporary
project and audit it there:
```sh
mkdir /tmp/verify-docs-mcp && cd /tmp/verify-docs-mcp
npm init -y && npm install @lichtblick/docs-mcp@0.1.0
npm audit signatures
```
## Configuration
| Variable | Default | Description |
| -------------------------- | ------------------------------------------ | --------------------------------------------------------------------------- |
| `LICHTBLICK_DOCS_SITE_URL` | `https://lichtblick-suite.github.io/docs/` | Public docs URL; `llms.txt` links are resolved against it |
| `LICHTBLICK_DOCS_SOURCE` | value of `LICHTBLICK_DOCS_SITE_URL` | URL or local Docusaurus `build/` directory to read `llms.txt` and pages from |
| `LICHTBLICK_DOCS_LOG` | (on) | Logs every tool call to stderr as JSON; `off` disables logging |
To test unpublished docs, build the docs repo and point `LICHTBLICK_DOCS_SOURCE` at its `build/` folder. Variables
go in the `env` object of the server entry in the client configuration.
### Logging
stdout carries the MCP protocol, so logs go to stderr as one JSON object per line:
- `ready`: server version and docs source.
- `docs_index`: pages and sections indexed, duration, and the pages that were skipped with the reason.
- `tool_call`: tool, arguments, duration in ms and whether it failed.
### Checking the docs
`npx @lichtblick/docs-mcp check` fetches every page listed in `llms.txt` of `LICHTBLICK_DOCS_SOURCE` and exits with
code 1 if any of them does not resolve to its `.md` page. CI runs it on every PR against the published docs.
## Development
```bash
npm install
npm run build
npm test # vitest
npm run test:coverage # vitest with coverage (80% threshold)
npm run test:smoke # check every llms.txt page of the published docs (needs a build)
npm run typecheck
npm run dev # tsc --watch
npm run inspect # MCP Inspector UI
```
Open this folder in VS Code; [.vscode/mcp.json](.vscode/mcp.json) registers the local build. Start it from
**MCP: List Servers**.
## Releasing
1. Add the changes under a new `## [<version>]` heading in [CHANGELOG.md](CHANGELOG.md) and bump `version` with
`npm version <patch|minor|major> --no-git-tag-version`.
2. Merge to `main`, then push a matching tag: `git tag v<version> && git push origin v<version>`.
3. The [release workflow](.github/workflows/release.yml) tests the package, publishes it to npm with provenance
(trusted publishing, no npm token) and creates the GitHub release from the changelog entry.
## Known limitations
- `docusaurus-plugin-llms` writes file-based URLs into `llms.txt` and ignores `slug`/`id` front matter. The pages
that returned 404 for this reason were fixed in the docs repository; the `check` smoke test fails if it happens
again. Until it is fixed, such a page is listed but skipped, and reported in the `docs_index` log.
- Docs are fetched once per server process; restart the server to pick up documentation changes.
- The extension API only covers what `@lichtblick/suite` exports; it is updated by bumping the dependency and
releasing a new version.
TDQS
Scored across 5 tools
Each tool has a distinct role: docs_list browses the page index, docs_search finds sections by keyword, docs_fetch reads a full page, and the two extension_api tools split symbol discovery from symbol retrieval. The descriptions explicitly state the hand-off relationships (list/search → fetch, list → get), leaving no realistic misselection.
Names follow a predictable resource_action pattern in snake_case, split into two clean namespaces: docs_* (list/search/fetch) and extension_api_* (list/get). The only variance is fetch vs get across the two namespaces, which is justified by their different semantics (full page vs symbol declaration).
Five tools is tightly scoped to the two jobs of the server: documentation lookup and extension API reference. Every tool earns its place, with no redundant or filler operations.
The docs surface is complete (enumerate, search, retrieve) and the API surface covers symbol enumeration and declaration lookup. A minor gap is that the extension API can only be queried by exact symbol name after listing, with no full-text/typeahead search over declarations, which could slow discovery for loosely-named symbols.