graphiti icon indicating copy to clipboard operation
graphiti copied to clipboard

Cursor Docker networking fix + multi project support + open router support

Open jonit-dev opened this issue 7 months ago • 5 comments

Summary

This PR significantly enhances the Graphiti MCP Server with OpenRouter integration improvements, Docker deployment enhancements, dependency updates, comprehensive documentation consolidation, and introduces seamless multi-project support through URL-based group_id switching.

Key Changes

🆕 NEW: OpenRouter App Identification

  • Automatic header injection: Added HTTP-Referer and X-Title headers for proper OpenRouter app identification
  • Leaderboard visibility: App now appears as "Graphiti MCP Server" instead of "Unknown" in OpenRouter usage logs
  • Smart detection: Headers automatically added when using openrouter.ai base URL
  • Zero configuration: Works seamlessly with existing OpenRouter setup

🚀 NEW: Multi-Project Support

  • URL-based group_id switching: Revolutionary feature enabling seamless project isolation
  • Single server, unlimited projects: Use one Graphiti instance for all your projects
  • Zero configuration switching: Change projects instantly via URL parameters
  • Real-time group isolation: Each connection maintains its own data namespace

🐳 Docker & Infrastructure Improvements

  • Fixed Docker networking: Set MCP server host to 0.0.0.0 for proper container accessibility
  • Updated Neo4j: Bumped from version 5.26.0 to 5.26.2 for latest fixes
  • Simplified Docker Compose: Cleaned up configuration and improved formatting
  • Enhanced logging: Added detailed SSE transport logging for better debugging

📚 Documentation Consolidation & Enhancement

  • Merged Cursor setup guide: Integrated CURSOR_SETUP.md into main mcp_server/README.md
  • 🆕 Multi-project documentation: Comprehensive guide for URL-based group switching
  • Enhanced setup instructions: Step-by-step integration guide with new features
  • Troubleshooting section: Included common issues and solutions
  • Support links: Added GitHub issues, docs, and community channel links

🔧 Configuration Updates

  • Streamlined env file handling: Simplified Docker Compose environment configuration
  • Improved quote consistency: Standardized YAML formatting across Docker files

🆕 OpenRouter App Identification Details

Automatic Header Injection

When using OpenRouter (detected by openrouter.ai in base URL), the system automatically adds:

HTTP-Referer: https://github.com/getzep/graphiti
X-Title: Graphiti MCP Server

Before vs After

Before: Usage logs show "Unknown" app

Provider / Model    App        Tokens    Cost
Gemini 2.5 Flash    Unknown    1,182     $0.000501

After: Usage logs show proper identification

Provider / Model    App                   Tokens    Cost
Gemini 2.5 Flash    Graphiti MCP Server   1,182     $0.000501

Technical Implementation

# Added to both OpenAIClient and OpenAIGenericClient
if config.base_url and 'openrouter.ai' in config.base_url:
    default_headers.update({
        'HTTP-Referer': 'https://github.com/getzep/graphiti',
        'X-Title': 'Graphiti MCP Server'
    })

self.client = AsyncOpenAI(
    api_key=config.api_key, 
    base_url=config.base_url,
    default_headers=default_headers if default_headers else None
)

🆕 Multi-Project Feature Details

URL-Based Group Switching

{
  "mcpServers": {
    "graphiti-work": {
      "url": "http://localhost:8000/sse?group_id=work_projects"
    },
    "graphiti-personal": {
      "url": "http://localhost:8000/sse?group_id=personal_coding"
    },
    "graphiti-client-a": {
      "url": "http://localhost:8000/sse?group_id=client_a_project"
    }
  }
}

Technical Implementation

# New middleware for automatic group_id extraction
def get_effective_group_id(provided_group_id: str | None = None) -> str | None:
    """Get the effective group_id, prioritizing URL-based, then provided, then config default."""
    if current_group_id is not None:
        return current_group_id
    if provided_group_id is not None:
        return provided_group_id
    return config.group_id

# Updated all tool functions to use effective group_id
async def add_memory(name: str, episode_body: str, group_id: str | None = None, ...):
    effective_group_id = get_effective_group_id(group_id)
    # ... rest of implementation

Technical Details

OpenRouter Headers Implementation

# Files modified:
# - graphiti_core/llm_client/openai_client.py
# - graphiti_core/llm_client/openai_generic_client.py

# Smart header detection and injection
default_headers = {}
if config.base_url and 'openrouter.ai' in config.base_url:
    default_headers.update({
        'HTTP-Referer': 'https://github.com/getzep/graphiti',
        'X-Title': 'Graphiti MCP Server'
    })

Docker Networking Fix

# Set host to 0.0.0.0 for Docker container accessibility
mcp.settings.host = '0.0.0.0'

Multi-Project Access Patterns

  • Default: http://localhost:8000/sse
  • Project A: http://localhost:8000/sse?group_id=project_a
  • Project B: http://localhost:8000/sse?group_id=project_b
  • Personal: http://localhost:8000/sse?group_id=personal

Neo4j Version Update

  • Updated from neo4j:5.26.0 to neo4j:5.26.2
  • Maintains compatibility while getting latest bug fixes

Files Changed

  • graphiti_core/llm_client/openai_client.py - NEW: Added OpenRouter identification headers
  • graphiti_core/llm_client/openai_generic_client.py - NEW: Added OpenRouter identification headers
  • mcp_server/graphiti_mcp_server.py - Major enhancement: Added URL-based group_id support, Docker networking, and logging improvements
  • mcp_server/docker-compose.yml - Neo4j update and configuration cleanup
  • mcp_server/README.md - Comprehensive update: Multi-project setup guide and Cursor documentation
  • mcp_server/CURSOR_SETUP.md - Removed (content merged into README)

