Skip to main content
Glama
stevennevins

Daml/Canton Docs MCP

by stevennevins
README.md
# 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

C2.1/5.0

Scored across 6 tools

Disambiguation4/5

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.

Naming Consistency5/5

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.

Tool Count5/5

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.

Completeness4/5

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.

Maintenance

ActivityInactive
ResponsivenessNo issues