A production-ready Model Context Protocol (MCP) server implementing a Retrieval-Augmented Generation (RAG) system with Neo4j graph database backend. The system intelligently converts natural language queries into Cypher queries, retrieves relevant information from a knowledge graph, and provides contextual answers about Wroclaw University of Science and Technology.
- Architecture Overview
- Features
- Prerequisites
- Installation
- Configuration
- Usage
- Project Structure
- Development
- API Reference
- Observability
- Contributing
The system consists of three main components:
- MCP Server - FastMCP-based server exposing knowledge graph tools
- MCP Client - CLI interface for querying the knowledge graph
- Data Pipeline - Multi-threaded ETL pipeline for loading documents into Neo4j
User Query → MCP Client → MCP Server → RAG System → Neo4j Graph DB
↓
Langfuse Observability
↓
LLM Processing → Response
- FastMCP: Model Context Protocol server implementation
- LangChain: LLM orchestration and chaining
- LangGraph: State machine for RAG pipeline
- Neo4j: Graph database for knowledge storage
- Langfuse: Observability and tracing
- OpenAI/DeepSeek: LLM providers for query generation and answering
- Guardrails System: Automatically determines if queries are relevant to the knowledge base
- Fallback Mechanism: Returns graceful responses for out-of-scope queries
- Session Tracking: Full trace tracking across the entire query lifecycle
- Multi-Stage Processing: Guardrails → Cypher Generation → Retrieval → Response
- State Machine Architecture: Built with LangGraph for predictable execution flow
- Error Handling: Robust error recovery with fallback strategies
- Caching: Schema caching for improved performance
- Fast LLM (gpt-5-nano): Quick decision-making for guardrails
- Accurate LLM (gpt-5-mini): Precise Cypher query generation
- Langfuse Integration: Complete trace and session tracking
- Mermaid Visualization: Graph flow visualization for debugging
- Structured Logging: Comprehensive logging throughout the pipeline
- Multi-threaded Processing: Configurable thread pool for parallel document processing
- PDF Support: Extract and process PDF documents
- Dynamic Graph Schema: Configurable nodes and relationships via JSON
- Database Management: Built-in database clearing and initialization
Data Pipeline Diagram
- Diagram: Displays the pipeline flow for document ingestion and processing. See the image below:
- Python 3.12 or higher
- Neo4j database instance (local or cloud)
- OpenAI API key or DeepSeek API key
- Langfuse account (for observability)
uvpackage manager (recommended) orpip
git clone <repository-url>
cd SOLVRO_MCPUsing uv (recommended):
uv syncUsing pip:
pip install -e .Option A: Docker Compose
cd db
docker-compose up -dOption B: Neo4j Desktop or Aura
Follow Neo4j's installation guide for your platform.
Create a .env file in the project root:
# LLM Provider (choose one)
OPENAI_API_KEY=your_openai_api_key
# OR
DEEPSEEK_API_KEY=your_deepseek_api_key
# CLARIN Polish LLM (optional, for Polish language support)
CLARIN_API_KEY=your_clarin_api_key
# Neo4j Configuration
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=your_neo4j_password
# Langfuse Observability
LANGFUSE_SECRET_KEY=your_langfuse_secret_key
LANGFUSE_PUBLIC_KEY=your_langfuse_public_key
LANGFUSE_HOST=https://cloud.langfuse.comEdit graph_config.json to define your knowledge graph structure:
{
"nodes": [
{
"name": "Student",
"properties": ["name", "id", "year"]
},
{
"name": "Course",
"properties": ["title", "code", "credits"]
}
],
"relationships": [
{
"type": "ENROLLED_IN",
"source": "Student",
"target": "Course",
"properties": ["semester", "grade"]
}
]
}Start the FastMCP server on port 8005:
just mcp-server
# OR
uv run serverThe server will initialize the RAG system and expose the knowledge_graph_tool.
Query the knowledge graph using natural language:
just mcp-client "Czym jest nagroda dziekana?"
# OR
uv run kg "What is the dean's award?"Example queries:
# Polish queries
uv run kg "Jakie są wymagania dla stypendium rektora?"
uv run kg "Kiedy są terminy egzaminów?"
# English queries
uv run kg "What are the scholarship requirements?"
uv run kg "When are the exam dates?"just pipeline
# OR
uv run pipelinejust pipeline-clear
# OR
uv run pipeline --clear-dbuv run python src/scripts/data_pipeline/main.py \
data/ \
graph_config.json \
4 \
--clear-dbParameters:
data/- Input directory containing PDF filesgraph_config.json- Graph schema configuration4- Number of parallel threads--clear-db- (Optional) Clear database before loading
SOLVRO_MCP/
├── src/
│ ├── mcp_server/ # MCP server implementation
│ │ ├── server.py # FastMCP server entry point
│ │ └── tools/
│ │ └── knowledge_graph/
│ │ ├── rag.py # RAG system core logic
│ │ ├── state.py # LangGraph state definitions
│ │ └── graph_visualizer.py # Mermaid visualization
│ │
│ ├── mcp_client/ # CLI client
│ │ └── client.py # Client implementation with Langfuse integration
│ │
│ └── scripts/
│ └── data_pipeline/ # ETL pipeline
│ ├── main.py # Pipeline orchestrator
│ ├── data_pipe.py # Data processing logic
│ ├── llm_pipe.py # LLM-based entity extraction
│ └── pdf_loader.py # PDF document loader
│
├── db/
│ └── docker-compose.yaml # Neo4j container configuration
│
├── data/ # Input documents directory
├── graph_config.json # Graph schema definition
├── pyproject.toml # Project dependencies and metadata
├── justfile # Task runner configuration
└── README.md # This file
The project uses Ruff for linting and formatting:
just lint
# OR
uv run ruff format src
uv run ruff check srcRuff Settings (in pyproject.toml):
- Line length: 100 characters
- Target: Python 3.13
- Selected rules: E, F, I, N, W
To add a new MCP tool:
- Create a new function in
src/mcp_server/server.py - Decorate with
@mcp.tool - Add documentation and type hints
- Update the README
Example:
@mcp.tool
async def new_tool(param: str) -> str:
"""
Tool description.
Args:
param: Parameter description
Returns:
Result description
"""
# Implementation
return resultQuery the knowledge graph with natural language.
Parameters:
user_input(str): User's question or querytrace_id(str, optional): Trace ID for observability
Returns:
str: JSON string containing retrieved context or "W bazie danych nie ma informacji"
Example:
result = await client.call_tool(
"knowledge_graph_tool",
{
"user_input": "What are the scholarship requirements?",
"trace_id": "unique-trace-id"
}
)Async method to query the RAG system.
Parameters:
message(str): User's questionsession_id(str): Session identifier (default: "default")trace_id(str): Trace identifier (default: "default")callback_handler(CallbackHandler): Langfuse callback handler
Returns:
Dict[str, Any]: Dictionary containing:answer(str): JSON context or "W bazie danych nie ma informacji"metadata(dict):guardrail_decision(str): Routing decisioncypher_query(str): Generated Cypher querycontext(list): Retrieved data from Neo4j
Load and process PDF documents from a directory.
Parameters:
directory(str): Path to directory containing PDF files
Returns:
- None (processes documents in-place)
The system provides comprehensive observability through Langfuse:
- Session Tracking: All queries within a session are grouped together
- Trace Hierarchy: Multi-level traces showing:
- Guardrails decision
- Cypher generation
- Neo4j retrieval
- Final answer generation
- Metadata Tagging: Traces tagged with component identifiers
- Performance Metrics: Latency and token usage tracking
- Log in to your Langfuse dashboard
- Navigate to "Sessions" to see grouped queries
- Click on individual traces for detailed execution flow
- Use filters to search by tags:
mcp_client,knowledge_graph,guardrails, etc.
The RAG system includes Mermaid graph visualization:
print(rag.visualizer.draw_mermaid())This outputs a Mermaid diagram showing the state machine flow.
1. Connection Refused (Neo4j)
Error: Could not connect to Neo4j at bolt://localhost:7687
Solution: Ensure Neo4j is running:
cd db && docker-compose up -d2. API Key Issues
Error: Missing required environment variables
Solution: Check your .env file contains all required keys.
3. Import Errors
ImportError: cannot import name 'langfuse_context'
Solution: This import is not available in standard Langfuse. Use session tracking through function parameters.
Adjust parallel processing threads in the pipeline:
uv run python src/scripts/data_pipeline/main.py data/ graph_config.json 8Recommended thread counts:
- CPU-bound: Number of CPU cores
- I/O-bound: 2-4x CPU cores
- Indexing: Create indexes on frequently queried properties
- LIMIT Clauses: Pipeline automatically adds LIMIT to queries
- Connection Pooling: FastMCP handles connection management
Adjust model parameters in rag.py:
self.fast_llm = BaseChatOpenAI(
model="gpt-5-nano",
temperature=0.1, # Lower = more deterministic
)For AI coding assistants and developers, see .github/agents.md for detailed coding guidelines and patterns.
The project now includes a FastAPI service for integrating with the ToPWR application. This provides:
- RESTful API endpoints for chat functionality
- Conversation state management with memory
- User tracking and session management
- Thread-safe in-memory storage (database integration pending)
# Start the API server
just topwr-api
# OR
uv run topwr-apiThe API will be available at http://localhost:8000
POST /api/chat- Send a message and get AI responseGET /api/sessions/{session_id}- Get session informationGET /api/sessions/{session_id}/history- Get conversation historyGET /api/users/{user_id}/sessions- Get all user sessionsGET /api/stats- Get system statisticsGET /health- Health check
# Start a new conversation
curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{
"user_id": "user123",
"message": "Czym jest nagroda dziekana?"
}'
# Continue conversation with session_id
curl -X POST http://localhost:8000/api/chat \
-H "Content-Type: application/json" \
-d '{
"user_id": "user123",
"session_id": "abc123...",
"message": "A jakie są wymagania?"
}'For complete API documentation, see src/topwr_api/README.md
- Fork the repository
- Create a feature branch:
git checkout -b feature/new-feature - Make changes and ensure tests pass
- Run linting:
just lint - Commit changes:
git commit -m "Add new feature" - Push to branch:
git push origin feature/new-feature - Open a Pull Request
[Add your license here]
- Built for Wroclaw University of Science and Technology
- Powered by FastMCP, LangChain, and Neo4j
- Observability by Langfuse
For issues and questions:
- Open an issue on GitHub
- Contact the development team
- Check the documentation at [link]


