Skip to main content

papermoon-mkdocs-mcp

A lightweight MCP server for MkDocs documentation sites. Reads markdown files directly from disk, provides full-text and optional semantic search, and exposes project structure through the Model Context Protocol.

Features

  • 5 MCP tools -- search, read_document, list_documents, get_project_info, get_document_outline
  • SQLite FTS5 keyword search with BM25 ranking (zero external dependencies)
  • Optional semantic vector search via sentence-transformers
  • Hybrid search combining keyword + vector results with Reciprocal Rank Fusion
  • Incremental indexing -- fast updates when files change
  • Persistent SQLite index that survives server restarts
  • Navigation-aware -- parses mkdocs.yml and .nav.yml
  • Excludable documents -- keep drafts and internal pages off the MCP surface
  • Security-first -- path traversal prevention, read-only search connections
  • Minimal dependencies -- 3 required, 2 optional

Installation

pip install papermoon-mkdocs-mcp

To enable vector search:

pip install papermoon-mkdocs-mcp[vector]

Quick Start

Run from the root of any MkDocs project (where mkdocs.yml lives):

cd /path/to/your/mkdocs-project
papermoon-mkdocs-mcp

Or point to a specific config file:

papermoon-mkdocs-mcp --config /path/to/mkdocs.yml

The server auto-detects mkdocs.yml in the current directory when --config is omitted.

Transport Options

By default the server uses stdio transport. You can switch to a network transport for remote or multi-client setups:

# Streamable HTTP (recommended for network access)
papermoon-mkdocs-mcp --transport streamable-http --host 0.0.0.0 --port 9000

# SSE (legacy client compatibility)
papermoon-mkdocs-mcp --transport sse --port 8080
Flag Default Description
--transport stdio stdio, sse, or streamable-http
--host 127.0.0.1 Bind address (network transports only)
--port 8000 Bind port (network transports only)

Security note: When binding to a non-loopback address, place the server behind a reverse proxy (e.g. nginx, Caddy) that terminates TLS.

MCP Client Configuration

Claude Desktop

Add to your Claude Desktop configuration file:

{
  "mcpServers": {
    "mkdocs": {
      "command": "papermoon-mkdocs-mcp",
      "args": ["--config", "/path/to/mkdocs.yml"]
    }
  }
}

Note: If Claude Desktop can't find the command (Failed to spawn process: No such file or directory), use the full path to the executable instead of just mkdocs-mcp:

{
  "mcpServers": {
    "mkdocs": {
      "command": "/path/to/.venv/bin/mkdocs-mcp",
      "args": ["--config", "/path/to/mkdocs.yml"]
    }
  }
}

This is common when the package is installed in a virtual environment whose bin/ directory isn't in Claude Desktop's PATH.

Claude Code / VS Code

Add to .mcp.json in your project root:

{
  "mcpServers": {
    "mkdocs": {
      "command": "papermoon-mkdocs-mcp",
      "args": ["--config", "/path/to/mkdocs.yml"]
    }
  }
}

Available Tools

Search documentation using keyword, semantic, or hybrid search.

Parameter Type Default Description
query str (required) The search query string
search_type str "hybrid" "keyword", "vector", or "hybrid"
max_results int 10 Maximum results to return (1--100)

Returns ranked results with path, title, relevance score (normalized 0.0--1.0), and text snippet.

read_document

Read a documentation file by its relative path.

Parameter Type Default Description
path str (required) Relative path from docs dir (e.g. guide/setup.md)

Returns the markdown body (frontmatter stripped), parsed frontmatter as a separate field, heading structure, and file metadata.

list_documents

List all documentation files, optionally filtered by section.

Parameter Type Default Description
section str or null null Directory prefix to filter by (e.g. guide)

Returns document metadata (path, title, description, categories, size, mtime).

get_project_info

Get MkDocs project metadata. Takes no parameters.

Returns site name, site URL, docs directory, theme, navigation tree, document count, and index status.

get_document_outline

Get the heading structure (table of contents) for a document.

Parameter Type Default Description
path str (required) Relative path from docs dir (e.g. guide/setup.md)

Returns the document title and a list of headings with level, text, and anchor.

Excluding Documents

Some markdown files are not worth exposing over MCP -- drafts, internal runbooks, generated scratch files. Add an mcp_exclude list under extra in mkdocs.yml:

site_name: My Docs

