Skip to main content
Glama

manual-rag-mcp

Feed any manual / book / text into your RAG, then use it as an MCP server so your AI can retrieve information from it.

An MCP server that exposes retrieval-augmented search over an arbitrary set of reference manuals. Ingestion turns a PDF into text chunks and embeds them locally with Ollama (nomic-embed-text); search runs a brute-force cosine similarity over those embeddings — no cloud, no API keys, fully local. Any number of sources can be added, each with an arbitrary name, and existing embedding stores from other RAG projects can be imported without re-embedding.

Any manual works — the indexed sources are discovered at runtime via get_sources.

How it works

PDF ──pdftotext -layout──▶ text ──chunk (1200 chars / 150 overlap)──▶ chunks
     └─ chapter/page detection from headings                      │
                                                                  ▼
                              data/embeddings.json ◀── Ollama nomic-embed-text
                                        ▲                         │
                    existing embeddings │ (npm run import)        │
                                        └─────────────────────────┤
                          query ──embed──▶ cosine similarity ──▶ top-k excerpts

File

Role

src/index.ts

MCP stdio server — exposes search_manual, get_sources

src/embeddings.ts

Ollama client (OLLAMA_HOST, EMBEDDING_MODEL overridable via env)

src/store.ts

Data layer: paths, read/append/remove chunks, source metadata

src/vectorstore.ts

Loads the store, cosine similarity search, source stats, dimension guard

src/tools/search.ts

Tool-level result shaping

src/ingest.ts

PDF → text → chunks → embeddings (the ingest CLI)

src/import.ts

Import an existing embeddings JSON from any RAG project (no re-embedding)

Related MCP server: PDF RAG MCP Server

Requirements

  • Node.js ≥ 20

  • Ollama running locally with the embedding model:

    ollama pull nomic-embed-text
    brew services start ollama
  • pdftotext (from poppler) — brew install poppler

Install

git clone git@github.com:konraddiesch/manual-rag-mcp.git ~/Code/manual-rag-mcp
cd ~/Code/manual-rag-mcp
npm install
npm run build

build/ is committed, so a clone is runnable without building — but run npm run build after any change under src/.

Add a manual from a PDF

npm run ingest -- --pdf /path/to/manual.pdf --source my-manual

Flag

Description

--pdf <path>

Path to the PDF (required)

--source <name>

Arbitrary source id used for filtering and get_sources (required)

--chunk-size N

Characters per chunk (default 1200)

--overlap N

Overlap between chunks (default 150)

--replace

Re-ingest an existing source (required if the id already exists)

Embeddings are appended to data/embeddings.json; per-source metadata lands in data/sources/<source>/metadata.json.

Import an existing embeddings store

Already have a RAG store elsewhere? Bring its vectors in without re-embedding:

npm run import -- --from /path/to/other-rag/embeddings.json --source my-manual [--replace]

The file must be a JSON array of chunks; each entry needs content and embedding, with optional id, page and chapter (also read from a nested metadata object). Chunk ids are prefixed with the source name.

⚠️ All sources in one store must share the same embedding model as the query, otherwise dimensions won't match and mismatching chunks are skipped at search (with a warning). Set EMBEDDING_MODEL if the imported data uses a different model than nomic-embed-text.

Register the MCP server

The repo root .mcp.json already registers the server for Claude Desktop / IDE clients:

{
  "mcpServers": {
    "manual-rag": {
      "type": "stdio",
      "command": "node",
      "args": ["${HOME}/Code/manual-rag-mcp/build/index.js"]
    }
  }
}

For opencode, add to ~/.config/opencode/opencode.jsonc:

"manual-rag": {
  "type": "local",
  "command": ["node", "{env:HOME}/Code/manual-rag-mcp/build/index.js"],
  "enabled": true
}

Tools

Tool

Purpose

get_sources

List indexed manuals with chunk counts, page ranges, detected chapters

search_manual

Semantic search — query, optional source filter, maxResults (1–20, default 5)

Returns excerpts with page number, chapter, source and relevance score. An unknown source returns a helpful error listing the indexed sources.

Data is not committed

data/ (embeddings, extracted text and per-source metadata — ~129 MB) and node_modules/ are gitignored. Re-create the data layer with npm run ingest or npm run import. Override the location with an absolute DATA_DIR.

Usage guide

See SKILL.md — a precise playbook for using the MCP server well (call get_sources first, when to filter by source, how to cite, troubleshooting). The same skill is installed globally at ~/.config/opencode/skills/manual-rag/SKILL.md.

License

MIT

Available Tools

2 tools
get_sourcesA

