# Storm Developments MCP Quickstart Tutorial
## Learn to Create Professional Development Assistant MCPs

Welcome to the comprehensive tutorial for creating enterprise-grade MCP servers using Storm Development patterns! This guide will teach you step-by-step how to build professional development assistant MCPs.

## 🎯 What You'll Learn

By the end of this tutorial, you'll know how to:
- Create modular MCP servers with enterprise architecture
- Implement professional tools and resources
- Add Storm Development branding and features
- Create robust validation and testing systems
- Deploy and maintain production-ready MCPs

## 📚 Prerequisites

Before starting, make sure you have:
- Python 3.10+ installed
- Basic knowledge of Python programming
- Familiarity with command line tools
- FastMCP library installed (`pip install fastmcp`)

## 🏗️ Understanding the Architecture

### Why Modular Design?
The Storm Development MCP architecture uses a **modular server pattern** that separates concerns:

**Benefits:**
- **Maintainability**: Each module handles specific functionality
- **Scalability**: Easy to add new features without breaking existing ones
- **Testability**: Each module can be tested independently
- **Reusability**: Modules can be shared across different MCP projects

### Project Structure Explained
```
my_dev_assistant_mcp/           # Your MCP project root
├── main.py                     # 🏠 Main server (the "brain")
├── run.sh                      # 🚀 Professional launcher
├── quick-start.sh             # ⚡ Quick development startup
├── servers/                   # 🧩 Specialized tool modules
│   ├── __init__.py
│   ├── core.py               # 🔧 Core development tools
│   ├── analysis.py           # 📊 Code analysis tools
│   ├── testing.py            # 🧪 Test generation tools
│   ├── security.py           # 🔒 Security and compliance
│   └── cicd.py               # 🔄 CI/CD optimization
├── shell_helpers/            # ✅ Validation scripts
│   ├── syntax_checker.py
│   ├── import_validator.py
│   └── server_healthcheck.py
└── pyproject.toml            # 📋 Project configuration
```

