Add lifespan context manager for FastMCP Cloud initialization

FastMCP Cloud does not execute the if __name__ == '__main__' block,
so the Graphiti service was never initialized. This adds a lifespan
context manager that FastMCP uses for server startup/shutdown.

The lifespan:
- Loads configuration from environment variables
- Initializes GraphitiService and QueueService
- Connects to the database (Neo4j/FalkorDB)
- Sets up global clients for tool access

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
donbr 2025-12-06 23:59:23 -08:00
parent 83f03aefc9
commit 98f5a14f69

View file

@ -8,6 +8,7 @@ import asyncio
import logging
import os
import sys
from contextlib import asynccontextmanager
from pathlib import Path
from typing import Any, Optional
@ -328,6 +329,55 @@ class GraphitiService:
return self.client
@asynccontextmanager
async def graphiti_lifespan(app):
"""Lifespan context manager for FastMCP Cloud deployment.
This function initializes the Graphiti service when the server starts.
FastMCP Cloud calls this automatically - it does NOT run the if __name__ == '__main__' block.
"""
global config, graphiti_service, queue_service, graphiti_client, semaphore
logger.info('Initializing Graphiti service via lifespan...')
try:
# Load configuration from environment variables (FastMCP Cloud sets these)
config = GraphitiConfig()
# Log configuration details
logger.info('Using configuration:')
logger.info(f' - LLM: {config.llm.provider} / {config.llm.model}')
logger.info(f' - Embedder: {config.embedder.provider} / {config.embedder.model}')
logger.info(f' - Database: {config.database.provider}')
logger.info(f' - Group ID: {config.graphiti.group_id}')
# Initialize services
graphiti_service = GraphitiService(config, SEMAPHORE_LIMIT)
queue_service = QueueService()
await graphiti_service.initialize()
# Set global client for backward compatibility
graphiti_client = await graphiti_service.get_client()
semaphore = graphiti_service.semaphore
# Initialize queue service with the client
await queue_service.initialize(graphiti_client)
logger.info('Graphiti service initialized successfully via lifespan')
yield # Server runs here
except Exception as e:
logger.error(f'Failed to initialize Graphiti service: {e}')
raise
finally:
logger.info('Shutting down Graphiti service...')
# Update the MCP server to use the lifespan
mcp.lifespan = graphiti_lifespan
@mcp.tool()
async def add_memory(
name: str,