rag-mcp
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., "@rag-mcpsearch the docs for the overpressure limit and read around the top hit"
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.
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.serverWhat 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 |
| Ranked passages with document ids, scores and chunk ids | retrieval only |
| One chunk in full plus its neighbours, by id | none |
| An entire indexed document, in order | none |
| Chunk count, models, reranker, tracing state | none |
| 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 |
|
| Where the RAG service listens |
|
| 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
pytest26 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 pytestRequirements
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_documenthas 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 toolsrag_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.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| context | No | ||
| chunk_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
| Name | Required | Description | Default |
|---|---|---|---|
| doc_id | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
rag_searchA
Search the indexed documents and return the most relevant passages.
Retrieval only: no text is generated, so this is the cheap and fast call. Prefer it when you want source material to read and quote yourself. Returns each passage with its document id, ordinal, relevance score and chunk_id; pass a chunk_id to rag_get_document to read around it. Use rag_answer instead only if you want the service to compose the answer.
| Name | Required | Description | Default |
|---|---|---|---|
| question | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does most of it: it declares the operation is non-generative, cheap and fast, and describes the shape of each returned passage plus the handoff to rag_get_document. It stops short of saying how many passages come back or whether there is any limit/pagination, which matters for a search call.
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?
Front-loaded with the core action, then three short lines covering cost, selection criteria, and return/follow-up. Every sentence earns its place with no repetition.
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?
Output schema exists so return values need no explanation, yet the description still summarizes what comes back and how to continue. Combined with the explicit routing to rag_answer and rag_get_document, an agent has everything needed to call this 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 0%, so the single required 'question' parameter is undocumented by structured data. The description implies it drives relevance search but never says whether it should be a natural-language question, a keyword string, or a phrase, so the agent must guess at the expected form.
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?
States a specific verb and resource ('Search the indexed documents and return the most relevant passages') and immediately scopes itself as retrieval-only, which cleanly separates it from the sibling rag_answer. An agent can pick between 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.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit positive condition ('Prefer it when you want source material to read and quote yourself') and an explicit alternative with the condition that selects it ('Use rag_answer instead only if you want the service to compose the answer'). It also names the follow-up tool rag_get_document and the chunk_id needed to use it.
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.
5 tool updates
v0.1.0- First observed
rag_answer - First observed
rag_index_stats - First observed
rag_read_around - First observed
rag_read_document - First observed
rag_search
TDQS
Scored across 5 tools
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.
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.
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.
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
Related MCP Connectors
Build a RAG pipeline station by station and search your own documents with cited answers.
A search engine that learns from feedback, over embeddings: one tool per API route.
Public web tools for agents: product extraction, claim checks, webpage QA and ranked audits.
Gateway between LLM agents and world data through eight tools and a bundled endpoint catalog.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceExposes RAG and document intelligence pipelines as 8 composable tools for MCP-compatible clients, enabling querying, indexing, classifying, extracting, and assessing documents.1MIT
- AlicenseNot gradedqualityDmaintenanceExposes document ingestion, retrieval (vector, vectorless, hybrid), and multi-turn chat tools for a LangGraph-powered RAG pipeline with streaming answers.3MIT
- AlicenseNot gradedqualityDmaintenanceProvides document search, context retrieval, and indexing tools for AgentOS agents to query pharma documents with grounded citations.MIT
- FlicenseNot gradedqualityCmaintenanceEnables document Q&A and knowledge retrieval through hybrid semantic and keyword search, with tools for document ingestion, chunking, summarization, PII redaction, and RAGAS-based evaluation.-