Skip to main content
Glama

fathom-mcp

Documentation RAG system: crawl a docs site → chunk + embed locally (HuggingFace) → store in Postgres+pgvector → semantic search via MCP server, REST API, and web UI.

Demo

live at https://fathom-mcp.veermehta.dev

Related MCP server: MCPDocSearch

Architecture

flowchart LR
    A[Browser] --> B[API Server]
    B --> D[Web UI]
    B --> C[(Postgres + pgvector)]
    B --> G[Ingestion Pipeline]
    G --> H[Scraper Subprocess]
    G --> C
    I[AI Client<br/>Claude Code, OpenCode] -->|MCP over stdio| F[MCP Server]
    F --> C

Quick start

git clone ... fathom-mcp && cd fathom-mcp
python -m venv .venv && source .venv/bin/activate
pip install -e ".[local]"
docker compose up -d
cp .env.example .env              # set LLM_API_KEY
.venv/bin/docs-mcp-api            # http://127.0.0.1:8000

npm (no clone needed)

npx @fathom-mcp/server            # first run installs ~5GB deps, then instant
npx @fathom-mcp/server --api      # REST API + web UI

MCP tools

add_documentation · search_documentation · list_sources · get_ingest_status · add_local_docs

REST API

Endpoint

What

GET /search?q=...

Semantic search

GET /sources

Indexed sources

POST /upload

Upload files

POST /upload-folder

Index a local folder

GET /llm-chat?q=...

Chat with docs

GET /about

System info

OpenCode

Add to ~/.config/opencode/opencode.jsonc:

{
  "mcp": {
    "fathom-mcp": {
      "type": "local",
      "command": ["/path/to/fathom-mcp/.venv/bin/python", "-m", "docs_mcp.server"]
    }
  }
}

Replace /path/to/fathom-mcp with your actual clone path. You can verify it works with:

echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | /path/to/fathom-mcp/.venv/bin/python -m docs_mcp.server

Config

~/.fathom-mcp/.env — set EMBEDDING_PROVIDER=api + EMBEDDING_API_KEY for remote embeddings (Jina, OpenAI, etc.), or leave as local for HuggingFace.

Available Tools

5 tools
add_documentationA

Crawl a framework/library documentation site and index it for semantic search.

Re-ingesting an existing source is incremental: pages whose extracted markdown is unchanged are skipped (no re-embedding).

Args: name: Short identifier for the framework, e.g. "react". version: Version string, e.g. "18.3" or "latest". base_url: Entry point URL of the documentation site. max_depth: How many link hops to follow from base_url. max_pages: Hard cap on the number of pages crawled. background: If true, start the crawl and return a job id immediately; track it with get_ingest_status. Large sites should use this to avoid tool timeouts. prune_missing: If true, delete indexed pages that this crawl did not visit. Only enable when depth/page caps cover the whole site, otherwise capped crawls would delete valid pages. lang: ISO 639-1 language code to filter pages (e.g. "en"). Only pages matching this language are crawled. sitemap: If true, discover pages from sitemap.xml instead of following links. Gives better coverage for docs sites that expose a sitemap.

ParametersJSON Schema
NameRequiredDescriptionDefault
langNo
nameYes
sitemapNo
versionYes
base_urlYes
max_depthNo
max_pagesNo
backgroundNo
prune_missingNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior5/5

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

No annotations are provided, so the description carries the full burden and does so well. It discloses incremental re-ingestion behavior (skipping unchanged pages), the destructive risk of prune_missing with a condition to avoid data loss, the asynchronous nature of background mode, and that a job id is returned for tracking.

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

Conciseness4/5

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

The description is well-structured with a brief overview followed by an Args list. It is appropriately sized for 9 parameters, though the overview could be slightly more front-loaded with the core action before the incremental note, but it remains clear and not verbose.

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?

Given the tool's complexity (9 parameters, no annotations, existing output schema), the description is complete. It covers purpose, parameter semantics, behavioral traits like incremental updates and async background jobs, and risk warnings for prune_missing, leaving no critical gaps for correct invocation.

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

