Files
dss/tools/dss_mcp/plugins/_template.py
Digital Production Factory 276ed71f31 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
2025-12-09 18:45:48 -03:00

218 lines
6.9 KiB
Python

"""
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
"""