- 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>
218 lines
6.9 KiB
Python
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
|
|
"""
|