Neo4j MCP Knowledge Graph Server

Neo4j MCP Knowledge Graph Server

A containerized FastAPI + MCP server that lets LLM agents inject structured entities and relationships into a Neo4j graph database with safe Cypher execution.

Category
Visit Server

README

Neo4j MCP Knowledge Graph Server

A containerized FastAPI + MCP (Model Context Protocol) server that lets LLM agents inject structured knowledge (Entities and Relationships) into a Neo4j graph database with APOC-based safe Cypher execution.

Features

  • Dual API: REST endpoints + MCP SSE transport for LLM agent integration
  • Safe Cypher: APOC procedures prevent Cypher injection with dynamic labels/types
  • Full-text search: Cross-label search via Neo4j full-text index
  • Schema flexibility: Agents can invent node labels and relationship types (tagged with is_generated: true)
  • API key auth: All traffic protected by X-API-Key header
  • Docker Compose: One-command deployment with Neo4j 5 + APOC

Prerequisites

  • Docker Desktop (with Docker Compose)
  • Git
  • (Optional) Python 3.10+ for local development

Quick Start

1. Clone the repository

git clone https://github.com/jfelipenc/neo4j-mcp-knowledge-graph.git
cd neo4j-mcp-knowledge-graph

2. Configure environment

cp .env.example .env

Edit .env and set your values:

# Required: Change this to a secure random string
API_KEY=your-secure-api-key-here

# Neo4j connection (defaults work with docker-compose)
NEO4J_URI=bolt://neo4j:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=testpassword123

Important: Change API_KEY to a secure random string. Generate one with:

# Linux/macOS
openssl rand -hex 32

# Windows PowerShell
[guid]::NewGuid().ToString("N")

3. Change the Neo4j password (optional but recommended)

Edit docker-compose.yml and update both services:

neo4j:
  environment:
    - NEO4J_AUTH=neo4j/your-new-password-here
    ...
  healthcheck:
    test: ["CMD", "cypher-shell", "-u", "neo4j", "-p", "your-new-password-here", "RETURN 1"]

api:
  environment:
    - NEO4J_PASSWORD=your-new-password-here

Also update .env:

NEO4J_PASSWORD=your-new-password-here

4. Start the stack

docker-compose up --build

Wait for Neo4j to be healthy (the API service depends on it):

neo4j-mcp-knowledge-graph-neo4j-1  | Started.
neo4j-mcp-knowledge-graph-api-1    | INFO:     Uvicorn running on http://0.0.0.0:8000

5. Verify it's running

# Health check (no auth required)
curl http://localhost:8000/health

# Test auth (replace with your API key)
curl -X POST http://localhost:8000/api/knowledge/entities \
  -H "X-API-Key: your-secure-api-key-here" \
  -H "Content-Type: application/json" \
  -d '{"entities": [{"name": "Alice", "label": "Person"}]}'

API Documentation

Authentication

All endpoints (except /health) require the X-API-Key header.

REST Endpoints

Add Entities

POST /api/knowledge/entities
Content-Type: application/json
X-API-Key: your-api-key

{
  "entities": [
    {
      "name": "Alice",
      "label": "Person",
      "properties": {"age": 30, "city": "NYC"},
      "is_generated": false
    },
    {
      "name": "GraphDB",
      "label": "Technology",
      "properties": {"vendor": "Neo4j"},
      "is_generated": true
    }
  ]
}

Response:

{"count": 2}

Add Relations

POST /api/knowledge/relations
Content-Type: application/json
X-API-Key: your-api-key

{
  "relations": [
    {
      "source_name": "Alice",
      "source_label": "Person",
      "target_name": "GraphDB",
      "target_label": "Technology",
      "relation_type": "USES",
      "properties": {"since": "2024"},
      "is_generated": false
    }
  ]
}

Response:

{"count": 1}

Search Graph

GET /api/knowledge/search?q=Alice&limit=10
X-API-Key: your-api-key

Response:

{
  "nodes": [
    {
      "name": "Alice",
      "label": "Person",
      "properties": {"age": 30, "city": "NYC"}
    }
  ],
  "edges": [
    {
      "source": "Alice",
      "target": "GraphDB",
      "type": "USES",
      "properties": {"since": "2024"}
    }
  ]
}

