# 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 = `
            <div class="project-card">
                <h3>${project.name}</h3>
                <p>${project.description}</p>
                <span class="status ${project.state}">
                    ${project.state}
                </span>
            </div>
        `;
    }
}
```

---

## 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)
