Metadata-Version: 2.4
Name: papermoon-mkdocs-mcp
Version: 0.1.0b2
Summary: A lightweight MCP server for MkDocs documentation sites
License-Expression: BSD-2-Clause
License-File: LICENSE
Keywords: documentation,mcp,mkdocs,model-context-protocol,search
Classifier: Development Status :: 4 - Beta
Classifier: License :: OSI Approved :: BSD License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Topic :: Documentation
Requires-Python: >=3.10
Requires-Dist: fastmcp<4,>=3.0.0
Requires-Dist: markdown>=3.4
Requires-Dist: pydantic<3,>=2.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: vector
Requires-Dist: numpy>=1.24; extra == 'vector'
Requires-Dist: sentence-transformers>=3.0; extra == 'vector'
Description-Content-Type: text/markdown

# 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`
- **Security-first** -- path traversal prevention, read-only search connections
- **Minimal dependencies** -- 3 required, 2 optional

## Installation

```bash
pip install papermoon-mkdocs-mcp
```

To enable vector search:

```bash
pip install papermoon-mkdocs-mcp[vector]
```

## Quick Start

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

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

Or point to a specific config file:

```bash
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:

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

# SSE (legacy client compatibility)
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:

```json
{
  "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`:

```json
{
  "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:

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

## Available Tools

### search

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.

## Architecture

```
src/mkdocs_mcp/
  config.py      -- MkDocs config detection and nav parsing
  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

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

Linting and type checking:

```bash
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](LICENSE) for details.
