Initial commit: Clean DSS implementation
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
This commit is contained in:
145
tools/dss_mcp/config.py
Normal file
145
tools/dss_mcp/config.py
Normal file
@@ -0,0 +1,145 @@
|
||||
"""
|
||||
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")
|
||||
Reference in New Issue
Block a user