Files
dss/dss/mcp/plugins/_template.py
Bruno Sarlo 41fba59bf7 Major refactor: Consolidate DSS into unified package structure
- Create new dss/ Python package at project root
- Move MCP core from tools/dss_mcp/ to dss/mcp/
- Move storage layer from tools/storage/ to dss/storage/
- Move domain logic from dss-mvp1/dss/ to dss/
- Move services from tools/api/services/ to dss/services/
- Move API server to apps/api/
- Move CLI to apps/cli/
- Move Storybook assets to storybook/
- Create unified dss/__init__.py with comprehensive exports
- Merge configuration into dss/settings.py (Pydantic-based)
- Create pyproject.toml for proper package management
- Update startup scripts for new paths
- Remove old tools/ and dss-mvp1/ directories

Architecture changes:
- DSS is now MCP-first with 40+ tools for Claude Code
- Clean imports: from dss import Projects, Components, FigmaToolSuite
- No more sys.path.insert() hacking
- apps/ contains thin application wrappers (API, CLI)
- Single unified Python package for all DSS logic

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 12:46:43 -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
"""