Skip to main content
Glama

docs-mcp

An MCP server that lets AI agents search and read your documentation at query time, instead of relying on stale training data. Point it at a folder of Markdown and it exposes search_docs, get_doc and list_docs over stdio (for Claude Code, Cursor, Claude Desktop) and over Streamable HTTP (for a hosted, public endpoint like OpenAI's Docs MCP or the Microsoft Learn MCP Server).

Published as @apideck/docs-mcp. It runs as a standalone CLI, a Vercel function, or as a library inside an existing Node or Next.js site. The docs/ folder in this repo is both the sample content and the server's own documentation. Start there: docs/index.md.

Quick start

pnpm install
pnpm audit -- --docs ./docs          # check the docs are complete, current, structured
pnpm search -- "vercel" --docs ./docs # try the index from the terminal
pnpm start -- --docs ./docs           # MCP over stdio
pnpm serve -- --docs ./docs --port 3000   # MCP over HTTP at http://localhost:3000/mcp

Build once (pnpm build) and the docs-mcp binary in dist/bin/ runs the same commands without tsx.

Related MCP server: search-docs

Connect Claude Code

claude mcp add my-docs -- docs-mcp start --docs /path/to/docs --base-url https://docs.example.com

Or commit a .mcp.json next to the docs:

{
  "mcpServers": {
    "my-docs": {
      "command": "docs-mcp",
      "args": ["start", "--docs", "./docs", "--base-url", "https://docs.example.com", "--about", "the Example API reference"]
    }
  }
}

Commands

Command

What it does

docs-mcp start

MCP over stdio. Re-indexes on file changes (--watch is on by default).

docs-mcp serve --port 3000

MCP over Streamable HTTP, same handler as the Vercel function.

docs-mcp audit

Reports broken links, thin or empty pages, stale pages, missing titles/descriptions, duplicate titles, heading skips and over-long sections. Exit 1 on errors.

docs-mcp search "query"

Runs a search against the index from the terminal.

Shared flags: --docs, --base-url, --about, --name. Each falls back to DOCS_DIR, DOCS_BASE_URL, DOCS_ABOUT, DOCS_NAME.

Tools

  • search_docs(query, limit?, path_prefix?): heading-level full-text search with title and heading boosts, prefix and fuzzy matching, and at most three hits per page.

  • get_doc(path, section?): full page markdown with a header and section outline, or one section and its sub-sections.

  • list_docs(path_prefix?, limit?): pages with title, description, word count and last-modified date.

Every page is also an MCP resource at docs://<path>. Full reference: docs/tools.md.

Hosting on Vercel

api/mcp.ts is a stateless Streamable HTTP function; vercel.json rewrites /mcp to it and bundles docs/** with the function. Set DOCS_BASE_URL and DOCS_ABOUT in the project environment and deploy. Details in docs/hosting.md.

Use as a library

Mount the handler inside a site that already builds its docs, so the endpoint lives next to them. A Next.js pages-router API route:

// src/pages/api/mcp.ts
import { createHttpHandler, DocStore } from '@apideck/docs-mcp'
import type { NextApiRequest, NextApiResponse } from 'next'
import path from 'path'

const store = new DocStore({ root: path.join(process.cwd(), 'public', 'md'), baseUrl: 'https://docs.example.com' })
const handler = createHttpHandler({ store, name: 'example-docs', about: 'the Example API documentation' })

export const config = { maxDuration: 60, api: { responseLimit: false } }
export default (req: NextApiRequest, res: NextApiResponse) => handler(req, res)

Add experimental.outputFileTracingIncludes: { '/api/mcp': ['./public/md/**/*'] } to next.config so the markdown ships with the function on Vercel. DocStore also takes a metadata(path) hook to supply titles, descriptions and canonical URLs from a build manifest. Exports: DocStore, createServer, createHttpHandler, createDocTools, auditDocs, formatAuditReport.

Development

pnpm typecheck
pnpm lint
pnpm test        # node:test via tsx, covers parsing, indexing, audit, MCP over in-memory and HTTP transports
pnpm build

Layout mirrors @apideck/mcp: src/ for the library, bin/ for the stricli CLI, api/ for the Vercel function, tests co-located as *.test.ts.

How it works

  1. Every .md/.mdx/.markdown file under the docs root is read, frontmatter parsed, and the body split on ATX headings (code fences respected).

  2. Each section becomes a document in a MiniSearch index with title, heading, content and path fields.

  3. Queries run with all terms required first, falling back to any term, so a typo does not return nothing.

  4. In start and serve, a recursive file watcher rebuilds the index 300 ms after the last change. On Vercel the index is built once per function instance and refreshed by each deploy.

License

MIT

Available Tools

3 tools
get_docGet documentation pageA
Read-onlyIdempotent

Return the full markdown of a documentation page by path, or a single section of it. Use search_docs or list_docs to find paths.

ParametersJSON Schema
NameRequiredDescriptionDefault
pathYesPage path from search_docs or list_docs, e.g. "guides/getting-started". Extensions and "docs://" prefix are accepted.
sectionNoReturn only this section: an anchor ("#install" or "install") or the heading text.

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint, and openWorldHint=false, covering the safety profile. The description adds the return format (full markdown) and the section option, which is genuine added context, but it says nothing about behavior on nonexistent paths, anchoring misses, or pagination/size limits. Adequate but not rich.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste. The return-shape statement is front-loaded and the routing hint follows immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, so the description carries the return-value burden and does so by naming the markdown format and the section-subset option. Combined with the rich annotations and 100% schema coverage, an agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both 'path' (with its docs:// prefix and extension acceptance) and 'section' (anchor or heading text) are already fully documented in the schema. The description only restates that a path and optionally a single section are accepted, adding no syntax beyond the schema. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (Return full markdown) and resource (documentation page by path), plus the single-section variant. The mention of paths subtly separates it from the sibling tools, which are for discovery rather than retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly routes the agent: 'Use search_docs or list_docs to find paths.' This names both alternatives and the condition under which they are needed, so an agent knows to call this tool only once it already has a path.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_docsList documentation pagesA
Read-onlyIdempotent

List documentation pages with their path, title, description and last-modified date. Useful to browse the structure before searching or to find pages under a prefix.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of pages to list.
path_prefixNoOnly list pages under this path prefix.

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and a closed world, so the safety profile is covered structurally. The description adds the return-field list and the prefix-scoping notion, which is useful, but says nothing about result size, ordering, or what happens at the default limit of 200.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences, zero filler: the first delivers the returned fields, the second delivers the use cases. Front-loaded with the most decision-relevant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by naming the returned fields, and annotations cover the safety profile for a simple two-param read tool. The only real gap is pagination/truncation behavior around the limit parameter, which stays unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so both limit and path_prefix are already documented in the schema. The description only gestures at the prefix behavior already captured by the path_prefix description, adding no syntax, matching rules, or limit/total-count semantics. Baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (list) and resource (documentation pages) and enumerates the returned fields (path, title, description, last-modified date), which tells the agent exactly what this returns. It implicitly distinguishes itself from siblings by framing itself as a browsing tool used 'before searching', but never names get_doc and search_docs directly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives clear context: use it to browse structure before searching, or to find pages under a prefix. It references the searching alternative, so the agent knows when to prefer search_docs. It lacks explicit when-not conditions (e.g. don't use when you already know the exact page).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_docsSearch documentationA
Read-onlyIdempotent

Full-text search over the documentation. Returns matching sections with a snippet, the page path and heading anchor. Call get_doc with a returned path to read the full page or a single section.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum number of results.
queryYesFree-text query. Prefix matching and light fuzzy matching are applied per term.
path_prefixNoOnly search pages whose path starts with this prefix, e.g. "guides" or "api/reference".

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and a closed world, so safety is covered. The description adds genuinely additive context by disclosing the return shape (matching sections with a snippet, page path and heading anchor), which matters because no output schema exists. It stops short of noting result limits or ranking behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with what the tool does, followed by the return shape and the next-step handoff. No wasted clauses.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description correctly compensates by summarizing the returned fields and the path/anchor needed to chain into get_doc. Combined with 100% parameter coverage and clear annotations, nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

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 query (with prefix/fuzzy matching), limit, and path_prefix. The description adds no parameter-level syntax or format detail beyond what the schema provides, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('full-text search over the documentation') and names the sibling get_doc that handles the follow-up read. An agent can distinguish this retrieval tool from get_doc (full page read) and list_docs without inspecting any schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives a clear workflow condition: call get_doc with a returned path to read the full page or a single section, which frames search as the discovery step. It does not explicitly contrast with list_docs, so the alternative-selection guidance is present but incomplete.

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.

  1. 3 tool updatesv0.1.0
    • First observedget_doc
    • First observedlist_docs
    • First observedsearch_docs

TDQS

A4.1/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a clearly distinct operation: list_docs for browsing structure, search_docs for full-text queries, and get_doc for retrieving content by path. The descriptions explicitly cross-reference each other, reinforcing the intended workflow.

Naming Consistency5/5

All three tools follow the same noun-prefixed pattern with a consistent verb (get_doc, list_docs, search_docs), using uniform snake_case throughout. No deviations or mixing of conventions.

Tool Count4/5

Three tools cover the core read-only documentation workflow (browse, search, fetch) without redundancy. Slightly lean, but each tool earns its place and the scope is well-defined.

Completeness4/5

The browse/search/retrieve lifecycle is fully covered for consuming docs, with get_doc supporting both whole-page and section retrieval. Writing or indexing operations are absent, but may be intentionally out of scope for a read-oriented server.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    C
    maintenance
    Enables AI assistants to navigate and query hierarchical documentation structures, supporting markdown files with YAML metadata and OpenAPI 3.x specifications. It features intelligent full-text search, metadata filtering, and a built-in web interface for both human and AI-driven documentation access.
    6
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Enables AI agents to search local Markdown documents using natural language, with automatic indexing and section-level retrieval.
    10
    2 npm
    1
    MIT
  • A
    license
    A
    quality
    A
    maintenance
    Indexes your project's markdown documentation and exposes it to AI agents via local hybrid search (lexical + semantic) with progressive disclosure tools.
    3
    471 npm
    5
    MIT