Skip to content
Open
Show file tree
Hide file tree
Changes from 4 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
6 changes: 6 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,11 @@ CYPHER_ENDPOINT=http://localhost:11434/v1
MEMGRAPH_HOST=localhost
MEMGRAPH_PORT=7687
MEMGRAPH_HTTP_PORT=7444
# Memgraph authentication credentials
# Leave MEMGRAPH_USERNAME empty (or omit it) if your Memgraph instance doesn't require authentication
# If authentication is enabled, provide both username and password
# Common defaults: username=neo4j, password=password (or your custom credentials)
MEMGRAPH_USERNAME=
MEMGRAPH_PASSWORD=
LAB_PORT=3000
TARGET_REPO_PATH=.
2 changes: 2 additions & 0 deletions codebase_rag/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ class AppConfig(BaseSettings):
MEMGRAPH_HOST: str = "localhost"
MEMGRAPH_PORT: int = 7687
MEMGRAPH_HTTP_PORT: int = 7444
MEMGRAPH_USERNAME: str | None = None
MEMGRAPH_PASSWORD: str | None = None
LAB_PORT: int = 3000
MEMGRAPH_BATCH_SIZE: int = 1000

Expand Down
8 changes: 8 additions & 0 deletions codebase_rag/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -785,6 +785,8 @@ async def main_async(repo_path: str, batch_size: int) -> None:
host=settings.MEMGRAPH_HOST,
port=settings.MEMGRAPH_PORT,
batch_size=batch_size,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
) as ingestor:
console.print("[bold green]Successfully connected to Memgraph.[/bold green]")
console.print(
Expand Down Expand Up @@ -870,6 +872,8 @@ def start(
host=settings.MEMGRAPH_HOST,
port=settings.MEMGRAPH_PORT,
batch_size=effective_batch_size,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
) as ingestor:
if clean:
console.print("[bold yellow]Cleaning database...[/bold yellow]")
Expand Down Expand Up @@ -930,6 +934,8 @@ def export(
host=settings.MEMGRAPH_HOST,
port=settings.MEMGRAPH_PORT,
batch_size=effective_batch_size,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
) as ingestor:
console.print("[bold cyan]Exporting graph data...[/bold cyan]")
if not _export_graph_to_file(ingestor, output):
Expand Down Expand Up @@ -970,6 +976,8 @@ async def main_optimize_async(
host=settings.MEMGRAPH_HOST,
port=settings.MEMGRAPH_PORT,
batch_size=effective_batch_size,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
) as ingestor:
console.print("[bold green]Successfully connected to Memgraph.[/bold green]")

Expand Down
2 changes: 2 additions & 0 deletions codebase_rag/mcp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ def create_server() -> tuple[Server, MemgraphIngestor]:
host=settings.MEMGRAPH_HOST,
port=settings.MEMGRAPH_PORT,
batch_size=settings.MEMGRAPH_BATCH_SIZE,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
)

# CypherGenerator gets config from settings automatically
Expand Down
29 changes: 27 additions & 2 deletions codebase_rag/services/graph_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@
class MemgraphIngestor:
"""Handles all communication and query execution with the Memgraph database."""

def __init__(self, host: str, port: int, batch_size: int = 1000):
def __init__(
self,
host: str,
port: int,
batch_size: int = 1000,
username: str | None = None,
password: str | None = None,
):
self._host = host
self._port = port
self._username = username
self._password = password
if self._password is not None and self._username is None:
raise ValueError(
"A password was provided for Memgraph, but no username. Both are required for authentication."
)
if batch_size < 1:
raise ValueError("batch_size must be a positive integer")
self.batch_size = batch_size
Expand All @@ -32,7 +45,19 @@ def __init__(self, host: str, port: int, batch_size: int = 1000):

def __enter__(self) -> "MemgraphIngestor":
logger.info(f"Connecting to Memgraph at {self._host}:{self._port}...")
self.conn = mgclient.connect(host=self._host, port=self._port)
# Build connection parameters - only include username/password if provided
connect_params = {
"host": self._host,
"port": self._port,
}

# Only add authentication parameters if username is provided
# This allows connection to Memgraph instances without authentication
if self._username:
connect_params["username"] = self._username
connect_params["password"] = self._password if self._password else ""

self.conn = mgclient.connect(**connect_params)
self.conn.autocommit = True
logger.info("Successfully connected to Memgraph.")
return self
Expand Down
2 changes: 2 additions & 0 deletions realtime_updater.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,8 @@ def start_watcher(
host=host,
port=port,
batch_size=effective_batch_size,
username=settings.MEMGRAPH_USERNAME,
password=settings.MEMGRAPH_PASSWORD,
) as ingestor:
updater = GraphUpdater(ingestor, repo_path_obj, parsers, queries)

Expand Down