Parameters5/5

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

Schema description coverage is 0%, meaning the schema provides no parameter descriptions, so the description must compensate and does. It defines each of the 9 parameters with examples, defaults, and effects (e.g., max_depth as link hops, background as starting an async job, prune_missing as deleting indexed pages not visited).

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?

The description states a specific verb and resource: 'Crawl a framework/library documentation site and index it for semantic search.' This clearly distinguishes it from sibling tools like add_local_docs (local files) and search_documentation (queries the index), and it names the outcome (semantic search index).

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?

It explains when to use background mode for large sites to avoid timeouts, and warns to only enable prune_missing when depth/page caps cover the whole site. However, it does not explicitly contrast with add_local_docs or search_documentation, leaving sibling selection to inference.

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

add_local_docsA

Index local documentation files from a folder on disk.

Walks the folder, finds supported files (HTML, Markdown, PDF, TXT), extracts text, chunks, embeds, and stores them for semantic search.

Args: name: Short identifier for this collection, e.g. "internal-api". path: Absolute or relative path to the folder on the server. recursive: If true, descend into subdirectories (default true).

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
pathYes
recursiveNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior3/5

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

With no annotations, the description carries the full burden and does disclose the internal pipeline (walk, extract, chunk, embed, store) and supported formats, which is real value. It omits key behavioral facts: whether re-indexing the same name overwrites or duplicates, whether the call is synchronous or queues a job (the get_ingest_status sibling strongly implies asynchronous), and any permission requirements.

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

Conciseness4/5

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

Front-loaded with the purpose, then the pipeline, then an Args block; no filler sentences. It slightly duplicates the schema's 'default true' for recursive, but that is minor.

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?

An output schema exists, so return values need no explanation, and the description covers purpose, mechanics, formats and all three parameters. The remaining hole is operational context: async/job semantics tied to get_ingest_status and re-index behavior, which an agent about to invoke this tool would benefit from.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate and largely does: it explains name as a short identifier with an example, path as absolute or relative on the server, and recursive's descent behavior and default. The only gap is that it doesn't state the uniqueness/overwrite semantics of 'name'.

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?

The first sentence gives a specific verb ('Index') and resource ('local documentation files from a folder on disk'), and the pipeline sentence clarifies what indexing entails. The word 'local' implicitly separates it from add_documentation, but no sibling is named, so the differentiation is inferred rather than stated.

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

Usage Guidelines3/5

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

Usage is implied by 'local ... on disk' and the supported file list, which tells the agent this is for already-present files rather than fetched sources. However, there is no explicit when-to-use versus add_documentation or search_documentation, and no mention that get_ingest_status is the follow-up for tracking the job.

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

get_ingest_statusA

Check progress of a background add_documentation job.

Args: job_id: The id returned when the job was submitted with background=true.

ParametersJSON Schema
NameRequiredDescriptionDefault
job_idYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses that this observes a background job and that the id originates from a background submission, which is useful. It does not state whether the call is non-mutating, whether repeated polling is expected/safe, or what happens after the job completes (retention of status), leaving gaps for a no-annotation tool.

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

Conciseness4/5

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

One front-loaded sentence plus a short Args block; nothing is padded. The 'Args:' formatting is slightly noisy for a single parameter but costs almost nothing.

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?

An output schema exists, so return values need not be explained, and the description covers purpose and the single parameter's origin. Minor omissions remain around polling behavior and lifecycle after completion, but for a one-parameter status tool this is close to sufficient.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate — and it does, explaining that job_id is 'the id returned when the job was submitted with background=true.' That adds real meaning (provenance of the id) beyond the bare 'Job Id' title in the schema.

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+resource ('Check progress of a background add_documentation job') and ties itself to the sibling add_documentation by referencing its background=true submission path. That linkage distinguishes it from search_documentation, list_sources, and add_local_docs reasonably well, though it never explicitly names the alternative a caller might confuse it with.

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 for when it applies: only after a job was submitted with background=true. There is no explicit when-not guidance (e.g. what to do for synchronous ingest), but the trigger condition is unambiguous.

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

