Merge branch 'main' into graphid-isolation

This commit is contained in:
Naseem Ali 2025-10-23 13:58:41 +03:00 committed by GitHub
commit 445ea2e45c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
14 changed files with 810 additions and 453 deletions

View file

@ -69,6 +69,14 @@ COPY ./server/graph_service ./graph_service
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev uv sync --frozen --no-dev
# Install falkordb if requested
ARG INSTALL_FALKORDB=false
RUN --mount=type=cache,target=/root/.cache/uv \
if [ "$INSTALL_FALKORDB" = "true" ]; then \
WHEEL=$(ls /tmp/*.whl | head -n 1); \
uv pip install "$WHEEL[falkordb]"; \
fi
# Change ownership to app user # Change ownership to app user
RUN chown -R app:app /app RUN chown -R app:app /app

View file

@ -77,6 +77,23 @@ We're excited to open-source Graphiti, believing its potential reaches far beyon
<a href="https://arxiv.org/abs/2501.13956"><img src="images/arxiv-screenshot.png" alt="Zep: A Temporal Knowledge Graph Architecture for Agent Memory" width="700px"></a> <a href="https://arxiv.org/abs/2501.13956"><img src="images/arxiv-screenshot.png" alt="Zep: A Temporal Knowledge Graph Architecture for Agent Memory" width="700px"></a>
</p> </p>
## Zep vs Graphiti
| Aspect | Zep | Graphiti |
|--------|-----|----------|
| **What they are** | Complete managed platform for AI memory | Open-source graph framework |
| **User & conversation management** | Built-in users, threads, and message storage | Build your own |
| **Retrieval & performance** | Pre-configured, production-ready retrieval with sub-200ms performance at scale | Custom implementation required; performance depends on your setup |
| **Developer tools** | Dashboard with graph visualization, debug logs, API logs; SDKs for Python, TypeScript, and Go | Build your own tools |
| **Enterprise features** | SLAs, support, security guarantees | Self-managed |
| **Deployment** | Fully managed or in your cloud | Self-hosted only |
### When to choose which
**Choose Zep** if you want a turnkey, enterprise-grade platform with security, performance, and support baked in.
**Choose Graphiti** if you want a flexible OSS core and you're comfortable building/operating the surrounding system.
## Why Graphiti? ## Why Graphiti?
Traditional RAG approaches often rely on batch processing and static data summarization, making them inefficient for Traditional RAG approaches often rely on batch processing and static data summarization, making them inefficient for
@ -239,6 +256,22 @@ The quickstart demonstrates:
The example is fully documented with clear explanations of each functionality and includes a comprehensive README with The example is fully documented with clear explanations of each functionality and includes a comprehensive README with
setup instructions and next steps. setup instructions and next steps.
### Running with Docker Compose
You can use Docker Compose to quickly start the required services:
- **Neo4j Docker:**
```sh
docker compose up
```
This will start the Neo4j Docker service and related components.
- **FalkorDB Docker:**
```sh
docker compose --profile falkordb up
```
This will start the FalkorDB Docker service and related components.
## MCP Server ## MCP Server
The `mcp_server` directory contains a Model Context Protocol (MCP) server implementation for Graphiti. This server The `mcp_server` directory contains a Model Context Protocol (MCP) server implementation for Graphiti. This server

View file

@ -1,5 +1,6 @@
services: services:
graph: graph:
profiles: [""]
build: build:
context: . context: .
ports: ports:
@ -24,8 +25,10 @@ services:
- NEO4J_USER=${NEO4J_USER} - NEO4J_USER=${NEO4J_USER}
- NEO4J_PASSWORD=${NEO4J_PASSWORD} - NEO4J_PASSWORD=${NEO4J_PASSWORD}
- PORT=8000 - PORT=8000
- db_backend=neo4j
neo4j: neo4j:
image: neo4j:5.26.2 image: neo4j:5.26.2
profiles: [""]
healthcheck: healthcheck:
test: test:
[ [
@ -44,5 +47,46 @@ services:
environment: environment:
- NEO4J_AUTH=${NEO4J_USER}/${NEO4J_PASSWORD} - NEO4J_AUTH=${NEO4J_USER}/${NEO4J_PASSWORD}
falkordb:
image: falkordb/falkordb:latest
profiles: ["falkordb"]
ports:
- "6379:6379"
volumes:
- falkordb_data:/data
environment:
- FALKORDB_ARGS=--port 6379 --cluster-enabled no
healthcheck:
test: ["CMD", "redis-cli", "-p", "6379", "ping"]
interval: 1s
timeout: 10s
retries: 10
start_period: 3s
graph-falkordb:
build:
args:
INSTALL_FALKORDB: "true"
context: .
profiles: ["falkordb"]
ports:
- "8001:8001"
depends_on:
falkordb:
condition: service_healthy
healthcheck:
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8001/healthcheck')"]
interval: 10s
timeout: 5s
retries: 3
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
- FALKORDB_HOST=falkordb
- FALKORDB_PORT=6379
- FALKORDB_DATABASE=default_db
- GRAPHITI_BACKEND=falkordb
- PORT=8001
- db_backend=falkordb
volumes: volumes:
neo4j_data: neo4j_data:
falkordb_data:

View file

@ -14,6 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
""" """
import datetime
import asyncio import asyncio
import logging import logging
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
@ -263,6 +264,28 @@ class FalkorDriver(GraphDriver):
return cloned return cloned
async def health_check(self) -> None:
"""Check FalkorDB connectivity by running a simple query."""
try:
await self.execute_query("MATCH (n) RETURN 1 LIMIT 1")
return None
except Exception as e:
print(f"FalkorDB health check failed: {e}")
raise
@staticmethod
def convert_datetimes_to_strings(obj):
if isinstance(obj, dict):
return {k: FalkorDriver.convert_datetimes_to_strings(v) for k, v in obj.items()}
elif isinstance(obj, list):
return [FalkorDriver.convert_datetimes_to_strings(item) for item in obj]
elif isinstance(obj, tuple):
return tuple(FalkorDriver.convert_datetimes_to_strings(item) for item in obj)
elif isinstance(obj, datetime):
return obj.isoformat()
else:
return obj
def sanitize(self, query: str) -> str: def sanitize(self, query: str) -> str:
""" """
Replace FalkorDB special characters with whitespace. Replace FalkorDB special characters with whitespace.

View file

@ -106,3 +106,12 @@ class Neo4jDriver(GraphDriver):
for query in index_queries for query in index_queries
] ]
) )
async def health_check(self) -> None:
"""Check Neo4j connectivity by running the driver's verify_connectivity method."""
try:
await self.client.verify_connectivity()
return None
except Exception as e:
print(f"Neo4j health check failed: {e}")
raise

View file

@ -1,11 +1,20 @@
# Graphiti MCP Server Environment Configuration # Graphiti MCP Server Environment Configuration
# Neo4j Database Configuration # Database Configuration
# Choose between 'neo4j' or 'falkordb'
DATABASE_TYPE=falkordb
# These settings are used to connect to your Neo4j database # These settings are used to connect to your Neo4j database
NEO4J_URI=bolt://localhost:7687 NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j NEO4J_USER=neo4j
NEO4J_PASSWORD=demodemo NEO4J_PASSWORD=demodemo
# These settings are used to connect to your FalkorDB database
FALKORDB_PORT=6379
FALKORDB_HOST=localhost
FALKORDB_USER=
FALKORDB_PASSWORD=
# OpenAI API Configuration # OpenAI API Configuration
# Required for LLM operations # Required for LLM operations
OPENAI_API_KEY=your_openai_api_key_here OPENAI_API_KEY=your_openai_api_key_here

View file

@ -30,8 +30,13 @@ RUN groupadd -r app && useradd -r -d /app -g app app
COPY pyproject.toml uv.lock ./ COPY pyproject.toml uv.lock ./
# Install dependencies first (better layer caching) # Install dependencies first (better layer caching)
ARG INSTALL_FALKORDB=false
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-dev if [ "$INSTALL_FALKORDB" = "true" ]; then \
uv sync --frozen --no-dev --extra falkordb; \
else \
uv sync --frozen --no-dev; \
fi
# Copy application code # Copy application code
COPY graphiti_mcp_server.py ./ COPY graphiti_mcp_server.py ./
@ -43,7 +48,7 @@ RUN chown -Rv app:app /app
USER app USER app
# Expose port # Expose port
EXPOSE 8000 EXPOSE $PORT
# Command to run the application # Command to run the application
CMD ["uv", "run", "graphiti_mcp_server.py"] CMD ["uv", "run", "graphiti_mcp_server.py"]

View file

@ -82,11 +82,21 @@ uv sync
## Configuration ## Configuration
The server uses the following environment variables: The server supports both Neo4j and FalkorDB as database backends. Use the `DATABASE_TYPE` environment variable to choose between them.
#### Neo4j Configuration (default)
- `NEO4J_URI`: URI for the Neo4j database (default: `bolt://localhost:7687`) - `NEO4J_URI`: URI for the Neo4j database (default: `bolt://localhost:7687`)
- `NEO4J_USER`: Neo4j username (default: `neo4j`) - `NEO4J_USER`: Neo4j username (default: `neo4j`)
- `NEO4J_PASSWORD`: Neo4j password (default: `demodemo`) - `NEO4J_PASSWORD`: Neo4j password (default: `demodemo`)
#### FalkorDB Configuration
- `DATABASE_TYPE`: Set to `falkordb`
- `FALKORDB_HOST`: FalkorDB host (default: `localhost`)
- `FALKORDB_PORT`: FalkorDB port (default: `6379`)
- `FALKORDB_USERNAME`: FalkorDB username (optional)
- `FALKORDB_PASSWORD`: FalkorDB password (optional)
- `OPENAI_API_KEY`: OpenAI API key (required for LLM operations) - `OPENAI_API_KEY`: OpenAI API key (required for LLM operations)
- `OPENAI_BASE_URL`: Optional base URL for OpenAI API - `OPENAI_BASE_URL`: Optional base URL for OpenAI API
- `MODEL_NAME`: OpenAI model name to use for LLM operations. - `MODEL_NAME`: OpenAI model name to use for LLM operations.
@ -115,7 +125,7 @@ uv run graphiti_mcp_server.py
With options: With options:
```bash ```bash
uv run graphiti_mcp_server.py --model gpt-4.1-mini --transport sse uv run graphiti_mcp_server.py --model gpt-4.1-mini --transport sse --database-type falkordb --port 8001
``` ```
Available arguments: Available arguments:
@ -124,6 +134,7 @@ Available arguments:
- `--small-model`: Overrides the `SMALL_MODEL_NAME` environment variable. - `--small-model`: Overrides the `SMALL_MODEL_NAME` environment variable.
- `--temperature`: Overrides the `LLM_TEMPERATURE` environment variable. - `--temperature`: Overrides the `LLM_TEMPERATURE` environment variable.
- `--transport`: Choose the transport method (sse or stdio, default: sse) - `--transport`: Choose the transport method (sse or stdio, default: sse)
- `--database-type`: Choose database backend (neo4j or falkordb, default: neo4j)
- `--group-id`: Set a namespace for the graph (optional). If not provided, defaults to "default". - `--group-id`: Set a namespace for the graph (optional). If not provided, defaults to "default".
- `--destroy-graph`: If set, destroys all Graphiti graphs on startup. - `--destroy-graph`: If set, destroys all Graphiti graphs on startup.
- `--use-custom-entities`: Enable entity extraction using the predefined ENTITY_TYPES - `--use-custom-entities`: Enable entity extraction using the predefined ENTITY_TYPES
@ -175,11 +186,30 @@ The Docker Compose setup includes a Neo4j container with the following default c
- URI: `bolt://neo4j:7687` (from within the Docker network) - URI: `bolt://neo4j:7687` (from within the Docker network)
- Memory settings optimized for development use - Memory settings optimized for development use
To run only Neo4j with its MCP server:
```bash
docker compose up
```
- Neo4j MCP server on port 8000
#### FalkorDB Configuration
The Docker Compose setup includes a FalkorDB container with the following default configuration:
- Host: `falkordb`
- Port: `6379`
- No authentication by default
To run only FalkorDB with its MCP server:
```bash
docker compose --profile falkordb up
```
- FalkorDB MCP server on port 8001
#### Running with Docker Compose #### Running with Docker Compose
A Graphiti MCP container is available at: `zepai/knowledge-graph-mcp`. The latest build of this container is used by the Compose setup below. A Graphiti MCP container is available at: `zepai/knowledge-graph-mcp`. The latest build of this container is used by the Compose setup below.
Start the services using Docker Compose: Start the services using Docker Compose For Neo4j:
```bash ```bash
docker compose up docker compose up
@ -191,13 +221,25 @@ Or if you're using an older version of Docker Compose:
docker-compose up docker-compose up
``` ```
This will start both the Neo4j database and the Graphiti MCP server. The Docker setup: For FalkorDB:
```bash
docker compose --profile falkordb up
```
Or if you're using an older version of Docker Compose:
```bash
docker-compose --profile falkordb up
```
This will start the database(s) and the Graphiti MCP server(s). The Docker setup:
- Uses `uv` for package management and running the server - Uses `uv` for package management and running the server
- Installs dependencies from the `pyproject.toml` file - Installs dependencies from the `pyproject.toml` file
- Connects to the Neo4j container using the environment variables - Connects to the database container using the environment variables
- Exposes the server on port 8000 for HTTP-based SSE transport - Exposes the server on port 8000 (Neo4j) or 8001 (FalkorDB) for HTTP-based SSE transport
- Includes a healthcheck for Neo4j to ensure it's fully operational before starting the MCP server - Includes healthchecks to ensure databases are fully operational before starting the MCP server
## Integrating with MCP Clients ## Integrating with MCP Clients

View file

@ -0,0 +1,8 @@
{
"mcpServers": {
"graphiti": {
"transport": "sse",
"url": "http://localhost:8001/sse"
}
}
}

View file

@ -1,5 +1,6 @@
services: services:
neo4j: neo4j:
profiles: [""]
image: neo4j:5.26.0 image: neo4j:5.26.0
ports: ports:
- "7474:7474" # HTTP - "7474:7474" # HTTP
@ -19,7 +20,8 @@ services:
retries: 5 retries: 5
start_period: 30s start_period: 30s
graphiti-mcp: graphiti-mcp-neo4j:
profiles: [""]
image: zepai/knowledge-graph-mcp:latest image: zepai/knowledge-graph-mcp:latest
build: build:
context: . context: .
@ -31,6 +33,8 @@ services:
neo4j: neo4j:
condition: service_healthy condition: service_healthy
environment: environment:
- PORT=8000
- DATABASE_TYPE=neo4j
- NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687} - NEO4J_URI=${NEO4J_URI:-bolt://neo4j:7687}
- NEO4J_USER=${NEO4J_USER:-neo4j} - NEO4J_USER=${NEO4J_USER:-neo4j}
- NEO4J_PASSWORD=${NEO4J_PASSWORD:-demodemo} - NEO4J_PASSWORD=${NEO4J_PASSWORD:-demodemo}
@ -42,6 +46,50 @@ services:
- "8000:8000" # Expose the MCP server via HTTP for SSE transport - "8000:8000" # Expose the MCP server via HTTP for SSE transport
command: ["uv", "run", "graphiti_mcp_server.py", "--transport", "sse"] command: ["uv", "run", "graphiti_mcp_server.py", "--transport", "sse"]
falkordb:
profiles: ["falkordb"]
image: falkordb/falkordb:latest
ports:
- "6379:6379"
command: ["falkordb-server", "--loadmodule", "/FalkorDB/bin/src/falkordb.so"]
volumes:
- falkordb_data:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s
graphiti-mcp-falkordb:
profiles: ["falkordb"]
build:
args:
INSTALL_FALKORDB: "true"
context: .
dockerfile: Dockerfile
env_file:
- path: .env
required: false
depends_on:
falkordb:
condition: service_healthy
environment:
- PORT=8001
- DATABASE_TYPE=falkordb
- FALKORDB_HOST=falkordb
- FALKORDB_PORT=6379
- FALKORDB_USER=${FALKORDB_USER:-}
- FALKORDB_PASSWORD=${FALKORDB_PASSWORD:-}
- OPENAI_API_KEY=${OPENAI_API_KEY}
- MODEL_NAME=${MODEL_NAME}
- PATH=/root/.local/bin:${PATH}
- SEMAPHORE_LIMIT=${SEMAPHORE_LIMIT:-10}
ports:
- "8001:8001" # Expose the MCP server via HTTP for SSE transport
command: ["uv", "run", "graphiti_mcp_server.py", "--transport", "sse"]
volumes: volumes:
neo4j_data: neo4j_data:
neo4j_logs: neo4j_logs:
falkordb_data:

View file

@ -10,15 +10,17 @@ import os
import sys import sys
from collections.abc import Callable from collections.abc import Callable
from datetime import datetime, timezone from datetime import datetime, timezone
from typing import Any, TypedDict, cast from typing import Any, cast
from azure.identity import DefaultAzureCredential, get_bearer_token_provider from azure.identity import DefaultAzureCredential, get_bearer_token_provider
from dotenv import load_dotenv from dotenv import load_dotenv
from mcp.server.fastmcp import FastMCP from mcp.server.fastmcp import FastMCP
from openai import AsyncAzureOpenAI from openai import AsyncAzureOpenAI
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
from typing_extensions import TypedDict
from graphiti_core import Graphiti from graphiti_core import Graphiti
from graphiti_core.driver.neo4j_driver import Neo4jDriver
from graphiti_core.edges import EntityEdge from graphiti_core.edges import EntityEdge
from graphiti_core.embedder.azure_openai import AzureOpenAIEmbedderClient from graphiti_core.embedder.azure_openai import AzureOpenAIEmbedderClient
from graphiti_core.embedder.client import EmbedderClient from graphiti_core.embedder.client import EmbedderClient
@ -465,6 +467,21 @@ class Neo4jConfig(BaseModel):
password=os.environ.get('NEO4J_PASSWORD', 'password'), password=os.environ.get('NEO4J_PASSWORD', 'password'),
) )
class FalkorConfig(BaseModel):
"""Configuration for FalkorDB database connection."""
host: str = 'localhost'
port: int = 6379
user: str = ''
password: str = ''
@classmethod
def from_env(cls) -> 'FalkorConfig':
host = os.environ.get('FALKORDB_HOST', 'localhost')
port = int(os.environ.get('FALKORDB_PORT', 6379))
user = os.environ.get('FALKORDB_USER', '')
password = os.environ.get('FALKORDB_PASSWORD', '')
return cls(host=host, port=port, user=user, password=password)
class GraphitiConfig(BaseModel): class GraphitiConfig(BaseModel):
"""Configuration for Graphiti client. """Configuration for Graphiti client.
@ -475,18 +492,35 @@ class GraphitiConfig(BaseModel):
llm: GraphitiLLMConfig = Field(default_factory=GraphitiLLMConfig) llm: GraphitiLLMConfig = Field(default_factory=GraphitiLLMConfig)
embedder: GraphitiEmbedderConfig = Field(default_factory=GraphitiEmbedderConfig) embedder: GraphitiEmbedderConfig = Field(default_factory=GraphitiEmbedderConfig)
neo4j: Neo4jConfig = Field(default_factory=Neo4jConfig) neo4j: Neo4jConfig = Field(default_factory=Neo4jConfig)
falkordb: FalkorConfig = Field(default_factory=FalkorConfig)
group_id: str | None = None group_id: str | None = None
use_custom_entities: bool = False use_custom_entities: bool = False
destroy_graph: bool = False destroy_graph: bool = False
database_type: str = 'neo4j'
@classmethod @classmethod
def from_env(cls) -> 'GraphitiConfig': def from_env(cls) -> 'GraphitiConfig':
"""Create a configuration instance from environment variables.""" """Create a configuration instance from environment variables."""
return cls( db_type = os.environ.get('DATABASE_TYPE')
llm=GraphitiLLMConfig.from_env(), if not db_type:
embedder=GraphitiEmbedderConfig.from_env(), raise ValueError('DATABASE_TYPE environment variable must be set (e.g., "neo4j" or "falkordb")')
neo4j=Neo4jConfig.from_env(), if db_type == 'neo4j':
) return cls(
llm=GraphitiLLMConfig.from_env(),
embedder=GraphitiEmbedderConfig.from_env(),
neo4j=Neo4jConfig.from_env(),
database_type=db_type,
)
elif db_type == 'falkordb':
return cls(
llm=GraphitiLLMConfig.from_env(),
embedder=GraphitiEmbedderConfig.from_env(),
falkordb=FalkorConfig.from_env(),
database_type=db_type,
)
else:
raise ValueError(f'Unsupported DATABASE_TYPE: {db_type}')
@classmethod @classmethod
def from_cli_and_env(cls, args: argparse.Namespace) -> 'GraphitiConfig': def from_cli_and_env(cls, args: argparse.Namespace) -> 'GraphitiConfig':
@ -587,13 +621,38 @@ async def initialize_graphiti():
if not config.neo4j.uri or not config.neo4j.user or not config.neo4j.password: if not config.neo4j.uri or not config.neo4j.user or not config.neo4j.password:
raise ValueError('NEO4J_URI, NEO4J_USER, and NEO4J_PASSWORD must be set') raise ValueError('NEO4J_URI, NEO4J_USER, and NEO4J_PASSWORD must be set')
# Validate FalkorDB configuration
if config.database_type == 'falkordb' and (not config.falkordb.host or not config.falkordb.port):
raise ValueError('FALKORDB_HOST and FALKORDB_PORT must be set for FalkorDB')
embedder_client = config.embedder.create_client() embedder_client = config.embedder.create_client()
# Construct the driver based on the database_type
driver = None
if config.database_type == 'neo4j':
driver = Neo4jDriver(
uri=config.neo4j.uri,
user=config.neo4j.user,
password=config.neo4j.password,
)
elif config.database_type == 'falkordb':
from graphiti_core.driver.falkordb_driver import FalkorDriver
host = config.falkordb.host if hasattr(config.falkordb, 'host') else 'localhost'
port = int(config.falkordb.port) if hasattr(config.falkordb, 'port') else 6379
username = config.falkordb.user or None
password = config.falkordb.password or None
driver = FalkorDriver(
host=host,
port=port,
username=username,
password=password,
)
else:
raise ValueError(f'Unsupported database type: {config.database_type}')
# Initialize Graphiti client # Initialize Graphiti client
graphiti_client = Graphiti( graphiti_client = Graphiti(
uri=config.neo4j.uri, graph_driver=driver,
user=config.neo4j.user,
password=config.neo4j.password,
llm_client=llm_client, llm_client=llm_client,
embedder=embedder_client, embedder=embedder_client,
max_coroutines=SEMAPHORE_LIMIT, max_coroutines=SEMAPHORE_LIMIT,
@ -606,7 +665,7 @@ async def initialize_graphiti():
# Initialize the graph database with Graphiti's indices # Initialize the graph database with Graphiti's indices
await graphiti_client.build_indices_and_constraints() await graphiti_client.build_indices_and_constraints()
logger.info('Graphiti client initialized successfully') logger.info(f'Graphiti client initialized successfully with {config.database_type}')
# Log configuration details for transparency # Log configuration details for transparency
if llm_client: if llm_client:
@ -616,6 +675,7 @@ async def initialize_graphiti():
logger.info('No LLM client configured - entity extraction will be limited') logger.info('No LLM client configured - entity extraction will be limited')
logger.info(f'Using group_id: {config.group_id}') logger.info(f'Using group_id: {config.group_id}')
logger.info(f'Using database type: {config.database_type}')
logger.info( logger.info(
f'Custom entity extraction: {"enabled" if config.use_custom_entities else "disabled"}' f'Custom entity extraction: {"enabled" if config.use_custom_entities else "disabled"}'
) )
@ -1131,7 +1191,7 @@ async def clear_graph() -> SuccessResponse | ErrorResponse:
@mcp.resource('http://graphiti/status') @mcp.resource('http://graphiti/status')
async def get_status() -> StatusResponse: async def get_status() -> StatusResponse:
"""Get the status of the Graphiti MCP server and Neo4j connection.""" """Get the status of the Graphiti MCP server and database connection."""
global graphiti_client global graphiti_client
if graphiti_client is None: if graphiti_client is None:
@ -1145,14 +1205,14 @@ async def get_status() -> StatusResponse:
client = cast(Graphiti, graphiti_client) client = cast(Graphiti, graphiti_client)
# Test database connection # Test database connection
await client.driver.client.verify_connectivity() # type: ignore await client.driver.health_check() # type: ignore # type: ignore
return StatusResponse( return StatusResponse(
status='ok', message='Graphiti MCP server is running and connected to Neo4j' status='ok', message=f'Graphiti MCP server is running and connected to {config.database_type}'
) )
except Exception as e: except Exception as e:
error_msg = str(e) error_msg = str(e)
logger.error(f'Error checking Neo4j connection: {error_msg}') logger.error(f'Error checking {config.database_type} connection: {error_msg}')
return StatusResponse( return StatusResponse(
status='error', status='error',
message=f'Graphiti MCP server is running but Neo4j connection failed: {error_msg}', message=f'Graphiti MCP server is running but Neo4j connection failed: {error_msg}',
@ -1200,6 +1260,17 @@ async def initialize_server() -> MCPConfig:
default=os.environ.get('MCP_SERVER_HOST'), default=os.environ.get('MCP_SERVER_HOST'),
help='Host to bind the MCP server to (default: MCP_SERVER_HOST environment variable)', help='Host to bind the MCP server to (default: MCP_SERVER_HOST environment variable)',
) )
parser.add_argument(
'--port',
type=int,
default=int(os.environ.get('PORT', 8000)),
help='Port to run the MCP server on (default: 8000 or value of PORT env variable)',
)
parser.add_argument(
'--database-type',
choices=['neo4j', 'falkordb'],
help='Type of database to use (default: neo4j)',
)
args = parser.parse_args() args = parser.parse_args()
@ -1226,6 +1297,11 @@ async def initialize_server() -> MCPConfig:
# Set MCP server host from CLI or env # Set MCP server host from CLI or env
mcp.settings.host = args.host mcp.settings.host = args.host
if args.port:
logger.info(f'Setting MCP server port to: {args.port}')
# Set MCP server port from CLI or env
mcp.settings.port = args.port
# Return MCP configuration # Return MCP configuration
return MCPConfig.from_cli(args) return MCPConfig.from_cli(args)

View file

@ -7,7 +7,9 @@ requires-python = ">=3.10,<4"
dependencies = [ dependencies = [
"mcp>=1.5.0", "mcp>=1.5.0",
"openai>=1.68.2", "openai>=1.68.2",
"graphiti-core>=0.14.0", "graphiti-core==0.18.8",
"azure-identity>=1.21.0", "azure-identity>=1.21.0",
"graphiti-core",
] ]
[project.optional-dependencies]
falkordb = ["falkordb>=1.1.2,<2.0.0"]

892
mcp_server/uv.lock generated

File diff suppressed because it is too large Load diff

View file

@ -423,6 +423,14 @@
"created_at": "2025-10-15T16:29:33Z", "created_at": "2025-10-15T16:29:33Z",
"repoId": 840056306, "repoId": 840056306,
"pullRequestNo": 1005 "pullRequestNo": 1005
},
{
"name": "dontang97",
"id": 88384441,
"comment_id": 3431443627,
"created_at": "2025-10-22T09:52:01Z",
"repoId": 840056306,
"pullRequestNo": 1020
} }
] ]
} }