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:
Digital Production Factory
2025-12-09 18:45:48 -03:00
commit 276ed71f31
884 changed files with 373737 additions and 0 deletions

View File

@@ -0,0 +1,55 @@
"""
DSS MCP Server Plugins
This directory contains dynamically loaded plugins for the DSS MCP server.
Plugin Contract:
- Each plugin is a .py file in this directory
- Must export TOOLS: List[types.Tool] with MCP tool definitions
- Must have a handler class with execute_tool(name, arguments) method
- Optional: export PLUGIN_METADATA dict with name, version, author
Example Plugin Structure:
from mcp import types
PLUGIN_METADATA = {
"name": "My Plugin",
"version": "1.0.0",
"author": "DSS Team"
}
TOOLS = [
types.Tool(name="my_tool", description="...", inputSchema={...})
]
class PluginTools:
async def execute_tool(self, name, arguments):
if name == "my_tool":
return {"result": "success"}
Developer Workflow:
1. Copy _template.py to new_plugin.py
2. Edit TOOLS list and PluginTools class
3. (Optional) Create requirements.txt if plugin needs dependencies
4. Run: ../install_plugin_deps.sh (if dependencies added)
5. Restart MCP server: supervisorctl restart dss-mcp
6. Plugin tools are immediately available to all clients
Dependency Management:
- If your plugin needs Python packages, create a requirements.txt file
- Place it in the same directory as your plugin (e.g., plugins/my_plugin/requirements.txt)
- Run ../install_plugin_deps.sh to install all plugin dependencies
- Use --check flag to see which plugins have dependencies without installing
Example plugin with dependencies:
plugins/
├── my_plugin/
│ ├── __init__.py
│ ├── tool.py (exports TOOLS and PluginTools)
│ └── requirements.txt (jinja2>=3.1.2, httpx>=0.25.0)
└── _template.py
See _template.py for a complete example.
"""
__all__ = [] # Plugins are auto-discovered, not explicitly exported

View File

@@ -0,0 +1,217 @@
"""
Plugin Template for DSS MCP Server
This file serves as both documentation and a starting point for new plugins.
To create a new plugin:
1. Copy this file: cp _template.py my_plugin.py
2. Update PLUGIN_METADATA with your plugin details
3. Define your tools in the TOOLS list
4. Implement tool logic in the PluginTools class
5. Restart the MCP server
The plugin will be automatically discovered and registered.
"""
from typing import Dict, Any, List
from mcp import types
# =============================================================================
# 1. PLUGIN METADATA (Optional but recommended)
# =============================================================================
PLUGIN_METADATA = {
"name": "Template Plugin",
"version": "1.0.0",
"author": "DSS Team",
"description": "Template plugin demonstrating the plugin contract"
}
# =============================================================================
# 2. TOOLS DEFINITION (Required)
# =============================================================================
TOOLS = [
types.Tool(
name="template_hello",
description="A simple hello world tool to verify the plugin system works",
inputSchema={
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet (optional)",
"default": "World"
}
}
}
),
types.Tool(
name="template_echo",
description="Echo back the provided message",
inputSchema={
"type": "object",
"properties": {
"message": {
"type": "string",
"description": "Message to echo back"
},
"uppercase": {
"type": "boolean",
"description": "Convert to uppercase (optional)",
"default": False
}
},
"required": ["message"]
}
)
]
# =============================================================================
# 3. PLUGIN TOOLS HANDLER (Required)
# =============================================================================
class PluginTools:
"""
Handler class for plugin tools.
The PluginRegistry will instantiate this class and call execute_tool()
to handle tool invocations.
Contract:
- Must have async execute_tool(name: str, arguments: dict) method
- Should return list[types.TextContent | types.ImageContent | types.EmbeddedResource]
- Can raise exceptions for errors (will be caught and logged)
"""
def __init__(self, **kwargs):
"""
Initialize the plugin tools handler.
Args:
**kwargs: Optional context/dependencies (context_manager, user_id, etc.)
"""
# Extract any dependencies you need
self.context_manager = kwargs.get('context_manager')
self.user_id = kwargs.get('user_id')
self.audit_log = kwargs.get('audit_log')
# Initialize any plugin-specific state
self.call_count = 0
async def execute_tool(self, name: str, arguments: Dict[str, Any]) -> List:
"""
Route tool calls to appropriate implementation methods.
Args:
name: Tool name (matches TOOLS[].name)
arguments: Tool arguments from the client
Returns:
List of MCP content objects (TextContent, ImageContent, etc.)
Raises:
ValueError: If tool name is unknown
"""
self.call_count += 1
# Route to implementation methods
if name == "template_hello":
return await self._handle_hello(arguments)
elif name == "template_echo":
return await self._handle_echo(arguments)
else:
raise ValueError(f"Unknown tool: {name}")
async def _handle_hello(self, arguments: Dict[str, Any]) -> List[types.TextContent]:
"""
Implementation of template_hello tool.
Args:
arguments: Tool arguments (contains 'name')
Returns:
Greeting message
"""
name = arguments.get("name", "World")
message = f"Hello, {name}! The plugin system is operational. (Call #{self.call_count})"
return [
types.TextContent(
type="text",
text=message
)
]
async def _handle_echo(self, arguments: Dict[str, Any]) -> List[types.TextContent]:
"""
Implementation of template_echo tool.
Args:
arguments: Tool arguments (contains 'message' and optional 'uppercase')
Returns:
Echoed message
"""
message = arguments["message"]
uppercase = arguments.get("uppercase", False)
if uppercase:
message = message.upper()
return [
types.TextContent(
type="text",
text=f"Echo: {message}"
)
]
# =============================================================================
# NOTES FOR PLUGIN DEVELOPERS
# =============================================================================
"""
## Plugin Development Tips
### Error Handling
- The plugin loader catches exceptions during loading, so syntax errors won't crash the server
- Runtime exceptions in execute_tool() are caught and logged by the MCP server
- Return clear error messages to help users understand what went wrong
### Dependencies
- You can import from other DSS modules: from ..context.project_context import get_context_manager
- Keep dependencies minimal - plugins should be self-contained
- Standard library and existing DSS dependencies only (no new pip packages without discussion)
### Testing
- Test your plugin by:
1. Restarting the MCP server: supervisorctl restart dss-mcp
2. Using the MCP server directly via API: POST /api/tools/your_tool_name
3. Via Claude Code if connected to the MCP server
### Best Practices
- Use clear, descriptive tool names prefixed with your plugin name (e.g., "analytics_track_event")
- Provide comprehensive inputSchema with descriptions
- Return structured data using types.TextContent
- Log errors with logger.error() for debugging
- Keep tools focused - one tool should do one thing well
### Advanced Features
- For image results, use types.ImageContent
- For embedded resources, use types.EmbeddedResource
- Access project context via self.context_manager if injected
- Use async/await for I/O operations (API calls, database queries, etc.)
## Example Plugin Ideas
- **Network Logger**: Capture and analyze browser network requests
- **Performance Analyzer**: Measure component render times, bundle sizes
- **Workflow Helper**: Automate common development workflows
- **Integration Tools**: Connect to external services (Slack, GitHub, etc.)
- **Custom Validators**: Project-specific validation rules
"""

