mcp-documentation
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@mcp-documentationsearch docs for 'L3Out' in networking"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
MCP Documentation
An MCP (Model Context Protocol) server that exposes indexed documentation —
PDFs today, plain text/Markdown too, and more formats can be added — with
full-text search and paginated chunk retrieval. Documents are extracted and
chunked ahead of time into a local SQLite database
(documents/document_chunks/chunks_fts); the server only ever reads
from it, it never touches your source files.
Why this exists
A full RAG setup — embeddings, a vector store, re-indexing pipelines, chunk strategy tuning — is a lot to build and keep running just to let an LLM search a folder of documents. This server is the deliberately simpler alternative: SQLite's FTS5 for keyword search, plain chunked text for retrieval, and nothing else to operate. No embedding model to keep in sync, no vector db to run, no ongoing tuning — just a database file and one CLI to (re)index it.
Related MCP server: Markdown RAG MCP
Available tools
Tool | Description |
| Full-text search over indexed chunks (see Search). Returns up to |
| List categories, subcategories, and files as a nested tree, optionally scoped to one category. Each file entry includes its chunk count. |
| Same tree, without file names — just the category/subcategory structure. |
| Read specific chunks of one document, up to |
Search
search_doc returns {results, next_offset}. Each result has the
document's category/subcategory/file_name, the chunk_number, the
chunk's page_start/page_end (null for .txt/.md) and section
(nearest heading before the chunk, or null), a BM25 score (higher is
better), and a snippet: about 32 words around the hits, with the hits
wrapped in **. Fetch the whole chunk with read_doc.
Filters:
category,subcategory(also matches nested subcategories:ciscomatchescisco/aci) andfile_namenarrow the search.Paging: when more matches exist,
next_offsetis set; pass it back asoffsetfor the next page. It isnullon the last page.
pattern is an SQLite FTS5 query
over the default unicode61 tokenizer:
Matching is case-insensitive and word-based. Punctuation splits words, so
MP-BGPis indexed as the two wordsmpandbgp.Space-separated terms must all match (implicit
AND).OR,NOT,"phrases",prefix*andNEAR(a b, 10)are supported.A bare
-is query syntax, soMP-BGPunquoted is an error. Quote any term containing punctuation:"MP-BGP". Invalid queries return an error saying so.There are no synonyms. Widen a search with
OR, e.g.L3Out OR "external routing".
Examples: BGP AND OSPF AND L3Out, "MP-BGP", NEAR(bgp ospf, 10),
config*.
Document identity
Every tool identifies a document by (category, subcategory, file_name):
categoryandsubcategorycome from where the source file lives (see Ingesting documents below).subcategoryis a single slash-joined string (e.g."switches/access") ornullfor a file with no subcategory.file_nameis the source file's name with its extension stripped (e.g.config-guide.pdf→"config-guide"), as returned bylist_doc/search_doc.
If two different source files share the same stem in the same
category/subcategory (e.g. notes.pdf and notes.md side by side),
read_doc fails with an explicit error rather than silently picking one —
rename one of them, or ingest them under different categories.
Ingesting documents
Documents get into the database via the standalone mcp-documentation-ingest
CLI, not through an MCP tool — indexing is a deliberate, out-of-band step.
# One or more files, category given explicitly (shared by all of them)
mcp-documentation-ingest -f /path/to/config-guide.pdf --category devices
mcp-documentation-ingest -f /path/to/notes.md /path/to/vlans.pdf --category devices --subcategory switches/access
# A whole tree — category/subcategory derived from folder names
mcp-documentation-ingest -d /path/to/documentation
# Removal — every entry for a file name, just one category's entry, or
# every document in the tree's category folders
mcp-documentation-ingest -f config-guide.pdf --remove
mcp-documentation-ingest -f notes.md vlans.pdf --remove --category devices --subcategory switches/access
mcp-documentation-ingest -d /path/to/documentation --remove
# List what's indexed: category, subcategory, file name
mcp-documentation-ingest --list
# Print the version and exit (also logged at the start of every run)
mcp-documentation-ingest --versionOnly the file name (e.g. config-guide.pdf) is stored as a document's
source; together with category/subcategory it identifies the document. The
path as you passed it on the command line is kept in the document's
metadata as file_path. Consequences:
Two files with the same name in the same category/subcategory are the same document — ingesting the second replaces the first.
-f … --removematches by file name only, so it works even after the file has been deleted from disk.-d … --removeremoves every document in the categories that are top-level folders of the given directory (which must exist).
Upgrading from 0.8.x or older: 0.9.0 changed the database schema and the PDF extraction. Delete the database file (
db_path, see Configuration) and re-ingest.
Duplicate content is rejected. If a file's SHA-256 content hash matches
a document that is already indexed (under any category or name), ingesting it
fails with identical content already indexed as <category>/<subcategory>/<file>.
In directory mode that counts as one failed file; the rest of the run
continues. This means the same file can't be indexed under two categories.
Moving a file to another folder in the tree is not a duplicate: vanished
documents are removed before anything is ingested.
In directory mode, the first folder under the given directory becomes
category, and every folder below that is joined with / into
subcategory (no depth limit) — e.g.
documentation/devices/switches/access/config-guide.pdf becomes
category devices, subcategory switches/access. A file sitting directly
in the given directory (no category folder at all) is reported as a failure
for that file, without aborting the rest of the run. Hidden files and
folders (name starting with ., e.g. .git/) are ignored at any depth.
Ingestion is incremental: a file's mtime is checked first, falling back
to a SHA-256 content hash if the mtime changed (so a touch with no real
edit doesn't trigger a re-extraction). In directory mode, files that
disappeared — or moved to a different category/subcategory — since the last
run are removed from the database; this cleanup only looks at the categories
that are top-level folders of the given directory, so documents in other
categories (e.g. added with -f) are left alone.
Progress is logged to stderr as the run goes:
Found 3 supported file(s) in documentation
Removed devices/old-guide.pdf (no longer on disk)
[1/3] documentation/devices/config-guide.pdf
Indexing documentation/devices/config-guide.pdf ...
Added documentation/devices/config-guide.pdf: 181 page(s), 412 chunk(s), 523104 chars in 58.31s
[2/3] documentation/devices/switches/intro.md
Skipped documentation/devices/switches/intro.md (unchanged)
...
Ingest complete in 61.02s: scanned=3 added=1 updated=0 removed=1 skipped=2 failed=0Each run ends with that summary (-f mode has no scanned/removed), plus a
reason per failure.
Supported file types are a small registry in ingest/extractors.py —
.pdf and .txt/.md (read as plain UTF-8) today. Adding a new format is
one function in that file, no changes needed elsewhere.
PDFs are converted page by page to Markdown with
pymupdf4llm. Its layout model
detects headings, lists and tables and drops page headers and footers. OCR is
off. A cleanup pass then removes leftover markup, lines repeated on most
pages (e.g. Page 11 of 181), lone bullet characters and runs of blank
lines. Layout analysis costs about 0.3 s per page, so a large document takes
a few minutes to ingest.
Chunks are cut at natural boundaries rather than at a fixed offset. Once a
chunk is at least half of chunk_size, it ends at the next Markdown
heading. Otherwise it ends at the last blank line, then sentence end, then
whitespace before chunk_size. Each chunk stores the pages it spans and the
nearest heading before it (section).
Prerequisites
Installation
uv tool install git+https://github.com/kapitankaszanka/MCP-Documentation.gitThis creates two commands: mcp-documentation (the server) and
mcp-documentation-ingest (the indexer, see above). To upgrade later:
uv tool upgrade mcp-documentationConfiguration
On first start the server copies the bundled config.yaml and logging.yaml
templates into the platform config directory, if they are not there already
(your edits are never overwritten):
Linux:
~/.config/mcp/mcp-documentation/Windows:
%APPDATA%\mcp\mcp-documentation\
config.yaml:
db_path: null # optional — defaults to the platform data dir if unset
max_search_results: 5
max_chunks_per_read: 5
chunk_size: 2048
chunk_overlap: 254db_path— path to the SQLite database file. Defaults to~/.local/share/mcp/mcp-documentation/mcp-documentation.db(Linux) /%LOCALAPPDATA%\mcp\mcp-documentation\mcp-documentation.db(Windows) if unset. Shared by the server and themcp-documentation-ingestCLI — both must point at the same file.max_search_results— cap on how many chunkssearch_docreturns, and the page size for itsoffsetpaging.max_chunks_per_read— cap on how manychunk_numbersread_docaccepts per call; request a wider range in several calls.chunk_size— maximum characters per chunk when ingesting a document.chunk_overlap— up to this many characters from the end of a chunk are repeated at the start of the next one (starting on a word boundary), so a match sitting on a chunk boundary still has context in at least one chunk. No overlap is added when a chunk ends at a heading.
Changing chunk_size/chunk_overlap only affects documents ingested (or
re-ingested) after the change — it doesn't retroactively re-chunk what's
already in the database.
Environment variable overrides
Variable | Overrides |
| Path to |
| Path to |
Resolution order for the config/logging file paths themselves: env var →
user config dir. If neither file exists, built-in defaults are used. Everything inside
config.yaml (including db_path) is read only from that file — set it
there, not via an env var.
Running the server
mcp-documentation supports two transports, chosen with --transport:
# stdio (default) — for a client that spawns the server as a subprocess
# and talks JSON-RPC over stdin/stdout (e.g. Claude Code, Claude Desktop).
mcp-documentation
mcp-documentation --transport stdio
# Streamable HTTP — for a client that connects over the network instead.
mcp-documentation --transport http --host 127.0.0.1 --port 9002--transport—stdio(default) orhttp.--host— bind address forhttp(default127.0.0.1); ignored onstdio.--port— bind port forhttp(default9002); ignored onstdio.-v,--version— print the version and exit.
The version is also logged on every start (Starting mcp-documentation <version> …).
On stdio, stdout is reserved entirely for the JSON-RPC stream — nothing
else may write to it (see Logging). On http, the server runs
as a Streamable HTTP endpoint at http://<host>:<port>/mcp/, served by
Uvicorn.
Supported MCP protocol
Built on FastMCP 4.x
(fastmcp>=4.0.0), which implements the MCP specification's Streamable HTTP
and stdio transports and negotiates the protocol version per-connection with
the client — no version needs to be picked or configured here. The
underlying mcp/mcp-types packages this pulls in support protocol
versions 2024-11-05 through 2025-11-25 (handshake-compatible) and
2026-07-28 (latest); a client requesting an older or unrecognized version
gets FastMCP's standard negotiation-failure response rather than a silent
mismatch.
Logging
logging.yaml follows logging.config.dictConfig. A relative handler
filename is rewritten at startup into the platform log directory, so it works
unchanged on both OSes. console_stdout is disabled by default on purpose:
stdout carries the JSON-RPC stream on stdio transport and any extra output
would corrupt it.
Development
uv sync
uv run pytest
uvx ruff check
uvx pyrefly checkA pre-push hook in .githooks/ runs all three checks and blocks the push
if any fails. Enable it once per clone:
git config core.hooksPath .githooksOut of scope
OCR of scanned PDFs.
Semantic/embedding search.
Shelling out to external binaries.
Writing to the source documents.
Authentication — assume local/trusted use.
Available Tools
4 toolslist_categoriesList CategoriesA
List indexed categories and subcategories, without file names.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| categories | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full transparency burden. It only says 'List indexed categories and subcategories, without file names,' and does not disclose whether this is read-only, how results are ordered, whether pagination exists, or any other behavioral constraints.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence with no wasted words: 'indexed' scopes the operation, 'categories and subcategories' names the resource, and 'without file names' adds disambiguation from file-oriented siblings.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a parameterless listing tool with an output schema, this description is largely complete: it says what the tool returns and what it omits. The only gap is the lack of explicit sibling-tool routing, but that is a usage-guideline issue rather than a core completeness issue.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and an empty input schema, so there are no parameter semantics for the description to explain. The baseline of 4 applies because no parameter documentation is needed.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List'), names the resource ('indexed categories and subcategories'), and explicitly excludes file names. This clearly distinguishes it from the sibling list_doc tool, which likely lists documents.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'without file names' implies this is for category-level browsing rather than file retrieval, but it does not explicitly mention alternatives or state when to prefer this tool over list_doc, read_doc, or search_doc. Usage context is implied, not fully spelled out.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_docList DocA
List indexed categories, subcategories, and files.
Returns:
A nested category/subcategory tree. Each file entry carries its
chunks_num so read_doc's pagination bounds are visible up
front.
| Name | Required | Description | Default |
|---|---|---|---|
| category | No | Restrict to one top-level category, or null for all |
Output Schema
| Name | Required | Description |
|---|---|---|
| categories | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden, and it does disclose the key behaviors: the operation lists data without indicating mutation, and it returns a nested tree with file-level chunk counts. It also adds the cross-tool purpose of chunks_num, which is useful context beyond the schema. It stops short of mentioning data freshness, auth constraints, or potential size limits, but for a simple read/list tool these are minor gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is short, front-loaded with the core action, and every sentence earns its place. The Returns block is compact and adds only the cross-tool pagination insight that an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple, optional-parameter listing tool with an output schema, the description is nearly complete: it states scope, return shape, and the purpose of chunks_num. It lacks explicit routing versus sibling tools, but the output schema and schema-covered parameter leave no fatal gaps for invoking it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the category parameter is fully explained in the schema (optional, null means all, restrict to top-level). The description adds no parameter-level meaning, which is acceptable because the schema already does the work; baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('List indexed categories, subcategories, and files') and immediately clarifies that the result is a nested tree with file entries, which separates it from the sibling list_categories and search_doc. The cross-reference to read_doc further anchors its identity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The 'chunks_num ... so read_doc's pagination bounds are visible up front' line gives a clear implied workflow: call list_doc before deciding pagination. However, it never says when to prefer this over list_categories or search_doc, nor when not to use it, leaving some routing to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
read_docRead DocA
Read specific chunks of one document.
Raises: ValueError: Too many chunk_numbers requested, no document matches, or file_name is ambiguous within category/subcategory.
| Name | Required | Description | Default |
|---|---|---|---|
| category | Yes | Document's category | |
| file_name | Yes | Document's extension-stripped filename, as returned by list_doc/search_doc | |
| subcategory | Yes | Document's subcategory, or null if it has none | |
| chunk_numbers | Yes | Which chunk numbers to return - capped at max_chunks_per_read per call (see config.yaml) |
Output Schema
| Name | Required | Description |
|---|---|---|
| chunks | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden of behavioral disclosure. It usefully enumerates ValueError conditions, but it does not mention rate limits, permissions, side effects, or confirmation that reading is non-destructive beyond the verb 'Read.'
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact, front-loaded with the core purpose, and includes a concise error section. Every sentence contributes useful information with no redundancy or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read tool with a complete input schema and an output schema, the description covers the essential behavior and failure modes. It could be more explicit about the prerequisite of obtaining file_name from list_doc/search_doc, though the schema partially communicates this.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the schema already documents all four parameters well. The description adds little beyond the error condition involving chunk_numbers, which is a minor enhancement over the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb and resource: 'Read specific chunks of one document.' It does not explicitly differentiate from siblings like search_doc or list_doc, but the purpose is unambiguous and the tool name reinforces it.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The opening sentence clearly describes when to use the tool: when you need specific chunks of a single document. It does not explicitly name alternatives or exclusions, but the context is clear enough that an agent can select it without confusion.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_docSearch DocA
Full-text keyword search over indexed document chunks.
Matching is case-insensitive and word-based: punctuation splits words, so MP-BGP is indexed as the two words "mp" and "bgp". Unquoted, a '-' is query syntax and fails, so write "MP-BGP" in double quotes (a phrase). Space-separated terms are implicitly ANDed; there are no synonyms, so widen a search with OR ('L3Out OR "external routing"').
Each result carries a short snippet around the hits and a score; use read_doc with the result's chunk_number for the full chunk text.
Returns:
Up to max_search_results matching chunks (see config.yaml), best
match first, plus next_offset when more matches exist.
Raises: ValueError: pattern is not valid FTS5 query syntax.
| Name | Required | Description | Default |
|---|---|---|---|
| offset | No | Skip this many best matches, for paging | |
| pattern | Yes | SQLite FTS5 MATCH query. Examples: 'BGP AND OSPF', '"MP-BGP"', 'L3Out OR "external routing"', 'NEAR(bgp ospf, 10)', 'config*'. Quote any term containing punctuation such as '-'. | |
| category | No | Only search this category, or null for all | |
| file_name | No | Only search the document with this extension-stripped filename, or null for all | |
| subcategory | No | Only search this subcategory, including those nested below it ('cisco' also matches 'cisco/aci'), or null for all |
Output Schema
| Name | Required | Description |
|---|---|---|
| results | No | |
| next_offset | No | Pass as offset to get the next page, or null when there are no more matches |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries full behavioral burden and succeeds: it discloses case-insensitivity, word-based tokenization, quote requirements for punctuation, implicit AND, absence of synonyms, result ordering, max result cap, next_offset paging, and ValueError on invalid FTS5 syntax.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is structured with a summary, behavioral details, returns, and raises. Every sentence earns its place, and the length is justified by the complexity of the FTS5 query language.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers query syntax, result contents, paging, error handling, and how to retrieve full chunks. With an output schema present and no annotations to worry about, nothing an agent needs to invoke the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. The description goes beyond the schema by explaining FTS5 query semantics, OR/AND usage, quoting pitfalls, and paging behavior, which meaningfully helps an agent form valid pattern values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Opens with 'Full-text keyword search over indexed document chunks' – a specific verb, resource, and clear scope. This distinguishes it from siblings list_doc, list_categories, and read_doc, and it even names read_doc as the follow-up for full chunk text.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides rich guidance on query formation and explicitly instructs using read_doc with chunk_number for full text. It doesn't spell out when to prefer search_doc over list_doc, but the search/list/read roles are clear from the first sentence and tool names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.10.0- First observed
list_categories - First observed
list_doc - First observed
read_doc - First observed
search_doc
TDQS
Scored across 4 tools
search_doc and read_doc are clearly distinct (search vs. read), and list_doc vs. list_categories are separated by whether file names are included. One minor overlap exists between the two listing tools, but the descriptions make the boundary clear.
Three tools follow the verb_doc pattern (search_doc, list_doc, read_doc), while list_categories breaks the literal pattern but still uses a consistent verb_noun style. Naming is predictable overall with only a minor deviation.
Four tools is well-scoped for a documentation retrieval server. Each tool serves a distinct purpose—search, browse structure, list categories, and read chunks—without unnecessary bloat.
The set covers the core documentation workflows: searching, navigating the hierarchy, and reading chunked content. Minor gaps exist, such as no one-shot full-document retrieval or explicit metadata endpoint, but the typical use cases are supported.
Maintenance
Related MCP Connectors
Political Comms documentation MCP server: search docs, query the docs filesystem. No auth.
Read-only MCP server for the OrchestKit docs: full-text search + Markdown fetch. No auth.
- docs2mcpOAuthcom.docs2mcp
Query your own PDFs and documents from any MCP client. Every answer cites the page it came from.
Team docs served to AI agents over MCP - search, Markdown reads, version pinning, read audit.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceTransforms PDF collections into a searchable knowledge base using TF-IDF indexing and proximity matching. It enables users to search documents, retrieve specific page content, and manage document libraries through natural language via MCP clients.5-
- AlicenseNot gradedqualityDmaintenanceProvides semantic search over markdown documentation using RAG, allowing natural language queries and integration with MCP clients.1MIT
- FlicenseAqualityDmaintenanceEnables searching documentation from GitHub repositories and web pages via MCP tools, with in-memory indexing and caching for fast retrieval.3-
- AlicenseNot gradedqualityAmaintenanceEnables searching, reading, and navigating MkDocs documentation sites through MCP tools for keyword, semantic, or hybrid search, document browsing, and project metadata.1BSD 2-Clause "Simplified"