Search tips:

  • Use * for prefix matching: Alice* finds Alice, AliceSmith
  • Search is case-insensitive on the full-text index
  • Limit defaults to 10, max 100

MCP (Model Context Protocol)

The server exposes MCP tools via SSE (Server-Sent Events) transport.

Connect to SSE

GET /mcp/sse
X-API-Key: your-api-key

This opens an SSE stream. The MCP client will receive an endpoint event with the URL to POST messages to.

MCP Tools

Tool Description Parameters
add_entities Add nodes to the graph entities: list[Entity]
add_relations Add relationships between nodes relations: list[Relation]
search_graph Search nodes by name, return subgraph query: str, limit: int = 10

Entity schema:

{
  "name": "string (required)",
  "label": "string (required)",
  "properties": {"key": "value"},
  "is_generated": "boolean (default: false)"
}

Relation schema:

{
  "source_name": "string (required)",
  "source_label": "string (required)",
  "target_name": "string (required)",
  "target_label": "string (required)",
  "relation_type": "string (required)",
  "properties": {"key": "value"},
  "is_generated": "boolean (default: false)"
}

Local Development

Setup

# Create virtual environment
python -m venv .venv
.venv\Scripts\activate  # Windows
# source .venv/bin/activate  # Linux/macOS

# Install dependencies
pip install -r requirements.txt

Run tests

# Unit tests (fast, no Docker required)
pytest tests/ -m "not integration" -v

# Integration tests (requires Docker, spins up Neo4j container)
pytest tests/ -m integration -v

# All tests
pytest tests/ -v

Run locally (without Docker)

# Start Neo4j separately (e.g., via Docker)
docker run -p 7474:7474 -p 7687:7687 \
  -e NEO4J_AUTH=neo4j/testpassword123 \
  -e NEO4J_PLUGINS='["apoc"]' \
  -e NEO4J_dbms_security_procedures_unrestricted=apoc.* \
  neo4j:5

# Set environment variables
$env:API_KEY="dev-api-key"
$env:NEO4J_URI="bolt://localhost:7687"
$env:NEO4J_USER="neo4j"
$env:NEO4J_PASSWORD="testpassword123"

# Run the app
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000

Project Structure

/
├── app/
│   ├── __init__.py
│   ├── main.py          # FastAPI app, auth, REST endpoints, MCP SSE wiring
│   ├── mcp_server.py    # MCP tools (add_entities, add_relations, search_graph)
│   ├── database.py      # Neo4j driver, APOC merges, full-text search
│   └── schemas.py       # Pydantic models (Entity, Relation)
├── tests/
│   ├── test_schemas.py
│   ├── test_database.py
│   ├── test_mcp_server.py
│   ├── test_main.py
│   └── test_integration.py
├── docker-compose.yml   # Neo4j 5 + APOC + API service
├── Dockerfile           # Python 3.11 app container
├── requirements.txt
├── .env.example         # Environment template
└── README.md

Security Notes

  • API key: Always change the default API_KEY in production
  • Neo4j password: Change the default testpassword123 in production
  • Cypher injection: APOC procedures prevent injection via dynamic labels/types
  • Timing attacks: API key comparison uses secrets.compare_digest
  • Auth coverage: All routes except /health require authentication

Troubleshooting

Neo4j container won't start

# Check logs
docker-compose logs neo4j

# Common fix: remove stale volume and restart
docker-compose down -v
docker-compose up --build

API can't connect to Neo4j

  • Verify Neo4j is healthy: docker-compose ps
  • Check the password matches in both docker-compose.yml and .env
  • Ensure NEO4J_URI uses the service name (bolt://neo4j:7687) not localhost

Full-text search returns no results

  • Neo4j full-text indexes are eventually consistent — wait a moment after writes
  • Use prefix wildcards: Alice* instead of Alice for partial matching
  • Verify the index exists: SHOW INDEXES in Neo4j Browser (http://localhost:7474)

Port conflicts

If ports 8000, 7474, or 7687 are in use, edit docker-compose.yml:

api:
  ports:
    - "8001:8000"  # Change 8001 to an available port

License

MIT

Recommended Servers

playwright-mcp

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.

Official
Featured
TypeScript
Audiense Insights MCP Server

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.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

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.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
graphlit-mcp-server

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.

Official
Featured
TypeScript
Kagi MCP Server

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.

Official
Featured
Python
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

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.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured