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