Skip to main content
Glama

BDC Doc RAG

El MCP RAG de documentación de bdc-assist

bdc_doc_mcp/config.py      env-driven embeddings/LLM/Chroma (replaces utils/__init__.set_emb_llm)
bdc_doc_mcp/ingest.py      .pkl/.md/.mdx/.txt/.pdf → embeddings → Chroma (replaces utils/chroma/utils.py)
bdc_doc_mcp/api.py         FastAPI: /health /search
bdc_doc_mcp/mcp_server.py  search_docs MCP tool for AI agents — self-contained, same search as the API
bdc_doc_mcp/preproc/       source-specific preprocessing pipeline
tests/                     self-checks + API / agent notebooks
data/                      preproc output (*.pkl), ingest input

Configuración

uv sync
cp .env.example .env    # then fill in keys/URLs

Repositorios fuente

Solo se necesitan para el preprocesamiento (--sources all); el servidor API/MCP y la ingesta de archivos .pkl existentes funcionan sin ellos. Clona junto a este repositorio (o apunta las variables de entorno a ellos):

git clone https://github.com/stagecc/interim-bdc-website ../interim-bdc-website   # BDC_WEBSITE_DIR
git clone https://github.com/stagecc/bdc-gitbook ../bdc-gitbook                   # BDC_GITBOOK_DIR

Modelos

Para la finalización, usa la API de OpenAI en Azure (gpt-4o-mini por defecto)

Para los embeddings, usa Ollama en Sterling (conéctate mediante la VPN de RENCI)

kubectl -n ner port-forward svc/ollama 11434:11434

O usando Ollama local con el modelo groonga/bge-m3-Q4_K_M-GGUF.

Related MCP server: okfy

Ingesta

Reconstrucción completa desde cada fuente (necesita los dos repositorios fuente clonados — ver Configuración; escribe data/*.pkl y luego los carga):

uv run python -m bdc_doc_mcp.preproc.pipeline --sources all --ingest --reset

Archivos o directorios individuales:

uv run python -m bdc_doc_mcp.ingest ./data/docs.pkl --doc-type docs   # BDC_Chatbot preproc .pkl
uv run python -m bdc_doc_mcp.ingest ../interim-bdc-website/src/pages --doc-type page --reset

Los modelos de embedding no son intercambiables dentro de una colección — bge-m3 es de 1024 dimensiones, text-embedding-3-small de 1536. Cambiar de modelo implica --reset y una re-ingesta completa.

API

uv run uvicorn bdc_doc_mcp.api:app --port 8000     # docs at /docs

Endpoint

Cuerpo

Devuelve

GET /health

—

{status, documents}

POST /search

{query, k, mode?, doc_type?, date_from?, date_to?}

fragmentos clasificados + metadatos + puntuación

mode es embedding (por defecto; similitud semántica, puntuación = distancia, menor es mejor) o keyword (coincidencia literal difusa de palabras — ignora mayúsculas/puntuación y tolera pequeños errores tipográficos, así que picsure encuentra "PIC-SURE"; puntuación = recuento de ocurrencias, mayor es mejor — úsalo para nombres/acrónimos exactos). doc_type es un CSV de tipos a buscar (p. ej. page,faq). Cuando se omite, solo se buscan docs, page, faq y video — nombra fellow, update o event explícitamente para buscarlos. date_from/date_to (YYYY-MM-DD, inclusive) filtran por fecha; solo los documentos de evento y actualización llevan fecha, por lo que un filtro de fecha se reduce implícitamente a esos tipos.

El servicio es solo de búsqueda por diseño; la ingesta ocurre sin conexión mediante la CLI (ver Ingesta) y responder es tarea del llamador — un agente trae su propio LLM.

MCP

uv run python -m bdc_doc_mcp.mcp_server           # stdio
uv run python -m bdc_doc_mcp.mcp_server --http    # streamable HTTP, port MCP_PORT (default 8001)

Expone una herramienta, search_docs — la misma búsqueda que la API pero consulta Chroma directamente, por lo que el servicio API no necesita ejecutarse. Necesita un .chroma_db ingerido + embeddings.

Los clientes Stdio (Claude Desktop/Code, Cursor) lanzan el servidor ellos mismos — regístralo:

{"mcpServers": {"bdc-doc-mcp": {
  "command": "uv",
  "args": ["--directory", "/path/to/bdc-doc-mcp", "run", "python", "-m", "bdc_doc_mcp.mcp_server"]
}}}

Clientes de red: ejecuta --http y apúntalos a http://host:8001/mcp en su lugar.

Prueba de humo: uv run python tests/test_mcp.py

Preprocesamiento

bdc_doc_mcp/preproc/ es el pipeline de BDC_Chatbot, portado:

Módulo

Fuente

Portado de (BDC_Chatbot)

Notas

bdc_repo.py

interim-bdc-website MDX

utils/preproc/proc_BDC_repo.py (verbatim-ish)

fellows, events, latest-updates, pages

bdc_docs.py

bdc-gitbook markdown

utils/preproc/proc_BDC_docs.py (module-level LLM init removed)

dividido en fragmentos por jerarquía de encabezados; necesita el repositorio clonado

freshdesk.py

bdcatalyst.freshdesk.com

utils/preproc/proc_freshdesk.py

raspado en vivo

vids.py

Google Sheet + Drive SRT

utils/preproc/proc_BDC_vids.py (GoogleSheetsReader class flattened)

transcripciones de video con URLs de marca de tiempo

utils.py

—

—

contextualizador de fragmentos LLM + resumidor

pipeline.py

—

utils/preproc_doc.py

orquestador

--no-contextualize omite la llamada LLM por fragmento (mucho más rápido, recuperación más débil). Las rutas de origen provienen de BDC_WEBSITE_DIR / BDC_GITBOOK_DIR.

Pruebas

uv run python tests/test_ingest.py                             # batching + chunk-id logic, no network
uv run python tests/test_keyword.py                            # keyword ranking, pure function, no DB or API
uv run python tests/test_mcp.py                                # starts the server over stdio and exercises its tools; needs .chroma_db + embeddings

Notebooks (cada uno inicia la API en un puerto libre y la apaga al final; ambos necesitan un .chroma_db ingerido):

  • tests/api_test.ipynb — recorrido simple de la API: /health, /search, filtro doc_type. Solo necesita los embeddings locales.

  • tests/agent_test.ipynb — un agente que llama a herramientas (deepagents): el LLM configurado recibe search_docs como herramienta de LangChain y decide cuándo llamarla. También necesita que el proveedor de finalización sea accesible.

Available Tools

1 tool
search_docsA

Search the BDC (NHLBI BioData Catalyst) documentation database.

Returns the top-k matching chunks with content, metadata (source, doc_type, datetime when available), and a score.

query is the search text. In embedding mode phrase it as a question or topic (e.g. "how do I bring my own data"); in keyword mode give the literal terms to match.

k is the number of chunks to return (default 5). Raise it (10-20) for broad or multi-part questions; each chunk is a small section of a document.

mode toggles the search engine:

  • "embedding" (default): semantic similarity — best for questions, topics, and paraphrased wording. score is a distance (lower = more similar).

  • "keyword": fuzzy literal word matching — ignores case and punctuation ("picsure" finds "PIC-SURE") and tolerates small typos — best for exact names, acronyms, tool names, or error messages the embedding may blur. Chunks matching more of the query terms rank first; score is the total number of occurrences (higher = better).

doc_type is a CSV string of types to search (e.g. "page,faq" or "video"). Available types:

  • docs: BDC GitBook platform documentation — user guides, how-tos, and technical reference (bdcatalyst.gitbook.io)

  • page: key pages of the BDC website — about/overview, joining BDC, analyzing & sharing data, usage costs and terms

  • faq: Freshdesk help-desk FAQ articles (support questions & answers)

  • video: transcripts of BDC YouTube tutorials/webinars, with timestamped links into the video

  • fellow: BDC Fellows profiles — fellowship recipients and their research projects

  • update: dated news posts ("latest updates") from the BDC website

  • event: dated BDC events — webinars, workshops, deadlines When doc_type is omitted, only docs, page, faq, and video are searched — name fellow, update, or event explicitly to search them.

date_from / date_to ("YYYY-MM-DD", inclusive) filter by date. Only event and update docs carry a date, so a date filter implicitly narrows to those types. Results are ranked by relevance, NOT date — for "recent"/"latest" questions, always set date_from to bound the range, then compare the dates returned.

ParametersJSON Schema
NameRequiredDescriptionDefault
kNo
modeNoembedding
queryYes
date_toNo
doc_typeNo
date_fromNo

TDQS

A5/5.0
Behavior5/5

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

With no annotations, the description fully discloses behavioral traits: default doc types when omitted, score interpretation (distance vs occurrences), the effect of date filters, and ranking by relevance not date. It also notes that only event and update docs carry dates, further clarifying behavior. No annotation contradiction exists.

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?

The description is well-structured with bullet points for modes and types, and clear paragraphs for date and ranking behavior. It is lengthy but every sentence carries essential information, and it is front-loaded with the purpose and return content. No wasted words.

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 (6 parameters, no output schema, no annotations), the description is complete. It explains return format, scoring meaning, type-specific behavior, and parameter interactions. It fully equips an agent to invoke the tool correctly for a variety of use cases.

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 the description must compensate, and it does thoroughly. It explains query phrasing for each mode, k's range and purpose, mode options with detailed semantics, doc_type as a CSV list with each type's meaning, and date_from/date_to format and inclusive behavior. This adds far more meaning than the bare schema.

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 clearly states it searches the BDC (NHLBI BioData Catalyst) documentation database and returns top-k matching chunks with content, metadata, and a score. It names the specific resource and what is returned, making the tool's purpose unambiguous even without sibling tools for differentiation.

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?

Provides explicit guidance on when to use embedding vs keyword mode, how to adjust k for broad questions, when to explicitly name doc_type values, and how to use date filters for recency queries. It also warns that date filters implicitly narrow to types with dates and explains ranking behavior, giving clear when-to-use and when-not-to-use instruction.

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. 1 tool updatev0.1.0
    • First observedsearch_docs

TDQS

A4.6/5.0

Scored across 1 tool

Disambiguation5/5

With only a single tool, there is no possibility of ambiguity. The tool has a clearly defined purpose for searching documentation.

Naming Consistency5/5

The tool name 'search_docs' follows a consistent verb_noun pattern and is descriptive. Since it is the only tool, naming is inherently consistent.

Tool Count1/5

The server exposes only one tool, which is extremely thin. Even though the tool is multi-functional, a single tool does not constitute a well-scoped set; most servers with this purpose would benefit from at least a couple of complementary tools (e.g., retrieving a document by ID or listing available types).

Completeness3/5

The search tool covers multiple documentation sources and provides filtering and multiple modes, which addresses the core purpose. However, it lacks any other operation such as fetching a specific document, listing available doc types, or managing content, leaving notable gaps for a documentation server.

Maintenance

ActivityMaintained
ResponsivenessUnresponsive

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides semantic search over markdown documentation using RAG, allowing natural language queries and integration with MCP clients.
    1
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI agents to search, read, and traverse documentation bundles in Open Knowledge Format via MCP tools.
    506 npm
    73
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides RAG (Retrieval Augmented Generation) access to technical documentation through MCP, enabling LLMs to search and retrieve relevant documentation on-demand.
    4
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    Crawl documentation sites, index them with hybrid search, and expose them as MCP tools so LLM agents can search and retrieve current docs.
    MIT