Skip to main content
Glama
samishekhalard

rag-mcp

rag-mcp

An MCP server that gives a language model tools for searching a document index — built against rag-service.

pip install -r requirements.txt
RAG_MCP_SERVICE_URL=http://localhost:8000 python -m rag_mcp.server

What it does

The Model Context Protocol is how a model gets tools it can call. This server speaks MCP over stdio and exposes five:

Tool

What it returns

Cost

rag_search

Ranked passages with document ids, scores and chunk ids

retrieval only

rag_read_around

One chunk in full plus its neighbours, by id

none

rag_read_document

An entire indexed document, in order

none

rag_index_stats

Chunk count, models, reranker, tracing state

none

rag_answer

A generated answer with sources, per-stage latency and USD cost

calls an LLM

The tools are designed to chain: rag_search returns chunk ids, and rag_read_around takes one and reads around it. The integration test drives exactly that chain against a live service, so the promise in the tool descriptions is checked rather than asserted.

Related MCP server: NOEMA-AI MCP Server

Connecting it to Claude Code

{
  "mcpServers": {
    "rag": {
      "command": "python",
      "args": ["-m", "rag_mcp.server"],
      "env": {
        "PYTHONPATH": "/absolute/path/to/rag-mcp/src",
        "RAG_MCP_SERVICE_URL": "http://localhost:8000"
      }
    }
  }
}

Start rag-service first (docker compose up in that repo), then restart Claude Code. The tools appear as rag_search, rag_answer and so on.

Variable

Default

Meaning

RAG_MCP_SERVICE_URL

http://localhost:8000

Where the RAG service listens

RAG_MCP_TIMEOUT

30

Seconds before a request gives up

Three decisions worth explaining

The tool description is the API. A model picks a tool from its description alone — it never sees the implementation. rag_search and rag_answer overlap, so each description says when the other one is the better choice, and both state what they cost. Tool descriptions here are written as carefully as the code, because they are the part that determines whether the tools get used correctly.

Errors are instructions, not tracebacks. If the service is down, the tool returns "Cannot reach the RAG service at … Start it with docker compose up". A model can act on that; it cannot act on a ConnectionRefusedError. Every failure path is tested for the message it produces.

It talks HTTP, not Python. The server calls the RAG service over its public API instead of importing it. The two deploy independently, and this repo tests against a contract rather than someone else's internals.

This repo changed the other one

rag_read_around originally searched for the chunk id as a query string and filtered the results. That cannot work — a chunk id appears in neither the lexical nor the dense index — so it was a lookup that would quietly return nothing. The fix belonged in the service, which gained real endpoints:

GET /chunks/{chunk_id}?context=N
GET /documents/{doc_id}

Then the integration test, running the real service rather than a mock, failed on rag_answer: asked for the overpressure limit, it returned the dry-run paragraph. Two defects in the service's offline reader, both fixed there: sentences were scored on raw token overlap, so stopwords decided the answer; and the two best-scoring sentences were returned, when technical prose states the subject in one sentence and the value in the next.

Both bugs were invisible to this repo's mocked tests, which is the argument for having an integration test at all.

Tests

pytest

26 tests. 21 run against a mock HTTP transport and need nothing installed; 5 are integration tests that start a real rag-service in a background thread with its offline provider and an in-process Qdrant — no container, no API key, no network. They skip automatically if the service source isn't present:

RAG_SERVICE_SRC=/path/to/rag-service/src pytest

Requirements

Python 3.10+ and mcp 2.x. The SDK renamed FastMCP to MCPServer in 2.0, so requirements.txt pins mcp>=2.0,<3 rather than an open >=1.x that resolves across the rename and breaks on a fresh install.

Limitations

  • rag_read_document has no size limit. A large document returns in full and will fill a context window. Chunk-level reads are the safe default.

  • No write tools. Ingestion is deliberately absent: a model that can index documents can also poison the index.

  • No authentication. The server assumes the RAG service is reachable on a trusted network. Exposing it beyond localhost needs auth in front.

  • stdio transport only. No HTTP or SSE transport yet.

  • Tested against one implementation. The contract tests pin rag-service's API shape; another service would need its own.