extra:
  mcp_exclude:
    - drafts/             # any directory named 'drafts', at any depth
    - internal/**         # anchored: only 'internal/' at the docs root
    - "*-scratch.md"      # by filename suffix, at any depth
    - "!internal/public.md"  # re-include one file from a broader rule

It lives under extra because this project isn't a registered MkDocs plugin, so MkDocs' own config schema has no way to know about mcp_exclude -- a bare top-level key trips Unrecognised configuration name warnings, which mkdocs --strict turns into a hard failure. extra is the one top-level key MkDocs leaves open for arbitrary data, so nesting there passes validation. (A bare top-level mcp_exclude still works for now as a deprecated fallback, with a warning logged.)

Exclusions apply everywhere at once. An excluded document is absent from the navigation tree, never enters the search index, does not appear in list_documents, and is refused by read_document and get_document_outline -- the refusal is identical to the response for a file that does not exist, so it does not reveal that the document is there.

mcp_exclude affects only this MCP server. It does not change what mkdocs build publishes.

Pattern syntax

Patterns are gitignore-style and match against a document's path relative to docs_dir.

Pattern Matches
drafts/ Any directory named drafts and everything under it
/drafts/ Only drafts/ at the docs root
internal/** Everything under a root-level internal/
*.tmp.md Files ending .tmp.md, at any depth
guide/*.md .md files directly in guide/ (not in subdirectories)
guide/**/*.md .md files anywhere under guide/
draft?.md draft1.md, draftx.md -- ? is a single character
draft[0-9].md A character class
!keep/this.md Re-includes a path an earlier pattern excluded
  • A pattern containing / is anchored at docs_dir; one without it matches at any depth.
  • A trailing / restricts a pattern to directories, so drafts/ does not hide a file named drafts.md.
  • Rules are evaluated in order and the last one to match decides, so put ! re-inclusions after the rule they carve out of.
  • Blank lines and # comments are ignored.

Newly excluded files are dropped from the index on the next run, and removing a pattern brings them back -- no need to delete .mkdocs-mcp.db.

Architecture

src/mkdocs_mcp/
  config.py      -- MkDocs config detection and nav parsing
  exclusions.py  -- mcp_exclude pattern matching
  repository.py  -- SQLite schema and CRUD operations
  indexer.py     -- Index orchestration with incremental updates
  searcher.py    -- Keyword, vector, and hybrid search
  server.py      -- FastMCP server with 5 tool definitions
  utils.py       -- Path validation, frontmatter parsing, text extraction
  models.py      -- Pydantic response models

At startup the server reads mkdocs.yml, scans the docs directory, and builds (or incrementally updates) a SQLite FTS5 index. Search queries hit the index directly; vector search embeds the query with all-MiniLM-L6-v2 and compares against stored document embeddings. Hybrid mode fuses both result lists using Reciprocal Rank Fusion.

Development

git clone https://github.com/aspect-build/mkdocs-mcp.git
cd mkdocs-mcp
pip install -e ".[dev]"
pytest

Linting and type checking:

ruff check .
mypy src/

Requirements

  • Python >= 3.10
  • Required: fastmcp (>=3.0, <4), pydantic (>=2.0, <3), pyyaml (>=6.0), markdown (>=3.4)
  • Optional (vector search): sentence-transformers (>=3.0), numpy (>=1.24)

License

See LICENSE for details.

Metadata

Release files for papermoon-mkdocs-mcp 0.2.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for papermoon-mkdocs-mcp 0.2.2
File Size Uploaded Provenance Actions
papermoon_mkdocs_mcp-0.2.2.tar.gz 66.7 kB With provenance Details for papermoon_mkdocs_mcp-0.2.2.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for papermoon-mkdocs-mcp 0.2.2
File Interpreter ABI Platform Actions
papermoon_mkdocs_mcp-0.2.2-py3-none-any.whl Python 3 none any Details for papermoon_mkdocs_mcp-0.2.2-py3-none-any.whl

Total release size: 100.7 kB

Release files / papermoon_mkdocs_mcp-0.2.2.tar.gz

Download URL papermoon_mkdocs_mcp-0.2.2.tar.gz
Size 66.7 kB
Tags Source
SHA-256 checksum
How to use checksums
5bef15e9c9107039279bd6981aa76acd1df9c19649eb827ea3a621612b8658da
BLAKE2b-256 checksum
How to use checksums
81ceabe4de3fbb4de42dc2fae7f57b8f6a9d621200af00521427e17c9d7dfe35
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Release files / papermoon_mkdocs_mcp-0.2.2-py3-none-any.whl

Download URL papermoon_mkdocs_mcp-0.2.2-py3-none-any.whl
Size 34.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
3939d4c901ae439ef235f0a06ed324c8ee9a041548fa0983d498caf54255c32d
BLAKE2b-256 checksum
How to use checksums
fd26d5c420ede4996bf1520f1f44d5eaa8ed504010e7c43e19b7bc17f64bdca7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

Security for papermoon-mkdocs-mcp 0.2.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for papermoon_mkdocs_mcp-0.2.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 14, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page