Skip to content

mcp-neo4j-memory SSE Support, docker stdio/sse images, extensive test coverage #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions servers/mcp-neo4j-memory/.dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,30 @@ wheels/

# Virtual Environment
venv/
env/
ENV/
env.bak/
venv.bak/

# IDE
.idea/
.vscode/
.idea/
*.swp
*.swo
*~

# Testing
.pytest_cache/
.coverage
htmlcov/
.tox/
.nox/

# Development tools
.mypy_cache/
.pyright/

# Git
.git
.git/
.gitignore

# Docker
Expand All @@ -48,4 +61,4 @@ docs/
# Tests
tests/
test/
testing/
testing/
28 changes: 0 additions & 28 deletions servers/mcp-neo4j-memory/Dockerfile

This file was deleted.

71 changes: 64 additions & 7 deletions servers/mcp-neo4j-memory/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ Results in Claude calling the create_entities and create_relations tools.

## 📦 Components

### 🔌 Protocol Support

This MCP server supports multiple protocols:

- **stdio** - Default mode for Claude Desktop and MCP clients
- **SSE (Server-Sent Events)** - Real-time streaming mode for streaming applications

### 🔧 Tools

The server offers these core tools:
Expand Down Expand Up @@ -149,6 +156,7 @@ Alternatively, you can set environment variables:

### 🐳 Using with Docker

**stdio mode (default):**
```json
"mcpServers": {
"neo4j": {
Expand All @@ -159,12 +167,28 @@ Alternatively, you can set environment variables:
"-e", "NEO4J_URL=neo4j+s://xxxx.databases.neo4j.io",
"-e", "NEO4J_USERNAME=<your-username>",
"-e", "NEO4J_PASSWORD=<your-password>",
"mcp/neo4j-memory:0.1.4"
"mcp-neo4j-memory:latest"
]
}
}
```

**SSE mode (for streaming applications):**
```bash
# Build SSE image using unified Dockerfile
./scripts/build.sh sse

# Run SSE server
docker run -p 3001:3001 \
-e NEO4J_URL="neo4j+s://xxxx.databases.neo4j.io" \
-e NEO4J_USERNAME="<your-username>" \
-e NEO4J_PASSWORD="<your-password>" \
mcp-neo4j-memory:sse

# Test SSE endpoint
curl http://localhost:3001/sse
```

## 🚀 Development

### 📦 Prerequisites
Expand Down Expand Up @@ -194,21 +218,54 @@ source .venv/bin/activate # On Unix/macOS

# Install dependencies including dev dependencies
uv pip install -e ".[dev]"

# Set environment for tests
set NEO4J_URL=neo4j://localhost:7687
set NEO4J_USERNAME=neo4j
set NEO4J_PASSWORD=testpassword

# Run neo4j and run tests
docker run -d --name neo4j-test -p 7687:7687 -p 7474:7474 -e NEO4J_AUTH=neo4j/testpassword neo4j:latest
# Run tests
uv run pytest
```

### 🐳 Docker
### 🐳 Development with Docker
```bash
# 1. Build and run tests, clean
./scripts/test.sh build
./scripts/test.sh
./scripts/test.sh clean

# 2. Build Docker images
./scripts/build.sh all

# 3. Publish Docker images
./scripts/publish.sh
```

Build and run the Docker container:
### 🐳 Docker build images

Build and run different variants using the consolidated build system:

```bash
# Build the image
docker build -t mcp/neo4j-memory:latest .
# Build specific variants using the unified Dockerfile
./scripts/build.sh stdio # stdio-only (default)
./scripts/build.sh sse # SSE streaming server
./scripts/build.sh all # All variants (default)

# Run the container
# Run stdio container (default)
docker run -e NEO4J_URL="neo4j+s://xxxx.databases.neo4j.io" \
-e NEO4J_USERNAME="your-username" \
-e NEO4J_PASSWORD="your-password" \
mcp/neo4j-memory:latest
mcp-neo4j-memory:latest

# Run SSE server
docker run -p 3001:3001 \
-e NEO4J_URL="neo4j+s://xxxx.databases.neo4j.io" \
-e NEO4J_USERNAME="your-username" \
-e NEO4J_PASSWORD="your-password" \
mcp-neo4j-memory:sse
```

## 📄 License
Expand Down
18 changes: 18 additions & 0 deletions servers/mcp-neo4j-memory/README_QUICKSTART.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Neo4j Memory MCP Server Quick Start

## Installation, Testing

```bash
# 1. Build and run tests, clean
./scripts/test.sh build
./scripts/test.sh
./scripts/test.sh clean

# 2. Build Docker images
./scripts/build.sh all

