From bd49dd7bb526fdeef2319022d45d1fd166b87982 Mon Sep 17 00:00:00 2001 From: Daulet Amirkhanov Date: Thu, 9 Oct 2025 14:01:28 +0100 Subject: [PATCH] Configure `cognee-cli -ui` mcp to connect to cognee backend --- cognee-mcp/Dockerfile | 3 ++ cognee-mcp/entrypoint.sh | 89 +++++++++++++++++++++++++++------------- cognee-mcp/src/server.py | 4 +- cognee/api/v1/ui/ui.py | 46 +++++++++++++++------ 4 files changed, 98 insertions(+), 44 deletions(-) diff --git a/cognee-mcp/Dockerfile b/cognee-mcp/Dockerfile index 68dce1844..6608102c8 100644 --- a/cognee-mcp/Dockerfile +++ b/cognee-mcp/Dockerfile @@ -65,6 +65,9 @@ ENV PYTHONUNBUFFERED=1 ENV MCP_LOG_LEVEL=DEBUG ENV PYTHONPATH=/app +# Add labels for API mode usage +LABEL org.opencontainers.image.description="Cognee MCP Server with API mode support" + # Use the application name from pyproject.toml for normal operation # For testing, we'll override this with a direct command ENTRYPOINT ["/app/entrypoint.sh"] diff --git a/cognee-mcp/entrypoint.sh b/cognee-mcp/entrypoint.sh index e3ff849e0..2f122bbfd 100644 --- a/cognee-mcp/entrypoint.sh +++ b/cognee-mcp/entrypoint.sh @@ -14,61 +14,94 @@ HTTP_PORT=${HTTP_PORT:-8000} echo "Debug port: $DEBUG_PORT" echo "HTTP port: $HTTP_PORT" -# Run Alembic migrations with proper error handling. -# Note on UserAlreadyExists error handling: -# During database migrations, we attempt to create a default user. If this user -# already exists (e.g., from a previous deployment or migration), it's not a -# critical error and shouldn't prevent the application from starting. This is -# different from other migration errors which could indicate database schema -# inconsistencies and should cause the startup to fail. This check allows for -# smooth redeployments and container restarts while maintaining data integrity. -echo "Running database migrations..." +# Check if API mode is enabled +if [ -n "$API_URL" ]; then + echo "API mode enabled: $API_URL" + echo "Skipping database migrations (API server handles its own database)" +else + echo "Direct mode: Using local cognee instance" + # Run Alembic migrations with proper error handling. + # Note on UserAlreadyExists error handling: + # During database migrations, we attempt to create a default user. If this user + # already exists (e.g., from a previous deployment or migration), it's not a + # critical error and shouldn't prevent the application from starting. This is + # different from other migration errors which could indicate database schema + # inconsistencies and should cause the startup to fail. This check allows for + # smooth redeployments and container restarts while maintaining data integrity. + echo "Running database migrations..." -MIGRATION_OUTPUT=$(alembic upgrade head) -MIGRATION_EXIT_CODE=$? + MIGRATION_OUTPUT=$(alembic upgrade head) + MIGRATION_EXIT_CODE=$? -if [[ $MIGRATION_EXIT_CODE -ne 0 ]]; then - if [[ "$MIGRATION_OUTPUT" == *"UserAlreadyExists"* ]] || [[ "$MIGRATION_OUTPUT" == *"User default_user@example.com already exists"* ]]; then - echo "Warning: Default user already exists, continuing startup..." - else - echo "Migration failed with unexpected error." - exit 1 + if [[ $MIGRATION_EXIT_CODE -ne 0 ]]; then + if [[ "$MIGRATION_OUTPUT" == *"UserAlreadyExists"* ]] || [[ "$MIGRATION_OUTPUT" == *"User default_user@example.com already exists"* ]]; then + echo "Warning: Default user already exists, continuing startup..." + else + echo "Migration failed with unexpected error." + exit 1 + fi fi -fi -echo "Database migrations done." + echo "Database migrations done." +fi echo "Starting Cognee MCP Server with transport mode: $TRANSPORT_MODE" # Add startup delay to ensure DB is ready sleep 2 +# Build API arguments if API_URL is set +API_ARGS="" +if [ -n "$API_URL" ]; then + # Handle localhost in API_URL - convert to host-accessible address + if echo "$API_URL" | grep -q "localhost" || echo "$API_URL" | grep -q "127.0.0.1"; then + echo "⚠️ Warning: API_URL contains localhost/127.0.0.1" + echo " Original: $API_URL" + + # Try to use host.docker.internal (works on Mac/Windows and recent Linux with Docker Desktop) + FIXED_API_URL=$(echo "$API_URL" | sed 's/localhost/host.docker.internal/g' | sed 's/127\.0\.0\.1/host.docker.internal/g') + + echo " Converted to: $FIXED_API_URL" + echo " This will work on Mac/Windows/Docker Desktop." + echo " On Linux without Docker Desktop, you may need to:" + echo " - Use --network host, OR" + echo " - Set API_URL=http://172.17.0.1:8000 (Docker bridge IP)" + + API_URL="$FIXED_API_URL" + fi + + API_ARGS="--api-url $API_URL" + if [ -n "$API_TOKEN" ]; then + API_ARGS="$API_ARGS --api-token $API_TOKEN" + fi +fi + # Modified startup with transport mode selection and error handling if [ "$ENVIRONMENT" = "dev" ] || [ "$ENVIRONMENT" = "local" ]; then if [ "$DEBUG" = "true" ]; then echo "Waiting for the debugger to attach..." if [ "$TRANSPORT_MODE" = "sse" ]; then - exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS elif [ "$TRANSPORT_MODE" = "http" ]; then - exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS else - exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport stdio --no-migration + exec python -m debugpy --wait-for-client --listen 0.0.0.0:$DEBUG_PORT -m cognee-mcp --transport stdio --no-migration $API_ARGS fi else if [ "$TRANSPORT_MODE" = "sse" ]; then - exec cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS elif [ "$TRANSPORT_MODE" = "http" ]; then - exec cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS else - exec cognee-mcp --transport stdio --no-migration + exec cognee-mcp --transport stdio --no-migration $API_ARGS fi fi else if [ "$TRANSPORT_MODE" = "sse" ]; then - exec cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec cognee-mcp --transport sse --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS elif [ "$TRANSPORT_MODE" = "http" ]; then - exec cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration + exec cognee-mcp --transport http --host 0.0.0.0 --port $HTTP_PORT --no-migration $API_ARGS else - exec cognee-mcp --transport stdio --no-migration + exec cognee-mcp --transport stdio --no-migration $API_ARGS fi fi diff --git a/cognee-mcp/src/server.py b/cognee-mcp/src/server.py index c390d9ac6..f98800b18 100755 --- a/cognee-mcp/src/server.py +++ b/cognee-mcp/src/server.py @@ -18,8 +18,7 @@ from starlette.middleware import Middleware from starlette.middleware.cors import CORSMiddleware import uvicorn -# Import the new CogneeClient abstraction -from cognee_client import CogneeClient +from .cognee_client import CogneeClient try: @@ -38,7 +37,6 @@ mcp = FastMCP("Cognee") logger = get_logger() -# Global CogneeClient instance (will be initialized in main()) cognee_client: Optional[CogneeClient] = None diff --git a/cognee/api/v1/ui/ui.py b/cognee/api/v1/ui/ui.py index 7711cb6ac..01862c6dc 100644 --- a/cognee/api/v1/ui/ui.py +++ b/cognee/api/v1/ui/ui.py @@ -507,19 +507,35 @@ def start_ui( try: image = "cognee/cognee-mcp:main" subprocess.run(["docker", "pull", image], check=True) + + docker_cmd = [ + "docker", + "run", + "-p", + f"{mcp_port}:8000", + "--rm", + "--env-file", + env_file, + "-e", + "TRANSPORT_MODE=sse", + ] + + if start_backend: + docker_cmd.extend( + [ + "-e", + f"API_URL=http://localhost:{backend_port}", + ] + ) + logger.info( + f"Configuring MCP to connect to backend API at http://localhost:{backend_port}" + ) + logger.info("(localhost will be auto-converted to host.docker.internal)") + + docker_cmd.append("cognee/cognee-mcp:daulet-dev") + mcp_process = subprocess.Popen( - [ - "docker", - "run", - "-p", - f"{mcp_port}:8000", - "--rm", - "--env-file", - env_file, - "-e", - "TRANSPORT_MODE=sse", - "cognee/cognee-mcp:main", - ], + docker_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid if hasattr(os, "setsid") else None, @@ -529,7 +545,11 @@ def start_ui( _stream_process_output(mcp_process, "stderr", "[MCP]", "\033[34m") # Blue pid_callback(mcp_process.pid) - logger.info(f"✓ Cognee MCP server starting on http://127.0.0.1:{mcp_port}/sse") + + mode_info = "API mode" if start_backend else "direct mode" + logger.info( + f"✓ Cognee MCP server starting on http://127.0.0.1:{mcp_port}/sse ({mode_info})" + ) except Exception as e: logger.error(f"Failed to start MCP server with Docker: {str(e)}") # Start backend server if requested