Get a list of all indexed reference manuals with their chunk counts, page ranges, and detected chapters.

Use this tool when the user wants to:

  • Know which manuals are available to search

  • See what topics are covered in each manual

  • Find out the structure of available documentation

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A3.8/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. It implies a read-only listing and names the returned data, but says nothing about permissions, pagination, or size limits for large manual sets.

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 core action, followed by a compact bulleted usage list. Slightly verbose in the 'Use this tool when the user wants to:' framing, but no sentence is wasted.

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?

For a no-parameter, read-only discovery tool with no output schema, the description adequately covers what the agent gets back (manuals plus chunk counts, page ranges, chapters). Only the fetch mechanics remain unspecified.

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. There is nothing for the description to disambiguate and it does not need to.

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 description states a specific verb ('Get a list') and resource ('indexed reference manuals') and even enumerates the returned fields (chunk counts, page ranges, detected chapters). It is clearly distinct from a search operation, but it never names the sibling search_manual to make the boundary explicit.

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?

Three explicit 'when to use' scenarios are given (discovering available manuals, seeing covered topics, understanding documentation structure). This is clear positive guidance, though it offers no exclusions or a direct pointer to search_manual for the actual querying task.

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

search_manualA

Search the indexed reference manuals for information.

Call get_sources first to learn which manuals are indexed and what each covers. Then search a manual whenever the user asks about a feature, workflow, keyboard shortcut, setting, or concept covered by one of those manuals — this is the authoritative source, prefer it over guessing or a web search.

Pass the optional "source" parameter to restrict results to a single manual (use the exact source id returned by get_sources):

  • source="" — search only that manual

  • Omit "source" to search across all manuals simultaneously

The tool returns relevant excerpts with page numbers, chapter information, source identification, and a relevance score.

ParametersJSON Schema
NameRequiredDescriptionDefault
queryYesThe search query
sourceNoOptional source filter — must match a source id returned by get_sources (e.g. "ableton", "resolve"). Omit to search all sources.
maxResultsNoMaximum number of results to return (1-20, default 5)

TDQS

A4.6/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 load, and it does most of it: it discloses the return shape (excerpts with page numbers, chapter info, source id, relevance score) and the scoping semantics of the source filter. It does not state limits such as result-count behavior or what happens on a non-matching source id, which keeps it short of a 5.

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 core action, then workflow, then the source-filter mechanics, then return format — a sensible order with no filler sentences. The bulleted source options are slightly verbose relative to the schema text they echo, which keeps it off a 5.

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, and the description compensates by describing the return contents and relevance scoring, plus the prerequisite get_sources call. An agent has everything needed to invoke and interpret the result correctly.

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 coverage is 100%, so the baseline is 3, but the description adds operational meaning: the source value must be the exact id returned by get_sources, with concrete examples, and omitting it fans the search out across all manuals. That is more than a restatement of the schema's own text.

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 ('Search the indexed reference manuals') and immediately differentiates itself from the sibling get_sources by assigning that tool the discovery role and this one the retrieval role. An agent can distinguish the two without opening either schema.

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?

Gives explicit ordering ('Call get_sources first'), the trigger conditions ('whenever the user asks about a feature, workflow, keyboard shortcut, setting, or concept'), and an exclusion ('prefer it over guessing or a web search'). Nothing about when to reach for this tool is left to inference.

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. 2 tool updatesv1.0.0
    • First observedget_sources
    • First observedsearch_manual

TDQS

A4.1/5.0

Scored across 2 tools

Disambiguation5/5

search_manual and get_sources have clearly distinct purposes: one retrieves content from manuals, the other lists available sources and their structure. There is no overlap or ambiguity between them.

Naming Consistency5/5

Both tools follow a consistent snake_case verb_noun pattern (search_manual, get_sources). The naming is predictable and readable.

Tool Count3/5

Only 2 tools are provided, which is on the thin side for a RAG server. While both are essential and well-scoped, the count is borderline minimal.

Completeness4/5

The core workflow of listing sources and searching across or within manuals is covered. However, there is no direct way to retrieve full documents or specific pages beyond search excerpts, which is a minor gap.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI assistants to search and query PDF documents through a local RAG system with vector embeddings. Provides semantic document search capabilities while keeping all data stored locally without external dependencies.
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables intelligent search and question-answering over PDF documents using semantic similarity and keyword search. Supports OCR for scanned PDFs, persistent vector storage with ChromaDB, and maintains source tracking with page numbers.
    6
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Provides semantic search and management of shared documentation using ChromaDB and OpenAI embeddings. It enables users to query local documents by meaning, list files, and read content through natural language tools.
    -