Benefits

  • 🆕 OpenRouter app identification - Proper attribution in usage logs and leaderboards
  • 🆕 Seamless multi-project support - Use one server for unlimited isolated projects
  • 🆕 Zero-configuration project switching - Change projects via URL parameters
  • 🆕 Real-time group isolation - Instant data separation without server restarts
  • 🆕 Backward compatibility - All existing configurations continue to work
  • ✅ Fixed Docker container networking issues
  • ✅ Updated to latest stable Neo4j version
  • ✅ Single source of truth for comprehensive documentation
  • ✅ Improved developer experience with better setup instructions
  • ✅ Enhanced debugging with detailed logging

Testing & Validation

  • [x] 🆕 Verified OpenRouter headers are properly injected and working
  • [x] 🆕 Confirmed app shows as "Graphiti MCP Server" in OpenRouter logs
  • [x] 🆕 Tested mixed provider setup (OpenRouter LLM + OpenAI embeddings)
  • [x] Verified Docker containers start and communicate properly
  • [x] Confirmed MCP server is accessible on 0.0.0.0:8000
  • [x] 🆕 Tested URL-based group_id switching functionality
  • [x] 🆕 Validated data isolation between different group_ids
  • [x] 🆕 Confirmed Neo4j shows distinct groups: default, project_a, project_b, personal
  • [x] Tested Neo4j 5.26.2 compatibility
  • [x] Validated merged documentation renders correctly
  • [x] 🆕 Verified no regressions in existing functionality
  • [x] 🆕 All configuration tests passing (12/12)

OpenRouter Integration Verification

# Live testing shows successful API calls
2025-05-26 22:41:06,117 - httpx - INFO - HTTP Request: POST https://openrouter.ai/api/v1/chat/completions "HTTP/1.1 200 OK"
2025-05-26 22:41:06,843 - httpx - INFO - HTTP Request: POST https://api.openai.com/v1/embeddings "HTTP/1.1 200 OK"

Database Verification

// Query to see all groups in Neo4j
MATCH (n) RETURN DISTINCT n.group_id as group_id, labels(n) as node_types, count(n) as count ORDER BY group_id

// Results show successful group isolation:
// "default", ["Episodic"], 8
// "default", ["Entity"], 43  
// "personal", ["Episodic"], 1
// "personal", ["Entity"], 2
// "project_a", ["Episodic"], 1
// "project_a", ["Entity"], 1
// "project_b", ["Episodic"], 1
// "project_b", ["Entity"], 1

[!IMPORTANT] Major Enhancement: Introduces OpenRouter app identification alongside URL-based multi-project support, Docker networking fixes, Neo4j updates, and documentation consolidation.

  • 🆕 OpenRouter App Identification:
    • Added automatic HTTP-Referer and X-Title headers for proper OpenRouter attribution
    • Smart detection when using openrouter.ai base URL
    • App now appears as "Graphiti MCP Server" in usage logs instead of "Unknown"
    • Zero configuration required - works automatically with existing OpenRouter setup
  • 🆕 Multi-Project Feature:
    • Added URL-based group_id switching via query parameters (e.g., ?group_id=project_a)
    • Updated all MCP tool functions to use get_effective_group_id() for consistent group handling
    • Added FastAPI middleware for automatic group_id extraction from URLs
    • Enables seamless project isolation using a single server instance
  • Docker Networking Fix:
    • Set mcp.settings.host to 0.0.0.0 in graphiti_mcp_server.py for Docker container accessibility
  • Dependency Update:
    • Updated Neo4j from version 5.26.0 to 5.26.2 in docker-compose.yml
  • Enhanced Documentation:
    • Merged CURSOR_SETUP.md into README.md with comprehensive multi-project setup guide
    • Added detailed examples for URL-based group switching in Cursor and Claude Desktop
  • Validation:
    • Confirmed OpenRouter headers working and app properly identified
    • Confirmed data isolation across groups in Neo4j database
    • Verified backward compatibility with existing configurations

This PR transforms the Graphiti MCP Server from a single-project tool into a powerful multi-project platform with proper OpenRouter integration, while maintaining full backward compatibility and improving the overall developer experience.

jonit-dev avatar May 26 '25 20:05 jonit-dev


Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.


I have read the CLA Document and I hereby sign the CLA


You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

danielchalef avatar May 26 '25 20:05 danielchalef

Thank you for your submission, we really appreciate it. Like many open-source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution. You can sign the CLA by just posting a Pull Request Comment same as the below format.

I have read the CLA Document and I hereby sign the CLA

You can retrigger this bot by commenting recheck in this Pull Request. Posted by the CLA Assistant Lite bot.

I have read the CLA Document and I hereby sign the CLA

jonit-dev avatar May 26 '25 20:05 jonit-dev

Ideally I'd split this PR into multiple feature focused ones.

I'll do next time.

jonit-dev avatar May 26 '25 22:05 jonit-dev

PS: I'm the maintainer of this other OS project called DiffGuard. Feel free to integrate in your github actions workflow if you want

https://github.com/jonit-dev/diffguard

TLDR: You can point the PR diff to be reviewed automatically by any open router available model and scored. It can even block the PR merge if it think it has too many issues. If you don't want to spend credits, check deepseek-r1t-chimera:free model, however I'm getting good results with o4-mini

jonit-dev avatar May 26 '25 22:05 jonit-dev

@jonit-dev Thanks for contributing. This PR covers a lot of varying ground. Would you please split it into smaller PRs that can be reviewed and merged independently?

danielchalef avatar May 28 '25 03:05 danielchalef

Closing due to no response.

danielchalef avatar Jun 28 '25 19:06 danielchalef