# 2. Publish Docker images
./scripts/publish.sh
```

## 🔧 See Usage examples in `examples` directory
155 changes: 155 additions & 0 deletions servers/mcp-neo4j-memory/docker/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Master Dockerfile with multi-stage build for MCP Neo4j Memory server
# This provides a shared build stage for all protocol-specific images

# ============================================================================
# BUILD STAGE - Shared across all protocol variants
# ============================================================================
FROM python:3.11-alpine as builder

# Set working directory
WORKDIR /app

# Copy dependency files first for better layer caching
COPY pyproject.toml uv.lock* ./

# Copy README.md as it's referenced in pyproject.toml
COPY README.md ./

# Copy source code
COPY src/ ./src/
# Install build dependencies, build everything, then remove build deps in one layer
RUN apk add --no-cache --virtual .build-deps build-base && \
pip install --no-cache-dir uv && \
(uv sync --frozen --no-dev || pip install --no-cache-dir -e .) && \
pip install --no-cache-dir -e . && \
apk del .build-deps


# ============================================================================
# RUNTIME BASE - Shared runtime configuration
# ============================================================================
FROM python:3.11-alpine as runtime-base

# Create non-root user for security
RUN addgroup -S mcp && adduser -S -G mcp mcp

# Set working directory
WORKDIR /app

# Copy installed packages from builder (this is the main optimization)
COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
COPY --from=builder /usr/local/bin/mcp-neo4j-memory /usr/local/bin
COPY --from=builder /app/src /app/src
COPY --from=builder /app/README.md /app/

# Create directory for potential data persistence
RUN mkdir -p /app/data && chown -R mcp:mcp /app

# Clean up caches and build artifacts
RUN rm -rf /root/.cache /tmp/* /var/cache/apk/* && \
find /usr/local -name "*.pyc" -delete && \
find /usr/local -name "__pycache__" -type d -exec rm -rf {} + || true

# Switch to non-root user
USER mcp

# Set PYTHONPATH to ensure module imports work
ENV PYTHONPATH=/app/src

# Common environment variables
ENV NEO4J_URL="bolt://host.docker.internal:7687"
ENV NEO4J_USERNAME="neo4j"
ENV NEO4J_PASSWORD="password"
ENV NEO4J_DATABASE="neo4j"

# Default command (overridden by specific variants)
CMD ["echo", "Base image - specify target variant"]

# ============================================================================
# STDIO VARIANT - Default MCP protocol
# ============================================================================
FROM runtime-base as stdio

# stdio-specific environment
ENV MCP_MODE="stdio"

# Health check for stdio mode (check package import)
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD python -c "import mcp_neo4j_memory; print('OK')" || exit 1

# stdio command
CMD ["sh", "-c", "mcp-neo4j-memory --mode ${MCP_MODE} --db-url ${NEO4J_URL} --username ${NEO4J_USERNAME} --password ${NEO4J_PASSWORD} --database ${NEO4J_DATABASE}"]

# Labels for stdio
LABEL maintainer="MCP Neo4j Memory"
LABEL description="stdio-only MCP server for Neo4j knowledge graph memory"
LABEL protocol="stdio"
LABEL variant="stdio"

# ============================================================================
# SSE VARIANT - Server-Sent Events protocol
# ============================================================================
FROM runtime-base as sse

# SSE-specific environment
ENV MCP_MODE="sse"
ENV MCP_SERVER_HOST="0.0.0.0"
ENV MCP_SERVER_PORT="3001"

# Expose SSE port
EXPOSE 3001

# Install curl for health checks
USER root
RUN apk add --no-cache curl && rm -rf /var/cache/apk/*
USER mcp

# Health check for SSE mode
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3001/health || exit 1

# SSE command
CMD ["sh", "-c", "mcp-neo4j-memory --mode ${MCP_MODE} --host ${MCP_SERVER_HOST} --port ${MCP_SERVER_PORT} --db-url ${NEO4J_URL} --username ${NEO4J_USERNAME} --password ${NEO4J_PASSWORD} --database ${NEO4J_DATABASE}"]

# Labels for SSE
LABEL maintainer="MCP Neo4j Memory"
LABEL description="Server-Sent Events MCP server for Neo4j knowledge graph memory"
LABEL protocol="sse"
LABEL variant="sse"

# ============================================================================
# TEST VARIANT - Test environment with all dependencies
# ============================================================================
FROM runtime-base as test

# Test-specific environment
ENV MCP_MODE="stdio"
ENV PYTHONPATH=/app/src

# Install test dependencies
USER root
RUN apk add --no-cache curl && rm -rf /var/cache/apk/*

# Install test packages in one layer to minimize size impact
RUN pip install --no-cache-dir \
pytest \
pytest-cov \
pytest-asyncio \
pytest-xdist \
pytest-timeout \
pytest-mock \
httpx \
aiohttp \
requests && \
rm -rf /root/.cache

USER mcp

# Test command (runs comprehensive test suite)
CMD ["python", "tests/run_all_tests.py"]

# Labels for test
LABEL maintainer="MCP Neo4j Memory"
LABEL description="Test environment for MCP Neo4j Memory with all dependencies"
LABEL protocol="all"
LABEL variant="test"
Loading