# MCP Migration Implementation Guide ## Phase-by-Phase Implementation Plan ### Overview This guide walks through converting DSS from REST-based to MCP-first architecture with persistent state management. **Timeline:** 7-8 weeks **Current Status:** Architecture documented, components audited **Next Step:** Begin Phase 1 - MCP Tool Suite --- ## Phase 1: Complete MCP Tool Suite (Weeks 1-3) ### 1.1 Expand MCP Server **File:** `tools/dss_mcp/server.py` **Current Tools:** 2 (ingest_figma_file, get_status) **Target Tools:** 15+ ```python # Project Management - dss_create_project(name, root_path, description) → project_id - dss_list_projects() → [projects] - dss_get_project(project_id) → project - dss_update_project(project_id, updates) → project - dss_delete_project(project_id) → bool # Figma Integration - dss_setup_figma_credentials(api_token) → bool - dss_discover_figma_files(project_id) → [files] - dss_add_figma_file(project_id, file_key, name) → manifest - dss_list_figma_files(project_id) → [files] # Token Management - dss_sync_tokens(project_id, output_format) → tokens - dss_extract_tokens(figma_file_key) → tokens - dss_validate_tokens(tokens) → report - dss_detect_token_drift(project_id) → drift_report # Component Analysis - dss_discover_components(project_id, path) → components - dss_analyze_components(project_id) → analysis - dss_get_quick_wins(project_id, path) → [wins] # Status & Info - dss_get_project_status(project_id) → status - dss_get_system_health() → health ``` ### 1.2 Credential Management **Requirement:** Encrypt sensitive data at rest ```python # In dss_mcp/security.py class CredentialVault: """Manages encrypted credential storage""" def encrypt_figma_token(token: str) -> str: """Encrypt token for storage""" # Use cryptography library # Store in database with salt def decrypt_figma_token(encrypted: str) -> str: """Decrypt token for use""" def rotate_encryption_key() -> bool: """Support key rotation""" ``` ### 1.3 Operation Queuing **Requirement:** Handle long-running operations asynchronously ```python # In dss_mcp/operations.py class OperationQueue: """Manages async operations with status tracking""" def enqueue(operation_type, args) -> operation_id def get_status(operation_id) -> status def get_result(operation_id) -> result def cancel(operation_id) -> bool ``` ### 1.4 Audit Logging **Requirement:** Track all operations for compliance and debugging ```python # In dss_mcp/audit.py class AuditLog: """Persistent operation history""" def log_operation( operation_type: str, args: dict, result: dict, user_id: str, timestamp: datetime ) -> log_id def get_operation_history(project_id, limit=100) -> [logs] def get_audit_trail(start_date, end_date) -> [logs] ``` ### 1.5 Testing MCP Tools ```bash # Test each tool independently python -m pytest tools/dss_mcp/tests/test_project_tools.py python -m pytest tools/dss_mcp/tests/test_figma_tools.py python -m pytest tools/dss_mcp/tests/test_token_tools.py # Integration tests python -m pytest tools/dss_mcp/tests/test_workflows.py # End-to-end tests with MCP server python -m pytest tools/dss_mcp/tests/test_e2e.py ``` --- ## Phase 2: Persistence Layer (Week 4) ### 2.1 State Machine for Projects **Requirement:** Track project state through workflow ```python # In tools/storage/state_machine.py from enum import Enum class ProjectState(Enum): CREATED = "created" FIGMA_CONFIGURED = "figma_configured" TOKENS_EXTRACTED = "tokens_extracted" COMPONENTS_ANALYZED = "components_analyzed" READY = "ready" class ProjectStateMachine: """Manages valid state transitions""" def __init__(self, project_id): self.project_id = project_id self.state = self.load_state() def transition(self, action: str) -> bool: """Validate and apply state transition""" # Only allow valid transitions # Log transition # Update database def can_transition(self, action: str) -> bool: """Check if action is valid for current state""" ``` ### 2.2 Operation History **Requirement:** Support undo/rollback ```python # In tools/storage/operation_history.py class OperationHistory: """Tracks all state-changing operations""" def record_operation( project_id, operation: Operation, before_state: dict, after_state: dict ) -> history_id def get_operation(operation_id) -> Operation def rollback(operation_id) -> bool def get_timeline(project_id) -> [operations] ``` ### 2.3 Concurrent Operation Handling **Requirement:** Handle multiple operations safely ```python # In dss_mcp/concurrency.py import asyncio from threading import Lock class OperationLock: """Prevents concurrent modifications to same resource""" def acquire(project_id, resource_type) -> lock def release(lock) -> bool class OperationScheduler: """Queues operations and executes sequentially per resource""" async def queue_operation(operation) -> operation_id async def process_queue(project_id, resource_type) ``` --- ## Phase 3: JS UI Migration (Weeks 5-6) ### 3.1 Remove REST Calls **Before:** ```javascript // In admin-ui/js/core/ai.js async sendMessage(message) { const response = await fetch('/api/claude/chat', { method: 'POST', body: JSON.stringify({ message }) }); const data = await response.json(); return data.response; } ``` **After:** ```javascript // Delegate to Claude via MCP async sendMessage(message) { return { action: 'mcp_tool_call', tool: 'chat', args: { message } }; // Claude handles the REST call or MCP tool call } ``` ### 3.2 MCP Tool Invocation Layer **File:** `admin-ui/js/core/mcp-client.js` ```javascript class MCPClient { /** * Calls an MCP tool and waits for result */ async callTool(toolName, args) { const response = await fetch('/api/mcp/call', { method: 'POST', body: JSON.stringify({ tool: toolName, args: args }) }); if (!response.ok) { throw new Error(`Tool ${toolName} failed`); } return await response.json(); } async listTools() { const response = await fetch('/api/mcp/tools'); return await response.json(); } } // Usage in components const mcp = new MCPClient(); const project = await mcp.callTool('dss_create_project', { name: 'web-ui', root_path: './packages/design' }); ``` ### 3.3 Update AI Chat Component **File:** `admin-ui/js/core/ai.js` ```javascript // Replace REST calls with MCP async handleSendCommand(command) { const parsed = this.ai.parseCommand(command); if (parsed) { // Delegate to Claude with MCP tools const result = await this.ai.sendMessage(command, { enableTools: true // Use MCP tools }); // Claude will call appropriate MCP tools // and return formatted response this.addMessage('assistant', result); return; } // Regular chat const response = await this.ai.sendMessage(command); this.addMessage('assistant', response); } ``` ### 3.4 Update Component Data Binding **File:** `admin-ui/js/components/ds-project-card.js` ```javascript class DsProjectCard extends HTMLElement { async connectedCallback() { const projectId = this.getAttribute('data-project-id'); // Fetch project data via MCP const mcp = new MCPClient(); const project = await mcp.callTool( 'dss_get_project', { project_id: projectId } ); this.render(project); } render(project) { this.shadowRoot.innerHTML = `