License

MIT — see LICENSE.

Available Tools

5 tools
rag_answerA

Ask the RAG service to generate an answer, with its sources and trace.

This calls a language model, so it is slower and costs money; prefer rag_search when you intend to read the passages and answer yourself. Returns the answer, the documents it drew on, the per-stage latency breakdown and the cost of the query in USD.

NameRequiredDescriptionDefault
questionYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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

With no annotations, the description carries strong disclosure: it warns that an LLM call makes this slower and cost-bearing, and it enumerates the response payload (answer, source documents, per-stage latency, USD cost). What's missing is any statement of failure modes, timeouts, or idempotency, but the cost/latency warning is exactly the context an agent needs.

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?

Four short sentences; the purpose leads, the cost/latency caveat and the alternative follow, and the return shape closes. No filler or repetition of the tool name.

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, yet the description still summarizes the return shape usefully, and the single-parameter surface is fully covered by the purpose statement plus the timing/cost caveat.

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?

Only one parameter exists and schema description coverage is 0%, but 'question' is self-evident from the name and the description's framing of generating an answer from sources. No real ambiguity remains to document.

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 — 'Ask the RAG service to generate an answer' — and immediately scopes it as answer-plus-sources-plus-trace, which distinguishes it from the sibling rag_search that returns passages only.

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: 'prefer rag_search when you intend to read the passages and answer yourself.' That names the alternative and the condition that selects it, leaving little to inference.

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

rag_index_statsA

Report what is indexed and how the RAG service is configured.

Returns the collection name, chunk count, embedding and chat models, the active reranker and whether tracing is enabled. Call this first when a search returns nothing, to tell an empty index from a bad query.

NameRequiredDescriptionDefault

No parameters

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.5/5.0
Behavior4/5

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

There are no annotations, so the description carries the burden; it discloses that the operation is a passive report and describes its diagnostic role, making clear it mutates nothing. It omits the read-only/non-destructive framing explicitly and says nothing about cost, rate limits, or permissions. For a zero-parameter, side-effect-free diagnostic the remaining risk is low, but the disclosure is not exhaustive.

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?

Front-loaded with the one-line purpose, followed by the return contents and then the diagnostic trigger, in order of decreasing importance. Three sentences with no filler or redundant restatement of the tool name.

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 values needn't be fully documented here, yet the description still previews the key fields to justify the call. With zero parameters and no annotations to reconcile, 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.

Parameters4/5

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

The tool takes zero parameters, which is the baseline-4 case: there is nothing for the description to disambiguate and the empty schema matches the stated behavior of reporting global service state.

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 (report) and resource (index state / RAG configuration) and enumerates the concrete fields returned: collection name, chunk count, embedding and chat models, reranker, tracing flag. This makes it immediately distinguishable from the rag_search / rag_answer siblings, which retrieve content rather than describing the index itself.

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 an explicit trigger condition: "Call this first when a search returns nothing, to tell an empty index from a bad query." That is a clear when-to-use rule grounded in a sibling's failure mode. It stops short of naming explicit alternatives or stating when-not to call it (e.g. no need to poll per query), so a 4 rather than a 5.

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

rag_read_aroundA

Read one indexed chunk in full, together with its neighbouring chunks.

Use this after rag_search when a passage is relevant but truncated and you need the surrounding text. chunk_id comes from rag_search output. context is how many chunks either side to include (0-5, default 1). This is an exact lookup by id, not another search, so it costs nothing to run.

NameRequiredDescriptionDefault
contextNo
chunk_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.7/5.0
Behavior4/5

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

With no annotations, the description carries the burden itself and does well: it declares the operation is an exact id lookup, that it is cheap ("costs nothing to run"), and bounds the context parameter. It stops short of stating read-only semantics in annotation-like terms and says nothing about behavior on an unknown chunk_id (error vs. empty), which is the main remaining gap for a tool with zero annotation coverage.

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?

