multi-client-architecture.md•16.1 kB
# Multi-Client Architecture Documentation
This document provides technical details about the multi-client architecture implementation in the MCP Memory Service, specifically focusing on the integrated setup functionality added to `install.py`.
## Overview
The multi-client architecture enables multiple MCP applications to safely share the same memory database concurrently. The latest implementation integrates this setup directly into the main installation process, making it universally accessible to any MCP-compatible application.
## Architecture Components
### 1. Client Detection System
#### Detection Strategy
The system uses a multi-pronged approach to detect MCP clients:
```python
def detect_mcp_clients():
"""Detect installed MCP-compatible applications."""
clients = {}
# Pattern-based detection for known applications
detection_patterns = {
'claude_desktop': [
Path.home() / "AppData" / "Roaming" / "Claude" / "claude_desktop_config.json", # Windows
Path.home() / "Library" / "Application Support" / "Claude" / "claude_desktop_config.json", # macOS
Path.home() / ".config" / "Claude" / "claude_desktop_config.json" # Linux
],
'vscode_mcp': [
# VS Code settings.json locations with MCP extension detection
],
'continue': [
# Continue IDE configuration locations
],
'generic_mcp': [
# Generic MCP configuration file locations
]
}
```
#### Detection Logic
1. **File-based Detection**: Checks for configuration files in standard locations
2. **Content Analysis**: Examines configuration files for MCP-related settings
3. **CLI Detection**: Tests for command-line tools (e.g., Claude Code)
4. **Extension Detection**: Identifies IDE extensions that support MCP
### 2. Configuration Management
#### Configuration Abstraction
Each client type has a dedicated configuration handler:
```python
class MCPClientConfigurator:
"""Base class for MCP client configuration."""
def detect(self) -> bool:
"""Detect if this client is installed."""
raise NotImplementedError
def configure(self, config: MCPConfig) -> bool:
"""Configure the client for multi-client access."""
raise NotImplementedError
def validate(self) -> bool:
"""Validate the configuration."""
raise NotImplementedError
class ClaudeDesktopConfigurator(MCPClientConfigurator):
"""Configure Claude Desktop for multi-client access."""
def configure(self, config: MCPConfig) -> bool:
# Update claude_desktop_config.json
pass
class ContinueIDEConfigurator(MCPClientConfigurator):
"""Configure Continue IDE for multi-client access."""
def configure(self, config: MCPConfig) -> bool:
# Update Continue configuration files
pass
```
#### Configuration Template System
Universal configuration templates ensure consistency:
```python
class MCPConfig:
"""Standard MCP configuration structure."""
def __init__(self, repo_path: str):
self.repo_path = repo_path
self.base_config = {
"command": "uv",
"args": ["--directory", repo_path, "run", "memory"],
"env": {
"MCP_MEMORY_STORAGE_BACKEND": "sqlite_vec",
"MCP_MEMORY_SQLITE_PRAGMAS": "busy_timeout=15000,cache_size=20000",
"LOG_LEVEL": "INFO"
}
}
def for_client(self, client_type: str) -> dict:
"""Generate client-specific configuration."""
config = self.base_config.copy()
if client_type == "claude_desktop":
# Claude Desktop specific adjustments
pass
elif client_type == "continue":
# Continue IDE specific adjustments
pass
return config
```
### 3. WAL Mode Coordination
#### SQLite WAL Implementation
Write-Ahead Logging mode enables safe concurrent access:
```python
async def test_wal_mode_coordination():
"""Test WAL mode storage coordination for multi-client access."""
# Create test database with WAL mode
storage = SqliteVecMemoryStorage(test_db_path)
await storage.initialize()
# WAL mode pragmas are applied in storage initialization:
# PRAGMA journal_mode=WAL;
# PRAGMA busy_timeout=15000;
# PRAGMA cache_size=20000;
# PRAGMA synchronous=NORMAL;
# Test concurrent access patterns
storage2 = SqliteVecMemoryStorage(test_db_path)
await storage2.initialize()
# Verify both can read/write safely
success = await test_concurrent_operations(storage, storage2)
return success
```
#### Concurrency Model
- **Multiple Readers**: Any number of clients can read simultaneously
- **Single Writer**: One client writes at a time, with automatic queuing
- **Retry Logic**: Exponential backoff for lock conflicts
- **Timeout Handling**: 15-second timeout prevents deadlocks
### 4. Integration Flow
#### Installation Integration Points
The multi-client setup integrates at specific points in the installation flow:
```python
def main():
"""Main installation function with multi-client integration."""
# 1. System detection and backend selection
system_info = detect_system()
final_backend = determine_backend(args, system_info)
# 2. Core installation (dependencies, package, paths)
install_success = install_package(args)
configure_paths(args)
verify_installation()
# 3. Multi-client integration point
if should_offer_multi_client_setup(args, final_backend):
if prompt_user_for_multi_client() or args.setup_multi_client:
setup_universal_multi_client_access(system_info, args)
# 4. Final configuration and completion
complete_installation()
```
#### Decision Logic
Multi-client setup is offered based on:
```python
def should_offer_multi_client_setup(args, final_backend):
"""Intelligent decision logic for multi-client offering."""
# Required: SQLite-vec backend (only backend supporting multi-client)
if final_backend != "sqlite_vec":
return False
# Skip in automated/server environments
if args.server_mode or args.skip_multi_client_prompt:
return False
# Always beneficial for development environments
return True
```
### 5. Error Handling and Fallbacks
#### Layered Error Handling
The system implements multiple fallback layers:
```python
def setup_universal_multi_client_access(system_info, args):
"""Configure multi-client access with comprehensive error handling."""
try:
# Layer 1: WAL mode validation
if not test_wal_mode_coordination():
raise MCPSetupError("WAL mode coordination test failed")
# Layer 2: Client detection and configuration
clients = detect_mcp_clients()
success_count = configure_detected_clients(clients, system_info)
# Layer 3: Environment setup
setup_shared_environment()
# Layer 4: Generic configuration (always succeeds)
provide_generic_configuration()
return True
except MCPSetupError as e:
# Graceful degradation: provide manual instructions
print_error(f"Automated setup failed: {e}")
provide_manual_setup_instructions()
return False
```
#### Fallback Mechanisms
1. **Automated → Manual**: If automated setup fails, provide manual instructions
2. **Specific → Generic**: If client-specific config fails, use generic templates
3. **Integrated → Standalone**: Direct users to standalone setup script
4. **Setup → Documentation**: Always provide comprehensive documentation
### 6. Extensibility Framework
#### Adding New Client Support
The architecture is designed for easy extension:
```python
# 1. Add detection pattern
def detect_new_client():
"""Detect NewClient MCP application."""
config_paths = [
# Platform-specific configuration file locations
]
for path in config_paths:
if path.exists() and is_mcp_configured(path):
return path
return None
# 2. Add configuration handler
def configure_new_client_multi_client(config_path):
"""Configure NewClient for multi-client access."""
try:
# Read existing configuration
config = read_client_config(config_path)
# Apply multi-client settings
config.update(generate_mcp_config())
# Write updated configuration
write_client_config(config_path, config)
print_info(" [OK] NewClient: Updated configuration")
return True
except Exception as e:
print_warning(f" -> NewClient configuration failed: {e}")
return False
# 3. Register in detection system
def detect_mcp_clients():
clients = {}
# ... existing detection logic ...
# Add new client detection
new_client_path = detect_new_client()
if new_client_path:
clients['new_client'] = new_client_path
return clients
```
#### Plugin Architecture Potential
The current implementation could evolve into a plugin system:
```python
class MCPClientPlugin:
"""Base class for MCP client plugins."""
name: str
priority: int
def detect(self) -> Optional[Path]:
"""Detect client installation."""
pass
def configure(self, config: MCPConfig, config_path: Path) -> bool:
"""Configure client for multi-client access."""
pass
def validate(self, config_path: Path) -> bool:
"""Validate client configuration."""
pass
# Plugin registration system
REGISTERED_PLUGINS = [
ClaudeDesktopPlugin(),
ContinueIDEPlugin(),
VSCodeMCPPlugin(),
CursorIDEPlugin(),
GenericMCPPlugin(), # Fallback plugin
]
```
## Technical Decisions
### Why SQLite-vec Only?
Multi-client support is limited to SQLite-vec backend because:
1. **WAL Mode Support**: SQLite's WAL mode provides robust concurrent access
2. **File-based Storage**: Single database file simplifies sharing
3. **Performance**: SQLite is optimized for multi-reader scenarios
4. **Reliability**: Well-tested concurrency mechanisms
5. **Simplicity**: No network coordination required
### Why Integrated Setup?
Integration into the main installer provides:
1. **Discoverability**: Users learn about multi-client capabilities during installation
2. **Convenience**: One-step setup for all MCP applications
3. **Consistency**: Uniform configuration across all clients
4. **Future-proofing**: Automatic support for new MCP applications
### Configuration Strategy
Direct configuration file modification was chosen over:
- **Environment variables only**: Would require manual client restart
- **Network-based coordination**: Adds complexity and failure points
- **Copy-paste instructions**: Reduces user experience and increases errors
## Performance Considerations
### Database Performance
- **WAL Mode**: Allows concurrent readers without blocking
- **Cache Size**: 20MB cache improves multi-client performance
- **Busy Timeout**: 15-second timeout prevents deadlocks
- **Synchronous Mode**: NORMAL mode balances safety and performance
### Memory Usage
- **Shared Database**: Single database reduces total memory usage
- **Connection Pooling**: Each client maintains its own connection pool
- **Cache Coordination**: WAL mode provides implicit cache coordination
### Startup Performance
- **Lazy Initialization**: Clients initialize storage on first use
- **Fast Detection**: Configuration file checking is optimized
- **Minimal Overhead**: Setup adds <1 second to installation time
## Security Considerations
### File System Security
- **Path Validation**: All configuration paths are validated before modification
- **Backup Creation**: Original configurations are backed up before changes
- **Permission Checks**: Write permissions verified before attempting changes
### Configuration Security
- **Template Validation**: All configuration templates are validated
- **Injection Prevention**: No user input is directly inserted into configurations
- **Safe Defaults**: Conservative defaults used for security-sensitive settings
## Testing Strategy
### Unit Testing
```python
def test_client_detection():
"""Test MCP client detection functionality."""
# Mock configuration files
with mock_config_files():
clients = detect_mcp_clients()
assert 'claude_desktop' in clients
assert 'continue' in clients
def test_configuration_generation():
"""Test MCP configuration generation."""
config = MCPConfig("/test/repo")
claude_config = config.for_client("claude_desktop")
assert claude_config["env"]["MCP_MEMORY_STORAGE_BACKEND"] == "sqlite_vec"
assert "busy_timeout" in claude_config["env"]["MCP_MEMORY_SQLITE_PRAGMAS"]
```
### Integration Testing
```python
async def test_multi_client_coordination():
"""Test actual multi-client database coordination."""
# Create test database
db_path = create_test_database()
# Initialize multiple storage instances
storage1 = SqliteVecMemoryStorage(db_path)
storage2 = SqliteVecMemoryStorage(db_path)
await storage1.initialize()
await storage2.initialize()
# Test concurrent operations
success = await test_concurrent_read_write(storage1, storage2)
assert success
```
### End-to-End Testing
```python
def test_full_installation_flow():
"""Test complete installation with multi-client setup."""
with temporary_environment():
# Run installer with multi-client setup
result = run_installer(["--setup-multi-client", "--storage-backend", "sqlite_vec"])
assert result.success
assert result.multi_client_configured
assert validate_client_configurations()
```
## Monitoring and Observability
### Logging Framework
```python
# Multi-client specific logging
logger = logging.getLogger("mcp.multi_client")
def setup_universal_multi_client_access(system_info, args):
logger.info("Starting universal multi-client setup")
clients = detect_mcp_clients()
logger.info(f"Detected {len(clients)} MCP clients: {list(clients.keys())}")
for client_type, config_path in clients.items():
try:
success = configure_client(client_type, config_path)
logger.info(f"Client {client_type} configuration: {'success' if success else 'failed'}")
except Exception as e:
logger.error(f"Client {client_type} configuration error: {e}")
```
### Metrics Collection
```python
# Installation metrics
class InstallationMetrics:
def __init__(self):
self.clients_detected = 0
self.clients_configured = 0
self.configuration_errors = []
self.setup_duration = 0
def record_client_detection(self, client_type: str):
self.clients_detected += 1
def record_configuration_success(self, client_type: str):
self.clients_configured += 1
def record_configuration_error(self, client_type: str, error: str):
self.configuration_errors.append((client_type, error))
```
## Future Enhancements
### Planned Improvements
1. **HTTP Coordination**: Advanced coordination for 3+ clients
2. **Configuration Validation**: Real-time validation of client configurations
3. **Auto-Updates**: Automatic configuration updates for new MCP versions
4. **Cloud Sync**: Multi-device memory synchronization
5. **Plugin System**: Formal plugin architecture for client support
### Research Areas
1. **Conflict Resolution**: Advanced merge strategies for concurrent edits
2. **Performance Optimization**: Database sharding for large-scale deployments
3. **Security Enhancements**: Encrypted inter-client communication
4. **Mobile Support**: Extension to mobile MCP applications
This architecture provides a robust, extensible foundation for universal multi-client support in the MCP Memory Service ecosystem.