**Key Components:**
- **main.py**: The central server that coordinates everything
- **servers/**: Individual modules for different tool categories
- **shell_helpers/**: Scripts that validate your MCP before startup
- **run.sh**: Professional launcher with pre-flight checks

## 🚀 Tutorial: Building Your First Storm Development MCP

Let's build a complete MCP server step by step. We'll create a "Code Assistant MCP" that helps with development tasks.

### Step 1: Create the Project Structure

First, let's create our project directory and basic structure:

```bash
# Create project directory
mkdir storm-code-assistant-mcp
cd storm-code-assistant-mcp

# Create the directory structure
mkdir servers
mkdir shell_helpers
touch main.py
touch run.sh
touch quick-start.sh
touch pyproject.toml
touch servers/__init__.py
touch servers/core.py
touch servers/analysis.py
```

### Step 2: Understanding the Main Server

The `main.py` file is the **heart** of your MCP. It:
1. **Configures** the server with enterprise settings
2. **Mounts** specialized server modules
3. **Provides** global resources and health checks
4. **Manages** the server lifecycle

Let's build it step by step:

#### main.py - Start Simple, Build Complex

Let's start with a **basic version** and then enhance it. This helps you understand each piece:

**🔰 Basic Version (main.py)**
```python
"""
Storm Code Assistant MCP Server
Your first professional development MCP!
"""

import os
from fastmcp import FastMCP
from typing import Dict, Any

# Configuration - Keep it simple for now
SERVER_VERSION = "1.0.0"
DEFAULT_PROJECT_PATH = os.getcwd()

# Create your MCP server
mcp = FastMCP(
    name="Storm Code Assistant MCP",
    instructions="""
    🎯 **Storm Code Assistant MCP**
    
    Your personal development assistant for code analysis and improvement.
    
    **What I can do:**
    - Analyze your code quality
    - Generate documentation
    - Provide development recommendations
    - Help with project structure
    """,
    dependencies=[
        "fastmcp>=0.1.0"
    ]
)

# Your first tool - Simple but useful!
@mcp.tool
def analyze_file(file_path: str) -> str:
    """
    Analyze a Python file for basic quality metrics
    
    Args:
        file_path: Path to the Python file to analyze
        
    Returns:
        Analysis results in a friendly format
    """
    try:
        # Check if file exists
        if not os.path.exists(file_path):
            return f"❌ File not found: {file_path}"
        
        # Read the file
        with open(file_path, 'r') as f:
            content = f.read()
        
        # Basic analysis
        lines = content.splitlines()
        total_lines = len(lines)
        empty_lines = sum(1 for line in lines if not line.strip())
        has_docstring = '"""' in content or "'''" in content
        has_functions = 'def ' in content
        has_classes = 'class ' in content
        
        # Create a friendly report
        report = f"""
🔍 **Analysis Report for {file_path}**

📊 **Basic Metrics:**
- Total lines: {total_lines}
- Empty lines: {empty_lines}
- Code lines: {total_lines - empty_lines}

🔧 **Code Structure:**
- Has functions: {'✅' if has_functions else '❌'}
- Has classes: {'✅' if has_classes else '❌'}
- Has docstrings: {'✅' if has_docstring else '❌'}

💡 **Recommendations:**
"""
        
        # Add recommendations
        if not has_docstring:
            report += "- Add docstrings to explain what your code does\n"
        if not has_functions and not has_classes:
            report += "- Consider organizing code into functions or classes\n"
        if total_lines > 500:
            report += "- File is large - consider splitting into smaller modules\n"
        
        return report
        
    except Exception as e:
        return f"❌ Error analyzing file: {str(e)}"

# Your first resource - Project information
@mcp.resource("storm-code://project/info")
def get_project_info() -> Dict[str, Any]:
    """Get information about the current project"""
    return {
        "name": "Storm Code Assistant MCP",
        "version": SERVER_VERSION,
        "description": "Your first professional development MCP",
        "project_path": DEFAULT_PROJECT_PATH,
        "capabilities": [
            "File analysis",
            "Code quality assessment",
            "Development recommendations"
        ]
    }

# Run the server
if __name__ == "__main__":
    mcp.run()
```

### Step 3: Test Your Basic MCP

Let's test what we've built so far:

**🧪 Create a Test File (test_basic.py)**
```python
"""
Test your basic MCP server
"""

import asyncio
from fastmcp import Client

async def test_basic_mcp():
    """Test our basic MCP server"""
    print("🧪 Testing Storm Code Assistant MCP...")
    
    # Connect to our MCP
    client = Client("main.py")
    
    async with client:
        # Test the analyze_file tool
        print("\n📊 Testing file analysis...")
        result = await client.call_tool("analyze_file", {"file_path": "main.py"})
        print(result)
        
        # Test the project info resource
        print("\n📋 Testing project info...")
        info = await client.get_resource("storm-code://project/info")
        print(f"Project: {info['name']} v{info['version']}")
        print(f"Capabilities: {', '.join(info['capabilities'])}")
        
        print("\n✅ Basic MCP test completed!")

if __name__ == "__main__":
    asyncio.run(test_basic_mcp())
```

**🏃 Run Your Test:**
```bash
# In one terminal, start your MCP (we'll add the launcher later)
python main.py

# In another terminal, run the test
python test_basic.py
```

### Step 4: Understanding What You Built

**Congratulations! 🎉** You just created your first Storm Development MCP! Let's understand what each part does:

1. **FastMCP Creation**: `FastMCP(name="...", instructions="...")` creates your server
2. **@mcp.tool**: Decorates functions to make them available as tools
3. **@mcp.resource**: Decorates functions to provide information resources
4. **Error Handling**: Always handle errors gracefully (see the try/except in analyze_file)

### Step 5: Add Enterprise Features

Now let's enhance your MCP with **enterprise features**. Replace your basic main.py with this enhanced version:

**🚀 Enhanced Version (main.py)**

```python
"""
Storm Code Assistant MCP Server - Enhanced Version
Professional development intelligence with enterprise features
"""

import os
import yaml
from typing import Any, Dict, Optional, Set
from contextlib import asynccontextmanager
from pathlib import Path
from fastmcp import FastMCP
from fastmcp.server import MCP

# Configuration
SERVER_VERSION = "1.0.0"
DEFAULT_PROJECT_PATH = os.getcwd()

def custom_yaml_serializer(data: Any) -> str:
    """
    Custom YAML serializer for better tool output readability
    
    Why YAML? It's more readable than JSON for complex data structures
    """
    try:
        return yaml.dump(data, default_flow_style=False, allow_unicode=True, sort_keys=False, width=100, indent=2)
    except Exception:
        import json
        return json.dumps(data, indent=2)

@asynccontextmanager
async def lifespan(server: MCP):
    """
    Server lifespan management - runs code when server starts/stops
    This is where you can initialize databases, load models, etc.
    """
    # Startup
    print(f"🚀 Starting Storm Code Assistant MCP Server v{SERVER_VERSION}")
    print(f"📁 Project Path: {DEFAULT_PROJECT_PATH}")
    print(f"🏷️  Environment: {os.getenv('STORM_MCP_ENV', 'development')}")
    
    yield  # Server runs here
    
    # Shutdown
    print("🛑 Shutting down Storm Code Assistant MCP Server")

def create_enhanced_mcp_server() -> FastMCP:
    """
    Create an enhanced MCP server with enterprise features
    
    This function demonstrates:
    - Environment-based configuration
    - Tag-based tool filtering
    - Professional server setup
    """
    # Environment-based configuration
    environment = os.getenv("STORM_MCP_ENV", "development")
    
    # Tag filtering - controls which tools are available
    include_tags: Optional[Set[str]] = None
    exclude_tags: Optional[Set[str]] = None
    
    if environment == "production":
        include_tags = {"public", "stable"}
        exclude_tags = {"experimental", "debug"}
    elif environment == "testing":
        include_tags = {"public", "testing", "stable"}
        exclude_tags = {"experimental", "debug"}
    # Development environment includes all tools
    
    # Create the enhanced server
    server = FastMCP(
        name="Storm Code Assistant MCP Server",
        instructions="""
        🎯 **Storm Code Assistant MCP Server**
        
        Your professional development assistant with enterprise features.
        
        **Enhanced Capabilities:**
        - Smart code analysis with recommendations
        - Project structure optimization
        - Development workflow suggestions
        - Enterprise-grade error handling
        
        **Tag System:**
        - public: Safe for all users
        - experimental: Beta features
        - stable: Production-ready tools
        """,
        dependencies=[
            "fastmcp>=0.1.0",
            "pyyaml>=6.0"
        ],
        include_tags=include_tags,
        exclude_tags=exclude_tags,
        tool_serializer=custom_yaml_serializer,
        lifespan=lifespan,
        log_level=os.getenv("STORM_MCP_LOG_LEVEL", "INFO")
    )
    
    return server

# Create the enhanced server
mcp = create_enhanced_mcp_server()

# Enhanced tools with tags and better functionality
@mcp.tool
def analyze_project_structure(project_path: str = None) -> str:
    """
    Analyze entire project structure with detailed recommendations
    
    Args:
        project_path: Path to project (defaults to current directory)
        
    Returns:
        Comprehensive project analysis
    """
    # Tags: public, stable
    if project_path is None:
        project_path = os.getcwd()
    
    path = Path(project_path)
    if not path.exists():
        return f"❌ Project path {project_path} does not exist"
    
    # Advanced analysis
    analysis = {
        "project_info": {
            "name": path.name,
            "path": str(path),
            "type": "unknown"
        },
        "structure": {
            "total_files": 0,
            "python_files": 0,
            "test_files": 0,
            "config_files": 0,
            "doc_files": 0
        },
        "quality_indicators": {
            "has_tests": False,
            "has_docs": False,
            "has_config": False,
            "estimated_complexity": "unknown"
        },
        "recommendations": []
    }
    
    # Analyze project type
    if (path / "pyproject.toml").exists():
        analysis["project_info"]["type"] = "modern_python"
        analysis["quality_indicators"]["has_config"] = True
    elif (path / "setup.py").exists():
        analysis["project_info"]["type"] = "legacy_python"
        analysis["recommendations"].append("Consider migrating to pyproject.toml for modern Python packaging")
    
    # Count files and analyze structure
    for file_path in path.rglob("*"):
        if file_path.is_file():
            analysis["structure"]["total_files"] += 1
            
            if file_path.suffix == ".py":
                analysis["structure"]["python_files"] += 1
            elif "test" in file_path.name.lower() or file_path.parent.name == "tests":
                analysis["structure"]["test_files"] += 1
                analysis["quality_indicators"]["has_tests"] = True
            elif file_path.suffix in [".md", ".rst", ".txt"]:
                analysis["structure"]["doc_files"] += 1
                analysis["quality_indicators"]["has_docs"] = True
            elif file_path.name in ["pyproject.toml", "setup.py", "requirements.txt", "Pipfile"]:
                analysis["structure"]["config_files"] += 1
    
    # Generate intelligent recommendations
    if not analysis["quality_indicators"]["has_tests"]:
        analysis["recommendations"].append("🧪 Add test files to improve code reliability")
    if not analysis["quality_indicators"]["has_docs"]:
        analysis["recommendations"].append("📚 Add documentation to help users understand your project")
    if analysis["structure"]["python_files"] > 10 and analysis["structure"]["test_files"] == 0:
        analysis["recommendations"].append("⚠️ Large project without tests - consider implementing comprehensive testing")
    
    # Estimate complexity
    if analysis["structure"]["python_files"] < 5:
        analysis["quality_indicators"]["estimated_complexity"] = "simple"
    elif analysis["structure"]["python_files"] < 20:
        analysis["quality_indicators"]["estimated_complexity"] = "moderate"
    else:
        analysis["quality_indicators"]["estimated_complexity"] = "complex"
    
    return custom_yaml_serializer(analysis)

@mcp.tool
def generate_project_readme(project_path: str = None) -> str:
    """
    Generate a professional README.md for your project
    
    Args:
        project_path: Path to project
        
    Returns:
        Generated README content
    """
    # Tags: public, stable
    if project_path is None:
        project_path = os.getcwd()
    
    path = Path(project_path)
    project_name = path.name
    
    # Generate comprehensive README
    readme_content = f"""# {project_name}

## Overview
A professional development project built with Storm Development best practices.

## Features
- 🚀 Modern Python architecture
- 🧪 Comprehensive testing
- 📚 Professional documentation
- 🔧 Enterprise-grade tooling

## Installation

### Prerequisites
- Python 3.8+
- pip or poetry

### Quick Install
```bash
# Clone the repository
git clone <repository-url>
cd {project_name}

# Install dependencies
pip install -e .

# Or with poetry
poetry install
```

## Usage

### Basic Usage
```python
from {project_name} import main_function

# Example usage
result = main_function()
print(result)
```

### Advanced Features
```python
# Add your advanced usage examples here
```

## Development

### Setting up Development Environment
```bash
# Install development dependencies
pip install -e .[dev]

# Run tests
pytest

# Run linting
ruff check .

# Format code
black .
```

### Running Tests
```bash
# Run all tests
pytest

# Run with coverage
pytest --cov={project_name} --cov-report=html

# Run specific test file
pytest tests/test_specific.py
```

## Contributing

1. Fork the repository
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request

## License

This project is licensed under the MIT License - see the LICENSE file for details.

## Support

For support, please open an issue on GitHub or contact the development team.

---

Built with ❤️ using Storm Development patterns
"""
    
    return readme_content

# Enhanced resources
@mcp.resource("storm-code://server/info")
def get_enhanced_server_info() -> Dict[str, Any]:
    """Get comprehensive server information with enterprise features"""
    return {
        "name": "Storm Code Assistant MCP Server",
        "version": SERVER_VERSION,
        "description": "Professional development intelligence with enterprise features",
        "project_path": DEFAULT_PROJECT_PATH,
        "environment": os.getenv("STORM_MCP_ENV", "development"),
        "capabilities": {
            "project_analysis": "Comprehensive project structure analysis",
            "code_quality": "Advanced code quality assessment",
            "documentation": "Automated documentation generation",
            "recommendations": "Intelligent development recommendations"
        },
        "enterprise_features": {
            "tag_filtering": "Environment-based tool filtering",
            "yaml_serialization": "Improved output readability",
            "lifecycle_management": "Professional server lifecycle",
            "error_handling": "Robust error handling and logging"
        }
    }

@mcp.resource("storm-code://server/health")
def get_server_health() -> Dict[str, Any]:
    """Get server health status with detailed diagnostics"""
    project_path = Path(DEFAULT_PROJECT_PATH)
    
    return {
        "status": "healthy",
        "timestamp": __import__("datetime").datetime.now().isoformat(),
        "checks": {
            "project_path_exists": project_path.exists(),
            "project_path_readable": project_path.is_dir() if project_path.exists() else False,
            "environment_configured": bool(os.getenv("STORM_MCP_ENV")),
            "yaml_available": True  # We imported it successfully
        },
        "configuration": {
            "project_path": str(project_path),
            "environment": os.getenv("STORM_MCP_ENV", "development"),
            "log_level": os.getenv("STORM_MCP_LOG_LEVEL", "INFO"),
            "server_version": SERVER_VERSION
        }
    }

if __name__ == "__main__":
    mcp.run()
```

### Step 6: Understanding Enterprise Features

Let's understand what makes this version **enterprise-grade**:

**🏷️ Tag System:**
- Tools can be tagged (public, experimental, stable)
- Environment controls which tools are available
- Production environments only show stable, public tools

**🔧 Lifecycle Management:**
- Server startup/shutdown hooks
- Professional logging and status messages
- Environment-based configuration

**📊 Enhanced Analysis:**
- Comprehensive project structure analysis
- Intelligent recommendations
- Professional YAML output formatting

**🛡️ Error Handling:**
- Robust error handling in all functions
- Graceful degradation when services fail
- Professional error messages

### Step 7: Advanced Testing

Create an enhanced test to verify all features:

**🧪 Enhanced Test File (test_enhanced.py)**
```python
"""
Enhanced test for Storm Code Assistant MCP Server
"""

import asyncio
import os
import tempfile
from pathlib import Path
from fastmcp import Client

async def test_enhanced_mcp():
    """Test enhanced MCP features"""
    print("🧪 Testing Enhanced Storm Code Assistant MCP...")
    
    client = Client("main.py")
    
    async with client:
        # Test server info
        print("\n📋 Testing enhanced server info...")
        info = await client.get_resource("storm-code://server/info")
        print(f"Server: {info['name']} v{info['version']}")
        print(f"Environment: {info['environment']}")
        print(f"Enterprise Features: {list(info['enterprise_features'].keys())}")
        
        # Test health check
        print("\n🏥 Testing health check...")
        health = await client.get_resource("storm-code://server/health")
        print(f"Status: {health['status']}")
        print(f"All checks passed: {all(health['checks'].values())}")
        
        # Test project analysis
        print("\n📊 Testing project structure analysis...")
        analysis = await client.call_tool("analyze_project_structure", {})
        print("✅ Project analysis completed")
        
        # Test README generation
        print("\n📚 Testing README generation...")
        readme = await client.call_tool("generate_project_readme", {})
        print(f"✅ README generated ({len(readme)} characters)")
        
        # Test with different environment
        print("\n🌍 Testing environment configuration...")
        original_env = os.getenv("STORM_MCP_ENV")
        os.environ["STORM_MCP_ENV"] = "production"
        print(f"Environment set to: {os.getenv('STORM_MCP_ENV')}")
        if original_env:
            os.environ["STORM_MCP_ENV"] = original_env
        else:
            del os.environ["STORM_MCP_ENV"]
        
        print("\n✅ All enhanced tests completed!")

if __name__ == "__main__":
    asyncio.run(test_enhanced_mcp())
```

## 🎓 Learning Exercises

Now that you understand the basics, try these exercises to deepen your knowledge:

### Exercise 1: Add a New Tool
Create a tool that counts TODO comments in Python files:

```python
@mcp.tool
def count_todos(directory_path: str = ".") -> str:
    """Count TODO comments in Python files"""
    # Your implementation here
    pass
```

### Exercise 2: Add Environment-Specific Features
Create a tool that only works in development mode:

```python
@mcp.tool
def debug_project(project_path: str = None) -> str:
    """Debug tool - only available in development"""
    # Tags: experimental, debug
    # Your implementation here
    pass
```

### Exercise 3: Create a Custom Resource
Add a resource that provides development statistics:

```python
@mcp.resource("storm-code://stats/development")
def get_development_stats() -> Dict[str, Any]:
    """Get development statistics"""
    # Your implementation here
    pass
```

## 🧩 Advanced: Modular Server Architecture

For larger projects, you'll want to organize tools into separate modules. Here's how:

### servers/core.py - Your First Module
```python
"""
Core development tools for Storm Development Assistant MCP
This module demonstrates how to create reusable tool collections
"""

from fastmcp import FastMCP
from typing import Dict, Any
import json
import os
from pathlib import Path

def create_core_server() -> FastMCP:
    """
    Create a specialized server for core development tools
    
    This pattern allows you to:
    - Organize tools by category
    - Test modules independently
    - Reuse modules across projects
    """
    server = FastMCP("Storm Development Core Tools")
    
    @server.tool
    def count_lines_of_code(directory_path: str = ".") -> str:
        """
        Count lines of code in a project directory
        
        Args:
            directory_path: Path to analyze
            
        Returns:
            Code statistics
        """
        path = Path(directory_path)
        if not path.exists():
            return json.dumps({"error": f"Directory {directory_path} does not exist"})
        
        stats = {
            "total_files": 0,
            "total_lines": 0,
            "code_lines": 0,
            "comment_lines": 0,
            "empty_lines": 0,
            "file_breakdown": {}
        }
        
        # Analyze Python files
        for file_path in path.rglob("*.py"):
            if file_path.is_file():
                stats["total_files"] += 1
                
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        lines = f.readlines()
                    
                    file_stats = {
                        "total": len(lines),
                        "code": 0,
                        "comments": 0,
                        "empty": 0
                    }
                    
                    for line in lines:
                        stripped = line.strip()
                        if not stripped:
                            file_stats["empty"] += 1
                        elif stripped.startswith("#"):
                            file_stats["comments"] += 1
                        else:
                            file_stats["code"] += 1
                    
                    stats["total_lines"] += file_stats["total"]
                    stats["code_lines"] += file_stats["code"]
                    stats["comment_lines"] += file_stats["comments"]
                    stats["empty_lines"] += file_stats["empty"]
                    
                    stats["file_breakdown"][str(file_path.relative_to(path))] = file_stats
                    
                except Exception as e:
                    print(f"Error reading {file_path}: {e}")
        
        return json.dumps(stats, indent=2)
    
    @server.tool
    def find_large_files(directory_path: str = ".", max_lines: int = 200) -> str:
        """
        Find files that are larger than the specified line count
        
        Args:
            directory_path: Path to analyze
            max_lines: Maximum lines threshold
            
        Returns:
            List of large files with recommendations
        """
        path = Path(directory_path)
        large_files = []
        
        for file_path in path.rglob("*.py"):
            if file_path.is_file():
                try:
                    with open(file_path, 'r', encoding='utf-8') as f:
                        line_count = sum(1 for _ in f)
                    
                    if line_count > max_lines:
                        large_files.append({
                            "file": str(file_path.relative_to(path)),
                            "lines": line_count,
                            "severity": "high" if line_count > 500 else "medium",
                            "recommendation": "Consider splitting into smaller modules"
                        })
                        
                except Exception as e:
                    print(f"Error reading {file_path}: {e}")
        
        result = {
            "threshold": max_lines,
            "large_files_found": len(large_files),
            "files": sorted(large_files, key=lambda x: x["lines"], reverse=True)
        }
        
        return json.dumps(result, indent=2)
    
    return server

# Example of how to use the module
if __name__ == "__main__":
    # This allows you to test the module independently
    test_server = create_core_server()
    print("Core server created with tools:", [tool.name for tool in test_server.tools])
```

### How to Use Modular Servers

**1. Create the Module Structure:**
```bash
mkdir servers
touch servers/__init__.py
touch servers/core.py
touch servers/analysis.py
```

**2. Update Your Main Server:**
```python
# In main.py, add this to mount the modules
from servers.core import create_core_server

# Mount the specialized server
core_server = create_core_server()
mcp.mount(core_server, prefix="core")
```

**3. Test Individual Modules:**
```python
# Test just the core module
python servers/core.py
```

## 🚀 Professional Launcher Scripts

Add professional startup scripts to your MCP:

### quick-start.sh - Development Launcher
```bash
#!/bin/bash
# ⚡ Storm Code Assistant MCP Quick Start ⚡

echo "🚀 Starting Storm Code Assistant MCP in development mode..."

# Set development environment
export STORM_MCP_ENV=development
export STORM_MCP_LOG_LEVEL=DEBUG

# Change to script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"

# Start the server
python main.py
```

### run.sh - Production Launcher
```bash
#!/bin/bash
# ⚡ Storm Code Assistant MCP Production Launcher ⚡

set -e

# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

echo -e "${GREEN}⚡ Storm Code Assistant MCP Production Launcher ⚡${NC}"
echo

# Check prerequisites
echo "🔍 Checking prerequisites..."

# Check Python
if ! command -v python3 &> /dev/null; then
    echo -e "${RED}❌ Python 3 is required but not installed${NC}"
    exit 1
fi

# Check FastMCP
if ! python3 -c "import fastmcp" &> /dev/null; then
    echo -e "${RED}❌ FastMCP is required but not installed${NC}"
    echo "Install with: pip install fastmcp"
    exit 1
fi

# Check project structure
if [ ! -f "main.py" ]; then
    echo -e "${RED}❌ main.py not found${NC}"
    exit 1
fi

echo -e "${GREEN}✅ All prerequisites satisfied${NC}"
echo

# Set production environment
export STORM_MCP_ENV=production
export STORM_MCP_LOG_LEVEL=INFO

# Change to script directory
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
cd "$SCRIPT_DIR"

echo "🚀 Starting Storm Code Assistant MCP in production mode..."
python main.py
```

### Make Scripts Executable
```bash
chmod +x quick-start.sh
chmod +x run.sh
```

## 🧪 Comprehensive Testing Strategy

### test_complete.py - Full Test Suite
```python
"""
Comprehensive test suite for Storm Code Assistant MCP
"""

import asyncio
import os
import tempfile
import pytest
from pathlib import Path
from fastmcp import Client

class TestStormCodeAssistantMCP:
    """Professional test suite for your MCP"""
    
    @pytest.fixture
    def client(self):
        """Create a test client"""
        return Client("main.py")
    
    @pytest.fixture
    def temp_project(self):
        """Create a temporary project for testing"""
        with tempfile.TemporaryDirectory() as temp_dir:
            project_path = Path(temp_dir)
            
            # Create sample files
            (project_path / "main.py").write_text('''
"""Sample Python file"""

def hello_world():
    """Say hello to the world"""
    print("Hello, World!")
    
if __name__ == "__main__":
    hello_world()
''')
            
            (project_path / "requirements.txt").write_text("fastmcp>=0.1.0\n")
            (project_path / "README.md").write_text("# Sample Project\n\nThis is a test project.")
            
            yield str(project_path)
    
    async def test_server_health(self, client):
        """Test server health endpoint"""
        async with client:
            health = await client.get_resource("storm-code://server/health")
            assert health["status"] == "healthy"
            assert "timestamp" in health
            assert health["checks"]["yaml_available"] is True
    
    async def test_project_analysis(self, client, temp_project):
        """Test project structure analysis"""
        async with client:
            result = await client.call_tool("analyze_project_structure", {
                "project_path": temp_project
            })
            
            # Parse YAML result
            import yaml
            analysis = yaml.safe_load(result)
            
            assert analysis["project_info"]["name"] is not None
            assert analysis["structure"]["python_files"] > 0
            assert analysis["quality_indicators"]["has_config"] is True
    
    async def test_readme_generation(self, client, temp_project):
        """Test README generation"""
        async with client:
            readme = await client.call_tool("generate_project_readme", {
                "project_path": temp_project
            })
            
            assert "# " in readme  # Has title
            assert "## Overview" in readme
            assert "## Installation" in readme
            assert "Storm Development patterns" in readme
    
    async def test_environment_filtering(self, client):
        """Test environment-based tool filtering"""
        # Test with production environment
        os.environ["STORM_MCP_ENV"] = "production"
        
        async with client:
            # In production, only stable tools should be available
            info = await client.get_resource("storm-code://server/info")
            assert info["environment"] == "production"
        
        # Reset environment
        del os.environ["STORM_MCP_ENV"]

# Run tests
if __name__ == "__main__":
    pytest.main([__file__, "-v"])
```

### Run Tests
```bash
# Install pytest if not installed
pip install pytest pytest-asyncio

# Run the test suite
python test_complete.py
```

## 📚 Common Patterns and Best Practices

### 1. Error Handling Pattern
```python
@mcp.tool
def robust_tool(input_data: str) -> str:
    """Example of robust error handling"""
    try:
        # Validate input
        if not input_data:
            return json.dumps({"error": "Input data is required"})
        
        # Process data
        result = process_data(input_data)
        
        # Return success
        return json.dumps({"status": "success", "result": result})
        
    except ValueError as e:
        return json.dumps({"error": f"Invalid input: {str(e)}"})
    except Exception as e:
        return json.dumps({"error": f"Unexpected error: {str(e)}"})
```

### 2. Resource Pattern
```python
@mcp.resource("storm-code://data/template")
def get_template_data() -> Dict[str, Any]:
    """Provide reusable template data"""
    return {
        "templates": {
            "python_function": {
                "template": "def {name}():\n    \"\"\"{description}\"\"\"\n    pass",
                "variables": ["name", "description"]
            }
        }
    }
```

### 3. Configuration Pattern
```python
# Configuration with environment variables
class Config:
    def __init__(self):
        self.environment = os.getenv("STORM_MCP_ENV", "development")
        self.log_level = os.getenv("STORM_MCP_LOG_LEVEL", "INFO")
        self.project_path = os.getenv("STORM_PROJECT_PATH", os.getcwd())
        self.debug = self.environment == "development"
```

## 🎯 Next Steps

### Congratulations! 🎉

You've successfully learned how to create professional Storm Development MCPs! Here's what you've accomplished:

**✅ What You've Learned:**
- Created basic and enhanced MCP servers
- Implemented enterprise features and configuration
- Built modular, reusable tool collections
- Added professional launchers and validation
- Created comprehensive test suites

**🚀 What's Next:**
1. **Build Your Own MCP**: Create an MCP for your specific development needs
2. **Explore Advanced Features**: Add database integration, API connections, or ML models
3. **Contribute**: Share your MCP patterns with the Storm Development community
4. **Scale Up**: Build large-scale, enterprise-grade MCP systems

### Resources for Continued Learning

- **FastMCP Documentation**: Learn more advanced FastMCP features
- **Storm Logger MCP**: Study the complete implementation for advanced patterns
- **Community**: Join the Storm Development community for tips and best practices

### Common Next Projects

1. **Code Quality MCP**: Advanced static analysis and code quality tools
2. **Testing MCP**: Comprehensive test generation and validation
3. **Documentation MCP**: Automated documentation generation and maintenance
4. **CI/CD MCP**: Pipeline optimization and deployment automation

**Happy coding with Storm Development patterns! ⚡**

from fastmcp import FastMCP
from typing import Dict, Any, List, Optional
import json
import os
from pathlib import Path


def create_core_server() -> FastMCP:
    """Create core development tools server"""
    server = FastMCP("Storm Development Core Tools")
    
    @server.tool
    def analyze_project_structure(project_path: str = None) -> str:
        """
        Analyze project structure and organization
        
        Args:
            project_path: Path to project (defaults to current directory)
            
        Returns:
            JSON analysis of project structure
        """
        if project_path is None:
            project_path = os.getcwd()
        
        path = Path(project_path)
        if not path.exists():
            return json.dumps({"error": f"Project path {project_path} does not exist"})
        
        structure = {
            "project_path": str(path),
            "name": path.name,
            "type": "unknown",
            "files": {
                "total": 0,
                "python": 0,
                "tests": 0,
                "docs": 0,
                "config": 0
            },
            "structure": [],
            "recommendations": []
        }
        
        # Analyze project type
        if (path / "pyproject.toml").exists():
            structure["type"] = "python_package"
        elif (path / "setup.py").exists():
            structure["type"] = "python_legacy"
        elif (path / "package.json").exists():
            structure["type"] = "nodejs"
        
        # Count files
        for file_path in path.rglob("*"):
            if file_path.is_file():
                structure["files"]["total"] += 1
                if file_path.suffix == ".py":
                    structure["files"]["python"] += 1
                elif "test" in file_path.name.lower():
                    structure["files"]["tests"] += 1
                elif file_path.suffix in [".md", ".rst", ".txt"]:
                    structure["files"]["docs"] += 1
                elif file_path.name in ["pyproject.toml", "setup.py", "requirements.txt"]:
                    structure["files"]["config"] += 1
        
        # Generate recommendations
        if structure["files"]["tests"] == 0:
            structure["recommendations"].append("Add test files for better code quality")
        if structure["files"]["docs"] == 0:
            structure["recommendations"].append("Add documentation files")
        if structure["type"] == "python_legacy":
            structure["recommendations"].append("Consider migrating to pyproject.toml")
        
        return json.dumps(structure, indent=2)
    
    @server.tool
    def generate_project_documentation(project_path: str = None) -> str:
        """
        Generate comprehensive project documentation
        
        Args:
            project_path: Path to project
            
        Returns:
            Generated documentation content
        """
        if project_path is None:
            project_path = os.getcwd()
        
        path = Path(project_path)
        project_name = path.name
        
        docs = f"""# {project_name}

## Overview
Professional development tool created with Storm Development patterns.

## Installation
```bash
pip install -e .
```

## Quick Start
```python
from {project_name} import main_function

# Example usage
result = main_function()
print(result)
```

## Features
- Enterprise-grade architecture
- Comprehensive testing
- Security compliance
- Professional documentation