View File

@@ -0,0 +1,98 @@
"""
Hello World Plugin - Test Plugin for DSS MCP Server
Simple plugin to validate the plugin loading system is working correctly.
"""
from typing import Dict, Any, List
from mcp import types
PLUGIN_METADATA = {
"name": "Hello World Plugin",
"version": "1.0.0",
"author": "DSS Team",
"description": "Simple test plugin to validate plugin system"
}
TOOLS = [
types.Tool(
name="hello_world",
description="Simple hello world tool to test plugin loading",
inputSchema={
"type": "object",
"properties": {
"name": {
"type": "string",
"description": "Name to greet",
"default": "World"
}
}
}
),
types.Tool(
name="plugin_status",
description="Get status of the plugin system",
inputSchema={
"type": "object",
"properties": {}
}
)
]
class PluginTools:
"""Handler for hello world plugin tools"""
def __init__(self, **kwargs):
self.call_count = 0
async def execute_tool(self, name: str, arguments: Dict[str, Any]) -> List:
"""Execute tool by name"""
self.call_count += 1
if name == "hello_world":
return await self._hello_world(arguments)
elif name == "plugin_status":
return await self._plugin_status(arguments)
else:
raise ValueError(f"Unknown tool: {name}")
async def _hello_world(self, arguments: Dict[str, Any]) -> List[types.TextContent]:
"""Simple hello world implementation"""
name = arguments.get("name", "World")
message = (
f"Hello, {name}!\n\n"
f"✓ Plugin system is operational\n"
f"✓ Dynamic loading works correctly\n"
f"✓ Tool routing is functional\n"
f"✓ Call count: {self.call_count}"
)
return [
types.TextContent(
type="text",
text=message
)
]
async def _plugin_status(self, arguments: Dict[str, Any]) -> List[types.TextContent]:
"""Return plugin system status"""
status = {
"status": "operational",
"plugin_name": PLUGIN_METADATA["name"],
"plugin_version": PLUGIN_METADATA["version"],
"tools_count": len(TOOLS),
"call_count": self.call_count,
"tools": [tool.name for tool in TOOLS]
}
import json
return [
types.TextContent(
type="text",
text=json.dumps(status, indent=2)
)
]