Daml/Canton Docs MCP
# Daml/Canton Docs MCP
This repository builds and serves local MCP-searchable documentation indexes for the Daml, Canton, Canton Network, DPM, CN Quickstart, and Splice documentation sources.
The installed command is `docs-mcp`. It can:
- sync configured documentation sources into `.docs/`
- build SQLite FTS5 indexes for local search
- query an index from the command line
- serve an index over stdio or streamable HTTP as an MCP server
The primary docset is `daml`, which combines:
- `daml-sdk` from `digital-asset/daml`
- `canton` from `digital-asset/canton`
- `dpm` from `digital-asset/dpm`
- `cn-quickstart` from `digital-asset/cn-quickstart`
- `canton-network` from `docs.canton.network`
- `splice` from `canton-network/splice`
## Setup
Requirements: Python 3.10+, `uv`, and Git.
```bash
uv sync
uv run docs-mcp list
```
## Build or refresh indexes
Build the combined Daml/Canton index:
```bash
uv run docs-mcp update daml \
--export-dir .docs/daml \
--db-path .docs/daml/docs_index.db
```
Build an individual source index by replacing `daml` with a configured docset, for example `canton`, `daml-sdk`, `canton-network`, or `splice`.
Generated sources, caches, and indexes live under `.docs/` and `.cache/` and are ignored by Git.
## Use through [mcporter](https://mcporter.sh/)
This is the expected usage path for agents: register the `daml` docs server with [mcporter](https://mcporter.sh/), then call the generated tools on demand instead of loading the MCP server directly into every session.
Add a server entry to `~/.mcporter/mcporter.json` or to a project-local `config/mcporter.json`. Use absolute paths because mcporter may start the server outside this checkout.
```json
{
"mcpServers": {
"daml": {
"command": "/absolute/path/to/uv",
"args": [
"run",
"--directory",
"/absolute/path/to/daml-docs-mcp",
"docs-mcp",
"--root",
"/absolute/path/to/daml-docs-mcp",
"serve",
"daml",
"--export-dir",
"/absolute/path/to/daml-docs-mcp/.docs/daml",
"--db-path",
"/absolute/path/to/daml-docs-mcp/.docs/daml/docs_index.db"
]
}
}
}
```
Verify the registration and call the search tool:
```bash
mcporter list daml --schema
mcporter call daml.search_daml --args '{"query":"contract keys","scope":"chunks","limit":8}'
```
Refresh the index through the same registered server:
```bash
mcporter call daml.refresh_daml_index
```
## Query locally
```bash
uv run docs-mcp query daml \
--db-path .docs/daml/docs_index.db \
--scope chunks \
--limit 8 \
"contract keys"
```
Combined `daml` results prefix categories with their member docset, such as `canton:sdk`, so callers can tell which source matched.
## Serve as MCP
Serve over stdio for an MCP client:
```bash
uv run docs-mcp serve daml \
--db-path /absolute/path/to/daml-docs-mcp/.docs/daml/docs_index.db
```
Serve over streamable HTTP:
```bash
uv run docs-mcp serve daml \
--db-path .docs/daml/docs_index.db \
--transport streamable-http \
--port 8765
```
MCP client configs should use absolute paths for this repository and for `--db-path`, because clients may start the server from a different working directory.
## Configurations
Docsets are configured in `configs/*.json`. `configs/daml.json` is the combined index; the other Daml/Canton-related files define the source repositories, website source, public URL mapping, and file suffixes copied into the export.
`configs/hermes.json`, `configs/claude_code.json`, and `configs/template.json` remain from the upstream docs MCP template and are not part of the Daml/Canton package workflow.
## Development checks
Run these before changing CLI, export, indexing, or MCP behavior:
```bash
uv run ruff format --check .
uv run ruff check .
uv run mypy
uv run python -m unittest discover -s tests -v
```
## Project map
- `docs_mcp/cli.py`: `docs-mcp` command entry point.
- `scripts/sync_docset.py`: syncs sources and rebuilds exports/indexes.
- `scripts/export_docs.py`: copies docs and writes sitemap/export files.
- `scripts/build_fts_index.py`: builds SQLite FTS5 indexes.
- `scripts/query_fts.py`: queries indexes from the CLI.
- `scripts/docs_mcp_server.py`: serves MCP tools.
- `configs/`: docset configuration files.
- `tests/`: regression tests.
## License
MIT. See `LICENSE`.
TDQS
Scored across 6 tools
Each tool has a clear primary purpose: search, get a doc, get a chunk, list pages, inspect index, and refresh index. The only potential ambiguity is between get_daml_doc and get_daml_chunk, which could be confused without detailed descriptions, but their names suggest a whole-part relationship.
All tool names follow a consistent verb_daml_entity pattern using snake_case (e.g., search_daml, get_daml_doc, refresh_daml_index). The verb is consistently placed first and the suffix 'daml' appears uniformly, making the naming predictable and scannable.
With 6 tools, the server is well-scoped for a documentation retrieval and indexing service. The count covers search, retrieval, list, and index management without unnecessary bloat, making it easy for agents to choose the right tool.
The tool surface covers the core documentation workflow: searching, retrieving, listing, and index maintenance. A minor gap is that there is no explicit tool to fetch all chunks for a document at once, but this is likely achievable via list_daml_pages and repeated get_daml_chunk calls.