list_sourcesA

List all indexed documentation sources with page and chunk counts.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It discloses that output includes page and chunk counts (a read-only inventory), which is useful, but doesn't state permissions, pagination, or behavior on an empty index.

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?

A single front-loaded sentence with no waste. The verb and resource lead immediately.

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?

An output schema exists, so return-value detail need not be in the description. For a simple zero-param list tool, the description is nearly complete, only missing minor routing context versus siblings.

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

Parameters4/5

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

The tool takes zero parameters, so the baseline is 4. The description mentions page/chunk counts, but that describes the return payload rather than adding parameter meaning.

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 (indexed documentation sources) with the added scope of what each entry contains (page and chunk counts). It is distinguishable from siblings like add_documentation and search_documentation, though it doesn't explicitly name them.

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

Usage Guidelines3/5

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

No explicit when-to-use or when-not-to-use guidance is given. Usage is implied by the verb 'List' against the documentation-indexing siblings, which is adequate but leaves the agent to infer the routing.

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

search_documentationA

Semantic search over indexed documentation.

Returns the most relevant markdown chunks with their source URL and heading path. Use add_documentation first if nothing is indexed yet.

Args: query: What to look for, e.g. "how to define a loader". name: Optional framework name filter, e.g. "react". version: Optional version filter, e.g. "18.3". k: Number of chunks to return (1-20). mode: "hybrid" (default) fuses vector + keyword ranking; "vector" or "keyword" force a single strategy.

ParametersJSON Schema
NameRequiredDescriptionDefault
kNo
modeNohybrid
nameNo
queryYes
versionNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

No annotations are provided, so the description carries the full behavioral burden. It discloses what is returned (markdown chunks with metadata) and the prerequisite ingest step. It doesn't specify read-only nature or rate/latency behavior, but for a search 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.

Conciseness4/5

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

Front-loads the core operation and return value, then documents parameters cleanly. The Args section is well-structured and every line earns its place; slightly verbose but effectively so for a 0%-coverage schema.

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?

An output schema exists so return-value explanation is not strictly required, yet the description still summarizes the chunk format. Combined with full parameter documentation and the ingest prerequisite, an agent has everything needed to invoke this correctly.

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

Parameters5/5

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

Schema description coverage is 0%, so this description must fully compensate. It documents all five parameters with meaning and examples: query (with sample), name/version filters, k range (1-20), and the mode enum semantics including the default's fusion behavior. This is exactly what's needed.

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 (semantic search over indexed documentation) and describes the return unit (markdown chunks with source URL and heading path). This clearly distinguishes it from siblings like add_documentation and list_sources.

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?

Explicitly names the precondition: 'Use add_documentation first if nothing is indexed yet,' which routes the agent to the right sibling. It provides clear context but doesn't cover the other alternatives (add_local_docs, get_ingest_status) or when-not-to-use scenarios.

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. 5 tool updatesv0.1.0
    • First observedadd_documentation
    • First observedadd_local_docs
    • First observedget_ingest_status
    • First observedlist_sources
    • First observedsearch_documentation

TDQS

A4.2/5.0

Scored across 5 tools

Disambiguation5/5

Each tool targets a distinct operation: web ingestion (add_documentation), local ingestion (add_local_docs), job tracking (get_ingest_status), search (search_documentation), and enumeration (list_sources). The two ingest tools could superficially be confused, but their descriptions clearly separate web-crawl vs local-folder scopes.

Naming Consistency5/5

All tools use consistent snake_case verb_noun naming: add_documentation, add_local_docs, get_ingest_status, search_documentation, list_sources. The verb set (add/get/search/list) is predictable and readable throughout.

Tool Count5/5

Five tools is well-scoped for a documentation indexing/search server, covering ingestion, async job tracking, retrieval, and listing. No tool feels redundant or gratuitous.

Completeness4/5

The surface covers ingest (web + local), status, search, and list, which handles the core RAG lifecycle. However, there is no tool to delete or remove an indexed source, and no way to inspect job history or cancel a running job, leaving minor gaps.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers