confluence
Enables querying Confluence or Kubernetes documentation through hybrid search and an agentic RAG pipeline, returning structured answers with citations.
README
Hybrid Agentic RAG — LangChain + LangGraph + Evaluation
This project implements hybrid agentic RAG over Confluence using Python, LangChain, LangGraph, FAISS, BM25Retriever, Cohere reranker, OpenAI embeddings, RAGAS, BERTScore, LangSmith, and FastMCP. An MCP server and Streamlit chatbot are implemented as core functionalities, with a full evaluation suite and LangSmith monitoring.
Table of Contents
- How it Differs from Hybrid RAG
- Setup
- Pipeline
- Testing Without a Confluence Instance
- Monitoring: LangSmith
- Evaluation: RAGAS + Custom Metrics
- MCP Server
How it differs from hybrid RAG
The retrieval quality and pipeline structure are identical. What changes is the underlying library stack and what you get on top of it.
| Component | Hybrid RAG | This project (LangChain) |
|---|---|---|
| BM25 | bm25s |
BM25Retriever (langchain-community) |
| Dense index | numpy .npy |
FAISS vectorstore (langchain-community) |
| RRF fusion | custom _rrf() |
EnsembleRetriever (same c=60 constant) |
| Reranking | cohere.Client() |
CohereRerank + ContextualCompressionRetriever |
| Agent | pydantic-ai |
create_react_agent (LangGraph) |
| Tracing | none | LangSmith (automatic, zero code) |
| Evaluation | none | RAGAS + custom MRR/NDCG/BERTScore |
Setup
uv pip install -r requirements.txt
cp .env.example .env
# Fill in CONFLUENCE_*, OPENAI_API_KEY, COHERE_API_KEY, ANTHROPIC_API_KEY
# Optionally add LANGCHAIN_API_KEY for LangSmith monitoring
Pipeline
1-fetch-confluence.py Fetch Confluence pages → chunks/*.json
1-fetch-k8s.py Fetch public K8s docs → chunks/*.json (no account needed)
↓
2-build-index.py Build indexes/bm25.pkl + indexes/faiss/ + indexes/meta.json
↓
3-hybrid-search.py Interactive CLI to test the four-stage retrieval chain
↓
4-agent.py LangGraph ReAct agent with structured citations
↓
5-evaluate.py Full evaluation suite (retrieval + generator + end-to-end)
↓
6-mcp-server.py FastMCP server for Claude Desktop / Cursor / Claude Code
7-chatbot.py Streamlit chatbot with LangSmith trace links
Run each step
uv run 1-fetch-confluence.py
uv run 2-build-index.py
uv run 3-hybrid-search.py
uv run 4-agent.py "What is our deployment process?"
uv run 5-evaluate.py
uv run 6-mcp-server.py
uv run streamlit run 7-chatbot.py
Testing without a Confluence instance
1-fetch-k8s.py scrapes the public Kubernetes documentation (kubernetes.io/docs)
and saves chunks in the exact same JSON format that 2-build-index.py expects,
so the full pipeline — indexes, agent, evaluation, MCP server, chatbot — runs
unchanged. No Confluence account or API token needed.
Prerequisites
# beautifulsoup4 is the only extra dependency
uv pip install beautifulsoup4
Running the scraper
# Scrape ~190 Kubernetes docs pages (≈ 2 min at 0.5 s/request)
uv run 1-fetch-k8s.py
# Then continue with the normal pipeline
uv run 2-build-index.py
uv run 3-hybrid-search.py
uv run 6-mcp-server.py # terminal 1
uv run streamlit run 7-chatbot.py # terminal 2
Expected output:
Fetching sitemap: https://kubernetes.io/en/sitemap.xml
Found 192 pages to index
[ 1/192] Concepts 3 chunk(s)
[ 2/192] Kubernetes Components 4 chunk(s)
...
Done: 189 pages → 847 chunks (2 empty, 1 errors)
Chunks saved to: .../chunks/
Configuration
Edit the constants at the top of 1-fetch-k8s.py:
| Constant | Default | What it controls |
|---|---|---|
INCLUDE_SECTIONS |
concepts/, tasks/, tutorials/, setup/, reference/glossary/, reference/kubectl/ |
Sections of kubernetes.io/docs to crawl |
SKIP_PATTERNS |
reference/kubernetes-api/, contribute/ |
Sub-paths excluded even within included sections |
REQUEST_DELAY |
0.5 s |
Pause between HTTP requests |
MAX_CHUNK_CHARS |
1500 |
Maximum characters per chunk |
OVERLAP_CHARS |
150 |
Overlap between consecutive chunks |
Example queries once running
- "What is the difference between a Deployment and a StatefulSet?"
- "How do I configure resource limits for a Pod?"
- "What happens when a node fails?"
- "How does the Kubernetes scheduler decide where to place a Pod?"
For evaluation, add K8s questions to eval_set.json and run uv run 5-evaluate.py
to get MRR, NDCG@10, RAGAS faithfulness, and BERTScore against this corpus.
Monitoring: LangSmith
Add three lines to your .env:
LANGCHAIN_TRACING_V2=true
LANGCHAIN_API_KEY=ls_...
LANGCHAIN_PROJECT=hybrid-agentic-rag
That's it. Every LangChain and LangGraph call — embedding lookups, retriever invocations, LLM completions, tool calls — is automatically traced. Open smith.langchain.com to see latency breakdowns, token usage, and full input/output for every step.
Free tier: 5,000 traces/month.
Evaluation: RAGAS + custom metrics
Edit eval_set.json to add your own questions:
[
{
"question": "What is our deployment process?",
"ground_truth": "...",
"relevant_chunk_ids": ["page123_c0", "page456_c2"]
}
]
ground_truth: needed for ROUGE, BERTScore, context precision/recallrelevant_chunk_ids: needed for MRR, NDCG@10, Precision@10, Recall@10 (chunk IDs are visible in3-hybrid-search.pyoutput)
If fields are omitted, those metric groups are skipped gracefully.
Metrics covered
| Category | Metric | Implementation |
|---|---|---|
| Retrieval | MRR | utils/evaluation.py |
| Retrieval | NDCG@10 | utils/evaluation.py |
| Retrieval | Precision@10 | utils/evaluation.py |
| Retrieval | Recall@10 | utils/evaluation.py |
| Generator | ROUGE-1/2/L | rouge-score library |
| Generator | BERTScore F1 | bert-score library |
| End-to-End | Faithfulness | RAGAS (LLM-as-judge) |
| End-to-End | Answer Relevancy | RAGAS (LLM-as-judge) |
| End-to-End | Context Precision | RAGAS (needs ground_truth) |
| End-to-End | Context Recall | RAGAS (needs ground_truth) |
| Monitoring | Latency, tokens, errors | LangSmith (automatic) |
RAGAS uses OpenAI gpt-4o-mini as judge by default. Override with
RAGAS_JUDGE_MODEL=gpt-4o in .env for higher accuracy.
MCP server
uv run 6-mcp-server.py # starts on http://localhost:8051/sse
Add to Claude Desktop config (%APPDATA%\Claude\claude_desktop_config.json):
{
"mcpServers": {
"confluence": { "url": "http://localhost:8051/sse" }
}
}
Or to .mcp.json in any repo root for Claude Code:
{
"mcpServers": {
"confluence": { "type": "sse", "url": "http://localhost:8051/sse" }
}
}
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.