${project.name}

${project.description}

${project.state}
`; } } ``` --- ## Phase 4: Testing & Documentation (Week 7) ### 4.1 Integration Tests ```python # tests/integration/test_mcp_workflows.py import pytest from dss_mcp.server import mcp_server class TestProjectWorkflow: """End-to-end project creation workflow""" async def test_create_project_full_workflow(self): """Test: Create → Configure Figma → Extract Tokens""" # Step 1: Create project project = await mcp_server.call_tool('dss_create_project', { name: 'test-project', root_path: '/tmp/test' }) assert project['id'] # Step 2: Setup Figma result = await mcp_server.call_tool('dss_setup_figma_credentials', { api_token: TEST_FIGMA_TOKEN }) assert result['configured'] # Step 3: Discover files files = await mcp_server.call_tool('dss_discover_figma_files', { project_id: project['id'] }) assert len(files) > 0 # Step 4: Sync tokens tokens = await mcp_server.call_tool('dss_sync_tokens', { project_id: project['id'] }) assert tokens['count'] > 0 ``` ### 4.2 API Documentation **File:** `docs/MCP_API_REFERENCE.md` ```markdown # MCP Tools Reference ## dss_create_project Creates a new design system project. **Parameters:** - `name` (string, required): Project name - `root_path` (string, required): Root directory path - `description` (string, optional): Project description **Returns:** ```json { "id": "proj_12345", "name": "web-ui", "root_path": "/projects/web-ui", "created_at": "2025-12-06T00:00:00Z", "state": "created" } ``` **Errors:** - `ProjectAlreadyExists`: Project with this name exists - `InvalidPath`: Root path is invalid - `PermissionDenied`: No permission to create project ``` --- ## Architecture Workflows ### Workflow 1: Create Project with Figma ``` ┌─────────────────┐ │ User Input: │ │ "Create web-ui │ │ project with │ │ Figma" │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ JavaScript │ │ Parse command │ └────────┬────────┘ │ ▼ ┌─────────────────┐ │ Send to Claude │ │ with MCP tools │ └────────┬────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Claude orchestrates: │ │ 1. Check Figma token configured │ │ 2. Create project (MCP tool) │ │ 3. Setup Figma (MCP tool) │ │ 4. Discover files (MCP tool) │ │ 5. Return summary │ └────────┬────────────────────────────┘ │ ▼ ┌─────────────────────────────────────┐ │ Each MCP Tool: │ │ - Validates input │ │ - Updates database │ │ - Updates project state │ │ - Logs operation │ │ - Returns result │ └────────┬────────────────────────────┘ │ ▼ ┌─────────────────┐ │ Update UI │ │ with results │ └─────────────────┘ ``` ### Workflow 2: Sync Tokens from Figma ``` User: "Sync tokens from Figma" │ ▼ JavaScript → Claude │ ▼ Claude calls MCP tools sequentially: 1. dss_get_project(current_project_id) → Get current project 2. dss_list_figma_files(project_id) → Get linked Figma files 3. For each file: dss_sync_tokens(project_id, file_id) → Extract and sync tokens 4. dss_get_token_drift(project_id) → Check for inconsistencies │ ▼ Return results → Update UI → Show to user ``` --- ## Key Configuration Files ### MCP Server Config **File:** `tools/dss_mcp/config.py` ```python MCP_CONFIG = { 'server_name': 'dss', 'version': '1.0.0', 'tools': [ 'dss_create_project', 'dss_list_projects', # ... all 15+ tools ], 'database': { 'type': 'sqlite', 'path': '.dss/dss.db' }, 'credentials': { 'encryption_key': os.environ.get('DSS_ENCRYPTION_KEY'), 'salt': os.environ.get('DSS_ENCRYPTION_SALT') }, 'logging': { 'level': 'INFO', 'file': '.dss/logs/dss.log' } } ``` ### REST Bridge (Temporary) **File:** `tools/api/mcp_bridge.py` ```python from fastapi import APIRouter, HTTPException from dss_mcp.server import mcp_server router = APIRouter(prefix="/api/mcp") @router.post("/call") async def call_mcp_tool(request: ToolCallRequest): """ Bridge REST calls to MCP tools. Temporary during migration. Will be removed once all clients use MCP directly. """ try: result = await mcp_server.call_tool( request.tool, request.args ) return {'success': True, 'result': result} except Exception as e: logger.error(f"MCP tool error: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.get("/tools") async def list_mcp_tools(): """List all available MCP tools""" return {'tools': mcp_server.get_tools()} ``` --- ## Rollout Strategy ### Week 1-3: Backend Only - Implement MCP tools - Test tools thoroughly - Deploy MCP server - REST still primary ### Week 4-5: Parallel Operation - Update JavaScript to use MCP tools - REST bridge for compatibility - All new features use MCP only - Gradual migration of old features ### Week 6+: MCP Primary - Most operations via MCP - REST endpoints deprecated - Documentation updated - Monitoring in place --- ## Monitoring & Metrics ### Key Metrics to Track ```python # In dss_mcp/metrics.py metrics = { 'tool_calls_total': Counter('MCP tool calls'), 'tool_call_duration': Histogram('Tool execution time'), 'tool_errors': Counter('Tool errors by type'), 'operation_queue_depth': Gauge('Operations waiting'), 'database_queries': Counter('Database operations'), 'credential_rotations': Counter('Encryption key rotations') } ``` --- ## Troubleshooting Guide ### Problem: "Tool not found" **Solution:** Verify tool is registered in MCP server ### Problem: "Credential encryption failed" **Solution:** Check encryption key environment variable ### Problem: "State transition invalid" **Solution:** Project state doesn't allow this operation ### Problem: "Operation timeout" **Solution:** Long-running operation in queue, check logs --- ## References - [Existing ARCHITECTURE_MCP_FIRST.md](./ARCHITECTURE_MCP_FIRST.md) - [Component Audit](./COMPONENT_AUDIT.md) - [MCP Tools Spec](./MCP_TOOLS_SPEC.md) - [FastMCP Documentation](https://github.com/jlowin/FastMCP)