Four short sentences, front-loaded with the core action, then the usage trigger, then parameter meaning, then a cost reassurance. Each sentence adds distinct information; nothing is restated from the name or schema.

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, trigger, and both parameters. The only missing piece is failure behavior for an invalid or stale chunk_id, which matters given the id is obtained from a prior call.

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 coverage is 0%, so the description must compensate, and it does for both parameters: chunk_id's provenance is named (rag_search output) and context is defined semantically with its range and default ("how many chunks either side to include (0-5, default 1)"). The 0-5 bound is the kind of constraint the bare schema does not express.

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?

Specific verb and resource: "Read one indexed chunk in full, together with its neighbouring chunks." It also explicitly positions itself against rag_search ("This is an exact lookup by id, not another search"), so an agent can distinguish it from all four siblings without opening a 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 an explicit trigger ("Use this after rag_search when a passage is relevant but truncated") and names the source of the required id ("chunk_id comes from rag_search output"). It also states the inverse (not a search), which is the exact confusion an agent would otherwise have with rag_search.

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

rag_read_documentA

Read an entire indexed document, in order.

Use when a document is clearly the right source and you want all of it rather than retrieved fragments. Large documents produce long output — prefer rag_search or rag_read_around when you only need one section.

NameRequiredDescriptionDefault
doc_idYes

Output Schema

NameRequiredDescription
resultYes

TDQS

A4.3/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 burden; 'Read' implies a safe read-only operation, and it discloses the main real risk — that large documents produce long output. It does not say whether output is ever truncated or capped, which is the one behavioral detail missing for a tool whose contract is 'entire document'.

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 the action and scope, then usage condition, then the cost warning. No filler and the cautionary guidance is placed after the primary instruction where it belongs.

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?

Output schema exists, so return format needn't be described, and the cost/verbosity tradeoff against siblings is covered. The remaining gap is the undocumented doc_id and the unresolved question of whether a very large document is truncated despite the promise of reading it 'entirely'.

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

Parameters2/5

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

The single parameter doc_id has 0% schema description coverage, so the description is the only place its meaning could be established — but doc_id is never mentioned, nor where to obtain an identifier (presumably from rag_search results) or what form it takes. The coverage gap is left entirely uncompensated.

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?

Specific verb plus resource plus scope: 'Read an entire indexed document, in order' tells the agent both the operation and that the result is complete and ordered, not a fragment. This is directly contrastable with rag_search and rag_read_around which return partial content.

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?

Explicit when-to-use condition ('when a document is clearly the right source and you want all of it') plus named alternatives with the condition that selects them ('prefer rag_search or rag_read_around when you only need one section'). Both the positive case and the exclusion are stated.

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 observedrag_answer
    • First observedrag_index_stats
    • First observedrag_read_around
    • First observedrag_read_document
    • First observedrag_search

TDQS

A4.4/5.0

Scored across 5 tools

Disambiguation5/5

Each tool has a clearly distinct role: retrieval search, chunk-context reading, whole-document reading, index diagnostics, and LLM answer generation. The descriptions explicitly contrast rag_search with rag_answer and rag_read_around with rag_read_document, leaving little room for misselection.

Naming Consistency4/5

All names use a consistent snake_case rag_ prefix, and most follow a verb or verb-noun pattern such as rag_search and rag_read_document. rag_index_stats is slightly noun-oriented rather than action-oriented, but it remains readable and predictable.

Tool Count5/5

Five tools is well-scoped for a RAG retrieval server, with each tool covering a distinct part of the retrieval-and-answer workflow. There are no redundant tools and no obviously missing core operation within this small surface.

Completeness4/5

The set covers search, contextual reading, full-document reading, diagnostics, and generated answers, which are the core retrieval workflows. Minor gaps might include listing indexed documents or collections directly, but rag_index_stats and search largely compensate.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers