Skip to main content

Retrieval-only MCP server over the indexed React documentation, with a prebuilt index downloaded on first run.

Project description

cfunklabs-rag-react-docs

Backend for the RAG demo, built with LangChain, LangGraph, Anthropic Claude, and ChromaDB. It also ships a retrieval-only MCP server, published to PyPI as cfunklabs-rag-react-docs, that serves grounding context from the indexed React documentation (see MCP server).

Prerequisites

Setup

All commands should be run from the backend directory.

1. Install dependencies

uv sync

2. Configure environment variables

Copy the sample env file and add your Anthropic API key:

cp .env.sample .env

Open .env and set your key:

ANTHROPIC_API_KEY=your_api_key_here

3. Initialize the vector database

Create the ChromaDB collection used to store document embeddings:

uv run src/utils/init_db.py

This creates a persistent ChromaDB store under rag_datastore/ and a collection named after tool.rag_db.rag_doc_collection_name in pyproject.toml. The rag_datastore/ directory is gitignored.

4. Fetch the React docs dataset

The corpus is a local mirror of the React documentation markdown files. Download it with:

uv run src/utils/fetch_react_docs.py

This script:

  1. Fetches the index at react.dev/llms.txt
  2. Follows every linked https://react.dev/*.md URL
  3. Saves each page under docs/ at the repository root, using the index heading structure as directories and each file's frontmatter title as the filename

Example output path:

docs/API Reference/React/Components/Built-in React Components.md

The docs/ directory is gitignored — run the script locally after cloning and re-run it anytime to refresh the dataset.

Running

Startup check

Run main.py to verify your environment is configured correctly. It prints installed package versions and performs a live health check against the Claude API:

uv run main.py

A passing run looks like:

Versions:
  - langchain_core_version: x.x.x
  - langgraph_version: x.x.x
  - langchain_anthropic_version: x.x.x

Checking LLM service health... PASSED

If the health check fails, confirm that ANTHROPIC_API_KEY is set correctly in your .env file.

Ingesting documents

Chunk every Markdown file under docs/, embed the chunks, and upsert them into the vector store:

uv run main.py

To process a single file (useful while iterating on chunking), pass --md_file_path. Add --evaluate_chunking to write LLM-as-judge quality reports to evals/results, or --print_chunks to dump each chunk to stdout.

Querying

Ask a question against the ingested docs. The query pipeline is a LangGraph graph (retrieve -> generate) that embeds your question with the same model used at ingestion, retrieves the most similar chunks from ChromaDB, and has Claude answer using only that context. The answer streams token-by-token and is followed by the cited sources:

uv run query.py "How does memo work?"

Options:

  • --k N — number of chunks to retrieve (default top_k in pyproject.toml).
  • --no-stream — wait for the full answer instead of streaming tokens.
  • --show-scores — show the retrieval distance for each cited source.
  • -v, --verbose — show diagnostic output (the preflight datastore and LLM health checks). Hidden by default.

Retrieval and generation settings live under [tool.rag_query] in pyproject.toml (top_k and generation_model). Run uv run main.py first — querying requires a populated collection.

MCP server

In addition to the CLI, the retrieval pipeline is exposed as an MCP server over stdio, so MCP clients (Cursor, Claude Desktop, etc.) can pull grounding context directly. It exposes a single retrieval-only tool:

  • search_docs(question, k?) — embeds the question with the same model used at ingestion, retrieves the most similar chunks from ChromaDB, and returns each chunk's source label, content, and retrieval distance. The client LLM generates the answer from those chunks, so no Anthropic key is needed to run the server.

For end users (published package)

The server is published to PyPI as cfunklabs-rag-react-docs. End users don't clone the repo or run the ingestion pipeline — the prebuilt index (~34 MB) is downloaded from a GitHub Release and cached on first run. Just register it with your MCP client:

{
  "mcpServers": {
    "rag-react-docs": {
      "command": "uvx",
      "args": ["cfunklabs-rag-react-docs"]
    }
  }
}

The first launch needs network access to fetch the index; subsequent runs read from the local cache (platformdirs cache dir) and work offline. Optional environment overrides: RAG_TOP_K, RAG_COLLECTION_NAME, RAG_INDEX_URL, and RAG_DATASTORE_DIR.

Local development

Run the dev server from the backend directory (so pyproject.toml resolves) against the locally-built rag_datastore:

uv run mcp_server.py

Run standalone this way, the server prints a short startup banner to stderr and then blocks silently by design — the stdio transport reserves stdout for the JSON-RPC protocol, so it waits for a client to connect rather than logging. Running it directly is mainly a smoke test; press Ctrl+C to stop.

Run uv run main.py first — the dev server needs a populated collection. For interactive testing, launch the MCP Inspector with uv run mcp dev mcp_server.py.

Publishing to PyPI

The published package (cfunklabs-rag-react-docs) contains only the retrieval + MCP server (the import package rag_react_docs under src/). Ingestion/query tooling and src/utils/* are dev-only and excluded from the wheel.

Two artifacts get published: the Python package (to PyPI) and the prebuilt index (to a GitHub Release). They version independently — the index version is pinned as INDEX_VERSION in src/rag_react_docs/config.py.

  1. Build and upload the index archive (after uv run main.py has populated rag_datastore):
uv run scripts/build_index_archive.py
gh release create index-19-2-v1 dist/rag-index-19-2-v1.tar.gz dist/rag-index-19-2-v1.tar.gz.sha256
  1. Build and publish the package (test on TestPyPI first):
uv build                                   # -> dist/ wheel + sdist (only rag_react_docs)
uv publish --publish-url https://test.pypi.org/legacy/   # TestPyPI dry run
uv publish                                 # PyPI

The index version follows the standard index-<react-version>-v<incremental> (e.g. index-19-2-v1), composed in src/rag_react_docs/config.py from REACT_VERSION and INDEX_REVISION. Bump REACT_VERSION when re-fetching the docs for a new React release, and bump INDEX_REVISION for re-chunk or embedding-model changes within the same React version. Either bump changes the release tag/asset name and cache path, so clients pull a fresh, compatible index instead of reusing a stale cache — re-release the archive under the new index-<react-version>-v<incremental> tag.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cfunklabs_rag_react_docs-0.1.2.tar.gz (9.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cfunklabs_rag_react_docs-0.1.2-py3-none-any.whl (11.7 kB view details)

Uploaded Python 3

File details

Details for the file cfunklabs_rag_react_docs-0.1.2.tar.gz.

File metadata

  • Download URL: cfunklabs_rag_react_docs-0.1.2.tar.gz
  • Upload date:
  • Size: 9.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for cfunklabs_rag_react_docs-0.1.2.tar.gz
Algorithm Hash digest
SHA256 3e46ecd4cdabaa0bbf203f7130ffa182db9ce8b3ff1a4e0de00a9119203fd4ba
MD5 998930b388dbed07908104e73893f5b6
BLAKE2b-256 25717ba03808e633d733123b71967eb88a56b50f488df960d0d2f2b564392319

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfunklabs_rag_react_docs-0.1.2.tar.gz:

Publisher: publish.yml on cfunklabs/rag-react-docs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file cfunklabs_rag_react_docs-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for cfunklabs_rag_react_docs-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 c64e9ae54db9fdac7a5b64f66a0e2edab5db1647286a8964fa2cebab397863a5
MD5 859886534861cee9fd0a4ca25582fffd
BLAKE2b-256 34f54a51b7570e65638e4591a27f0c3729735791bc146b9566f9a6360cccd636

See more details on using hashes here.

Provenance

The following attestation bundles were made for cfunklabs_rag_react_docs-0.1.2-py3-none-any.whl:

Publisher: publish.yml on cfunklabs/rag-react-docs

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page