local-graphrag-mcp
A Model Context Protocol server implementing Graph RAG with local, embedded Knowledge Graph using FAISS for vector search and NetworkX for graph traversal, enabling hybrid retrieval through anchor discovery and relationship expansion.
README
Local GraphRAG MCP Server
<!-- mcp-name: io.github.nonatofabio/local-graphrag-mcp -->
A Model Context Protocol (MCP) server that provides a local, embedded Knowledge Graph for Retrieval-Augmented Generation (RAG).
Unlike standard vector stores, this project implements Graph RAG: it uses vector search to find relevant entities ("anchors") and then traverses relationships to retrieve connected context. It runs entirely in a single Python process using FAISS for vector search and NetworkX for graph operations.
Why Graph RAG?
Standard RAG (like FAISS alone) retrieves chunks based on semantic similarity to the query.
Graph RAG retrieves chunks based on semantic similarity AND relationship traversal.
Example:
- Standard RAG: User asks "Who manages the Auth Service?" → Finds chunks semantically similar to the query → May miss "Alice" if her description doesn't semantically match "manages auth service"
- Graph RAG: Finds "Auth Service" node via semantic search → Traverses
[MANAGED_BY]edge → Returns "Alice" and her full context, even if her description doesn't directly relate to the query
Features
Core Capabilities
- Pure Python: FAISS (vector search) + NetworkX (graph traversal) - no external services required
- Single Process: Runs entirely in-process, no Docker containers or background services
- Hybrid Retrieval: Combines vector similarity search (anchor discovery) with graph traversal (context expansion)
- Persistent Storage: Three-file storage system (FAISS index, NetworkX graph, metadata JSON)
- MCP Compatible: Plug-and-play with Claude Desktop, Cursor, or any MCP client
- Configurable Traversal: Control anchor count (top-k) and expansion depth (hops)
Installation
Prerequisites
- Python 3.10+
- pip
From Source
git clone https://github.com/nonatofabio/local_graphrag_mcp.git
cd local_graphrag_mcp
pip install -e .
Development Installation
pip install -e ".[dev]"
Ollama Setup (for Local Entity Extraction)
The CLI uses Ollama by default for local entity extraction. Install and set up Ollama:
# Install Ollama (macOS)
brew install ollama
# Or download from: https://ollama.ai
# Start Ollama service
ollama serve
# Pull the default model (Gemma 3 1B)
ollama pull gemma3:1b
Optional: Cloud Extraction with Claude API
For higher precision entity extraction, install the optional cloud dependencies:
pip install -e ".[cloud]"
export ANTHROPIC_API_KEY='your-key-here'
Usage
CLI Commands
The CLI provides document indexing with automatic entity extraction:
# Index documents using local Ollama (default)
local-graphrag index document.pdf
# Index multiple documents recursively
local-graphrag index -r documents/
# Index with specific Ollama model
local-graphrag index --extract-model gemma2:9b document.pdf
# Index using Claude API (requires anthropic package and API key)
local-graphrag index --use-cloud document.pdf
# Query the knowledge graph
local-graphrag search "What database does the auth service use?"
# List indexed entities
local-graphrag list
1. Running the MCP Server
Add to your claude_desktop_config.json:
{
"mcpServers": {
"local-graphrag": {
"command": "local-graphrag-mcp",
"args": [
"--index-dir", "/absolute/path/to/graphrag_data",
"--embed", "all-MiniLM-L6-v2"
]
}
}
}
Arguments:
--index-dir: Directory where graph data will be stored (default:./graphrag_index)--embed: Sentence transformer model name (default:all-MiniLM-L6-v2)--debug: Enable debug logging (optional)
2. Available Tools
The server exposes two tools to the LLM:
add_knowledge_graph
Directly adds nodes and edges to the knowledge graph. Use this when the LLM has extracted structured information from documents.
Input Schema:
{
"nodes": [
{
"id": "entity:auth_service",
"label": "Service",
"description": "The authentication microservice handling user login",
"properties": {"language": "Python", "version": "2.1.0"}
}
],
"edges": [
{
"source": "entity:auth_service",
"target": "entity:postgres_db",
"label": "CONNECTS_TO",
"properties": {"protocol": "TCP"}
}
]
}
Returns:
{
"success": true,
"nodes_added": 1,
"edges_added": 1
}
query_graph_rag
The primary retrieval tool implementing the "Anchor & Expand" strategy.
Input Schema:
{
"query": "What database does the auth service use?",
"top_k_anchors": 3,
"hops": 2
}
Parameters:
query: Natural language querytop_k_anchors: Number of most similar nodes to find (default: 3)hops: How many relationship hops to traverse from anchors (default: 2)
Returns:
{
"success": true,
"query": "What database does the auth service use?",
"anchors": [
{
"id": "entity:auth_service",
"label": "Service",
"description": "The authentication microservice...",
"similarity_score": 0.85
}
],
"subgraph": {
"nodes": [...],
"edges": [...]
}
}
How It Works Internally
Anchor & Expand Strategy:
- Embed: Converts your query into a 384-dimensional vector using sentence-transformers
- Vector Search: Uses FAISS to find the top-k most similar nodes (anchors) via L2 distance
- Graph Expansion: Performs BFS traversal from anchor nodes up to N hops
- Traverses both outgoing edges (successors)
- Collects all connected nodes and relationships
- Context Assembly: Returns structured subgraph to the LLM with anchor nodes and expanded neighborhood
Example:
Query: "What database does the auth service use?"
Step 1 (Anchor): Find "entity:auth_service" (similarity: 0.85)
Step 2 (Expand 1-hop): Traverse [CONNECTS_TO] → "entity:postgres_db"
Step 3 (Expand 2-hops): Traverse from postgres_db → "entity:backup_service"
Result: Subgraph with 3 nodes and 2 edges
Architecture
Stack Overview
[ LLM Client ] <--> [ MCP Server ] <--> [ GraphRAGVectorStore ]
|
+---------------+---------------+
| |
[ FAISS Index ] [ NetworkX Graph ]
(vector similarity) (relationship traversal)
| |
+----------- Shared IDs --------+
Data Model
Nodes:
id: Unique entity identifier (e.g., "entity:auth_service")label: Entity type (e.g., "Service", "Database", "Person")description: Natural language description (embedded as 384D vector)properties: Schema-less JSON attributes
Edges:
source: Source node IDtarget: Target node IDlabel: Relationship type (e.g., "CONNECTS_TO", "MANAGED_BY")properties: Schema-less JSON metadata
Storage
Three files are created in the index directory:
nodes.index: FAISS IndexFlatL2 (vector embeddings)graph.gpickle: NetworkX directed graph (nodes, edges, properties)metadata.json: Node descriptions and embedding model info
Development
Running Tests
# Install dev dependencies
pip install -e ".[dev]"
# Run all tests
pytest tests/
# Run with verbose output
pytest tests/ -v
# Run standalone integration test
python tests/test_standalone.py
Project Structure
local-graphrag-mcp/
├── local_graphrag_mcp/
│ ├── __init__.py # Package exports
│ ├── __main__.py # CLI entry point
│ └── server.py # Core implementation (585 lines)
├── tests/
│ ├── __init__.py
│ └── test_standalone.py # End-to-end integration test
├── pyproject.toml # Package configuration
├── .mcp.json.example # Example MCP config
├── CLAUDE.md # Development guidance
└── README.md # This file
Key Design Decisions
Why FAISS + NetworkX instead of a graph database?
- Simplicity: Pure Python, no external services (Redis, Neo4j, etc.)
- Performance: FAISS for fast vector search, NetworkX for in-memory graph traversal
- Portability: Entire graph fits in three files, easy to version control or share
Why not DuckDB/DuckPGQ?
- Initial implementation attempted SQL/PGQ property graphs
- Compatibility issues with DuckPGQ extension across DuckDB versions
- Complex SQL syntax for graph patterns vs. simple Python NetworkX API
- Decision: Prioritize simplicity and reliability
Roadmap
- [x] v0.1.0: Core FAISS + NetworkX implementation
- [x] v0.1.0: MCP server with add/query tools
- [x] v0.1.0: Persistent storage and reload
- [ ] v0.2.0: CLI commands for initialization and ingestion
- [ ] v0.3.0: Smart document ingestion (auto-extract entities via LLM)
- [ ] v0.4.0: Graph visualization tools
- [ ] v0.5.0: Multi-hop reasoning enhancements
Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
License
MIT License - see LICENSE file for details
Acknowledgments
This project follows patterns established by local_faiss_mcp for MCP integration and coding style.
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.