MCP Layer Refactoring Summary¶
Problem Statement¶
When running in Docker mode with memory tools, the bot was creating MCP configurations (Qwen CLI and universal configs) even though it shouldn't. This violated the architectural principle that the MCP Hub service should own ALL MCP-related logic.
Original Logs (Issue)¶
2025-10-15 10:05:57.110 | INFO | src.mcp.server_manager:_create_qwen_config:422 | [MCPServerManager] Creating MCP configurations for various clients...
2025-10-15 10:05:57.110 | INFO | src.mcp.server_manager:_create_qwen_config:430 | [MCPServerManager] Creating Qwen CLI config (HTTP/SSE mode)
2025-10-15 10:05:57.112 | INFO | src.mcp.server_manager:_create_qwen_config:458 | [MCPServerManager] Docker mode detected; skipping universal config generation
Problem: Bot was creating configs in Docker mode when it should be a pure client.
Architecture Goals¶
- MCP Hub Service owns ALL MCP logic:
- Built-in MCP tools (memory, etc.)
- MCP server registry
- Configuration file generation
-
HTTP/SSE API
-
Bot is a pure client:
- Docker mode: Connects to external MCP Hub service
- Standalone mode: Launches MCP Hub subprocess
- Never creates configuration files
Changes Made¶
1. Removed Config Generation from Bot (src/mcp/server_manager.py)¶
Removed Methods:
- _create_qwen_config() - Deleted entirely
- _setup_mcp_hub_connection() - Deleted entirely
- Config file creation from _setup_memory_subprocess() - Removed
Updated Methods:
- setup_default_servers() - Now only manages subprocess lifecycle
- _setup_memory_subprocess() - Only registers subprocess, no config creation
Updated Class Docstring:
class MCPServerManager:
"""
MCP Server Manager - Subprocess Lifecycle Manager
IMPORTANT: This manager is ONLY responsible for managing MCP Hub subprocess
lifecycle in standalone mode. It does NOT create any configurations.
"""
2. Added Config Generation to MCP Hub (src/mcp/mcp_hub_server.py)¶
New Function:
def _generate_client_configs(host: str, port: int) -> None:
"""
Generate MCP client configurations for various clients
This is the MCP Hub's responsibility - it knows its URL and should
generate configs for clients to connect to it.
"""
What It Does:
- Generates Qwen CLI config (~/.qwen/settings.json)
- Generates universal config (data/mcp_servers/mcp-hub.json) in standalone mode
- Skips universal config in Docker mode (as intended)
Startup Flow:
1. Initialize registry
2. Generate client configs (unless --skip-config-gen)
3. Start HTTP/SSE server
3. Added Config API Endpoint (src/mcp/mcp_hub_server.py)¶
New Endpoint:
@mcp.custom_route("/config/client/{client_type}", methods=["GET"])
async def http_get_client_config(request: Request):
"""
HTTP: Get client configuration for a specific client type
Supported client types:
- standard: Standard MCP format (Cursor, Claude Desktop, Qwen CLI)
- lmstudio: LM Studio specific format
- openai: OpenAI-compatible format
"""
Usage:
# Get standard config
curl http://localhost:8765/config/client/standard
# Download as file
curl http://localhost:8765/config/client/standard?format=raw -o mcp-hub.json
4. Updated Documentation¶
Created:
- docs_site/architecture/mcp-architecture.md - Comprehensive architecture guide
Updated:
- src/mcp/README.md - Reflects new architecture
Behavior Changes¶
Before Refactoring¶
Docker Mode:
Bot starts
↓
MCPServerManager.setup_default_servers()
↓
_create_qwen_config() runs ← WRONG!
↓
Creates ~/.qwen/settings.json ← WRONG!
↓
Bot connects to MCP Hub
Standalone Mode:
Bot starts
↓
MCPServerManager.setup_default_servers()
↓
_setup_memory_subprocess() creates config file ← WRONG!
↓
_create_qwen_config() runs ← WRONG!
↓
Starts MCP Hub subprocess
↓
Bot connects to MCP Hub
After Refactoring¶
Docker Mode:
MCP Hub container starts
↓
MCP Hub generates configs on startup ✓
↓
Bot container starts
↓
MCPServerManager.setup_default_servers() does nothing ✓
↓
Bot connects to MCP Hub via MCP_HUB_URL ✓
Standalone Mode:
Bot starts
↓
MCPServerManager.setup_default_servers()
↓
_setup_memory_subprocess() registers subprocess only ✓
↓
Starts MCP Hub subprocess ✓
↓
MCP Hub generates configs on startup ✓
↓
Bot connects to MCP Hub ✓
Files Changed¶
- src/mcp/server_manager.py
- Removed:
_create_qwen_config(),_setup_mcp_hub_connection() - Updated:
setup_default_servers(),_setup_memory_subprocess() -
Updated: Class docstring
-
src/mcp/mcp_hub_server.py
- Added:
_generate_client_configs()function - Added:
--skip-config-genCLI argument - Added:
/config/client/{client_type}API endpoint -
Updated:
main()to call config generation on startup -
docs_site/architecture/mcp-architecture.md
-
Created: Comprehensive architecture documentation
-
src/mcp/README.md
- Updated: Architecture section to reflect new design
Testing¶
Syntax Check¶
python3 -m py_compile src/mcp/server_manager.py
python3 -m py_compile src/mcp/mcp_hub_server.py
# ✓ Both pass
Docker Mode Test¶
# Start services
docker-compose up
# Expected logs from MCP Hub:
# "📝 Generating client configurations..."
# "✓ Qwen CLI config: ..."
# "Docker mode: Skipping universal config generation"
# Expected logs from Bot:
# "[MCPServerManager] Docker mode: Bot will connect to external MCP Hub at ..."
# NO config generation logs from bot ✓
# Verify health
curl http://localhost:8765/health
# Verify config API
curl http://localhost:8765/config/client/standard
Standalone Mode Test¶
# Start bot
python -m main
# Expected logs:
# Bot: "[MCPServerManager] Standalone mode: Will launch MCP Hub as subprocess"
# MCP Hub subprocess: "📝 Generating client configurations..."
# MCP Hub subprocess: "✓ Qwen CLI config: ..."
# MCP Hub subprocess: "✓ Universal config: ..."
# Verify configs created by MCP Hub
ls -la ~/.qwen/settings.json
ls -la data/mcp_servers/mcp-hub.json
Migration Guide¶
For Existing Deployments¶
-
Pull latest code with refactored MCP layer
-
Docker deployments:
- Rebuild images:
docker-compose build - Restart services:
docker-compose up -d - Verify no config logs from bot container
-
Verify config logs from mcp-hub container
-
Standalone deployments:
- Update code
- Restart bot:
python -m main -
Verify MCP Hub subprocess creates configs
-
Verify configs:
Rollback (if needed)¶
If issues occur: 1. Revert to previous commit before refactoring 2. Rebuild/restart services 3. Report issue with logs
Benefits¶
- Clear Separation of Concerns
- MCP Hub: owns all MCP logic
-
Bot: pure client
-
No Config Duplication
- Single source of truth (MCP Hub)
-
Consistent configs across deployments
-
Mode-Agnostic Bot
- Same bot code for Docker and standalone
-
Mode detected via
MCP_HUB_URLenv var -
Dynamic Config API
- Clients can fetch configs programmatically
-
Useful for automation and tooling
-
Better Testability
- Clear interface boundaries
- Easier to mock and test
Known Issues / Future Work¶
- Config API Authentication
- Currently no auth on
/config/client/*endpoints -
Consider adding in production environments
-
Config Caching
- Configs generated on every startup
-
Could cache and only regenerate on change
-
Multi-Hub Support
- Currently assumes single MCP Hub
-
Could extend to support multiple hubs
-
Config Validation
- No validation of generated configs
- Could add schema validation
References¶
Author¶
- Refactored by: AI Agent
- Date: 2025-10-15
- Issue: Config generation in Docker mode when it shouldn't