Migrated from design-system-swarm with fresh git history.
Old project history preserved in /home/overbits/apps/design-system-swarm
Core components:
- MCP Server (Python FastAPI with mcp 1.23.1)
- Claude Plugin (agents, commands, skills, strategies, hooks, core)
- DSS Backend (dss-mvp1 - token translation, Figma sync)
- Admin UI (Node.js/React)
- Server (Node.js/Express)
- Storybook integration (dss-mvp1/.storybook)
Self-contained configuration:
- All paths relative or use DSS_BASE_PATH=/home/overbits/dss
- PYTHONPATH configured for dss-mvp1 and dss-claude-plugin
- .env file with all configuration
- Claude plugin uses ${CLAUDE_PLUGIN_ROOT} for portability
Migration completed: $(date)
🤖 Clean migration with full functionality preserved
146 lines
4.8 KiB
Python
146 lines
4.8 KiB
Python
"""
|
|
MCP Server Configuration
|
|
|
|
Loads configuration from environment variables and provides settings
|
|
for the MCP server, integrations, and security.
|
|
"""
|
|
|
|
import os
|
|
from pathlib import Path
|
|
from typing import Optional
|
|
from dotenv import load_dotenv
|
|
from cryptography.fernet import Fernet
|
|
|
|
# Load environment variables
|
|
load_dotenv()
|
|
|
|
# Base paths
|
|
PROJECT_ROOT = Path(__file__).parent.parent.parent
|
|
TOOLS_DIR = PROJECT_ROOT / "tools"
|
|
STORAGE_DIR = PROJECT_ROOT / "tools" / "storage"
|
|
CACHE_DIR = PROJECT_ROOT / os.getenv("DSS_CACHE_DIR", ".dss/cache")
|
|
|
|
|
|
class MCPConfig:
|
|
"""MCP Server Configuration"""
|
|
|
|
# Server Settings
|
|
HOST: str = os.getenv("DSS_MCP_HOST", "127.0.0.1")
|
|
PORT: int = int(os.getenv("DSS_MCP_PORT", "3457"))
|
|
|
|
# Database
|
|
DATABASE_PATH: str = os.getenv(
|
|
"DATABASE_PATH",
|
|
str(STORAGE_DIR / "dss.db")
|
|
)
|
|
|
|
# Context Caching
|
|
CONTEXT_CACHE_TTL: int = int(os.getenv("DSS_CONTEXT_CACHE_TTL", "300")) # 5 minutes
|
|
|
|
# Encryption
|
|
ENCRYPTION_KEY: Optional[str] = os.getenv("DSS_ENCRYPTION_KEY")
|
|
|
|
@classmethod
|
|
def get_cipher(cls) -> Optional[Fernet]:
|
|
"""Get Fernet cipher for encryption/decryption"""
|
|
if not cls.ENCRYPTION_KEY:
|
|
return None
|
|
return Fernet(cls.ENCRYPTION_KEY.encode())
|
|
|
|
@classmethod
|
|
def generate_encryption_key(cls) -> str:
|
|
"""Generate a new encryption key"""
|
|
return Fernet.generate_key().decode()
|
|
|
|
# Redis/Celery for worker pool
|
|
REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379/0")
|
|
CELERY_BROKER_URL: str = os.getenv("CELERY_BROKER_URL", "redis://localhost:6379/0")
|
|
CELERY_RESULT_BACKEND: str = os.getenv("CELERY_RESULT_BACKEND", "redis://localhost:6379/0")
|
|
|
|
# Circuit Breaker
|
|
CIRCUIT_BREAKER_FAILURE_THRESHOLD: int = int(
|
|
os.getenv("CIRCUIT_BREAKER_FAILURE_THRESHOLD", "5")
|
|
)
|
|
CIRCUIT_BREAKER_TIMEOUT_SECONDS: int = int(
|
|
os.getenv("CIRCUIT_BREAKER_TIMEOUT_SECONDS", "60")
|
|
)
|
|
|
|
# Logging
|
|
LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO").upper()
|
|
|
|
|
|
class IntegrationConfig:
|
|
"""External Integration Configuration"""
|
|
|
|
# Figma
|
|
FIGMA_TOKEN: Optional[str] = os.getenv("FIGMA_TOKEN")
|
|
FIGMA_CACHE_TTL: int = int(os.getenv("FIGMA_CACHE_TTL", "300"))
|
|
|
|
# Anthropic (for Sequential Thinking)
|
|
ANTHROPIC_API_KEY: Optional[str] = os.getenv("ANTHROPIC_API_KEY")
|
|
|
|
# Jira (defaults, can be overridden per-user)
|
|
JIRA_URL: Optional[str] = os.getenv("JIRA_URL")
|
|
JIRA_USERNAME: Optional[str] = os.getenv("JIRA_USERNAME")
|
|
JIRA_API_TOKEN: Optional[str] = os.getenv("JIRA_API_TOKEN")
|
|
|
|
# Confluence (defaults, can be overridden per-user)
|
|
CONFLUENCE_URL: Optional[str] = os.getenv("CONFLUENCE_URL")
|
|
CONFLUENCE_USERNAME: Optional[str] = os.getenv("CONFLUENCE_USERNAME")
|
|
CONFLUENCE_API_TOKEN: Optional[str] = os.getenv("CONFLUENCE_API_TOKEN")
|
|
|
|
|
|
# Singleton instances
|
|
mcp_config = MCPConfig()
|
|
integration_config = IntegrationConfig()
|
|
|
|
|
|
def validate_config() -> list[str]:
|
|
"""
|
|
Validate configuration and return list of warnings.
|
|
|
|
Returns:
|
|
List of warning messages for missing optional config
|
|
"""
|
|
warnings = []
|
|
|
|
if not mcp_config.ENCRYPTION_KEY:
|
|
warnings.append(
|
|
"DSS_ENCRYPTION_KEY not set. Integration credentials will not be encrypted. "
|
|
f"Generate one with: python -c \"from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())\""
|
|
)
|
|
|
|
if not integration_config.ANTHROPIC_API_KEY:
|
|
warnings.append("ANTHROPIC_API_KEY not set. Sequential Thinking tools will not be available.")
|
|
|
|
if not integration_config.FIGMA_TOKEN:
|
|
warnings.append("FIGMA_TOKEN not set. Figma tools will not be available.")
|
|
|
|
return warnings
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print("=== DSS MCP Configuration ===\n")
|
|
print(f"MCP Server: {mcp_config.HOST}:{mcp_config.PORT}")
|
|
print(f"Database: {mcp_config.DATABASE_PATH}")
|
|
print(f"Context Cache TTL: {mcp_config.CONTEXT_CACHE_TTL}s")
|
|
print(f"Encryption Key: {'✓ Set' if mcp_config.ENCRYPTION_KEY else '✗ Not Set'}")
|
|
print(f"Redis URL: {mcp_config.REDIS_URL}")
|
|
print(f"\nCircuit Breaker:")
|
|
print(f" Failure Threshold: {mcp_config.CIRCUIT_BREAKER_FAILURE_THRESHOLD}")
|
|
print(f" Timeout: {mcp_config.CIRCUIT_BREAKER_TIMEOUT_SECONDS}s")
|
|
|
|
print(f"\n=== Integration Configuration ===\n")
|
|
print(f"Figma Token: {'✓ Set' if integration_config.FIGMA_TOKEN else '✗ Not Set'}")
|
|
print(f"Anthropic API Key: {'✓ Set' if integration_config.ANTHROPIC_API_KEY else '✗ Not Set'}")
|
|
print(f"Jira URL: {integration_config.JIRA_URL or '✗ Not Set'}")
|
|
print(f"Confluence URL: {integration_config.CONFLUENCE_URL or '✗ Not Set'}")
|
|
|
|
warnings = validate_config()
|
|
if warnings:
|
|
print(f"\n⚠️ Warnings:")
|
|
for warning in warnings:
|
|
print(f" - {warning}")
|
|
else:
|
|
print(f"\n✓ Configuration is valid")
|