Skip to main content
Glama

Security MCP Server

by nordeim
README.md71.5 kB
<div align="center"> # 🛡️ Security MCP Server ### Production-Ready Model Context Protocol Server for Network Security Tools [![Build Status](https://img.shields.io/badge/build-passing-brightgreen.svg)](https://github.com/nordeim/Security-MCP-Server) [![Coverage](https://img.shields.io/badge/coverage-85%25-green.svg)](https://github.com/nordeim/Security-MCP-Server) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/) [![Docker](https://img.shields.io/badge/docker-ready-blue.svg)](https://hub.docker.com/r/nordeim/security-mcp-server) [![MCP Protocol](https://img.shields.io/badge/MCP-1.0-purple.svg)](https://modelcontextprotocol.io) [Quick Start](#-quick-start) • [Documentation](#-table-of-contents) • [Examples](#-usage-guide) • [Contributing](#-contributing) </div> --- ## 📋 Table of Contents ### For Users - [Overview](#-overview) - [Quick Start](#-quick-start) - [Installation](#-installation--setup) - [Usage Guide](#-usage-guide) - [Deployment](#-deployment-guide) - [FAQ & Troubleshooting](#-faq--troubleshooting) ### For Developers - [Architecture](#-architecture) - [Developer Guide](#-developer-guide) - [Creating Custom Tools](#creating-custom-tools) - [Testing](#testing-guide) - [Contributing](#-contributing) ### For Operators - [Monitoring & Operations](#-monitoring--operations) - [Security](#-security) - [API Reference](#-api-reference) ### Additional - [Roadmap](#-roadmap) - [License](#-license--credits) --- ## 🌟 Overview ### What is Security MCP Server? Security MCP Server is a **production-ready** implementation of the [Model Context Protocol (MCP)](https://modelcontextprotocol.io) that provides AI agents (like Claude) with secure, controlled access to network security tools. It transforms command-line security utilities into safe, monitored, API-accessible services with comprehensive safety controls. ### 🎯 Key Features <table> <tr> <td width="33%"> #### 🔒 Security First - RFC1918/private IP enforcement - Command injection prevention - Whitelist-based validation - Resource limits - Intrusive operation controls </td> <td width="33%"> #### 🏗️ Production Ready - Circuit breaker pattern - Health monitoring - Prometheus metrics - Graceful shutdown - Hot-reload configuration </td> <td width="33%"> #### 🚀 Developer Friendly - Easy tool creation - Comprehensive testing - Clear documentation - Docker support - Extensible architecture </td> </tr> <tr> <td width="33%"> #### 🛠️ Tool Ecosystem - **Nmap** - Network scanning - **Extensible** - Add your own - **Template-based** - Quick scans - **Validated** - Safe inputs </td> <td width="33%"> #### 📊 Observability - Real-time health checks - Prometheus metrics - Structured logging - Performance tracking - Error monitoring </td> <td width="33%"> #### 🔄 Resilient - Auto-retry with backoff - Circuit breaker protection - Resource limits - Timeout enforcement - Graceful degradation </td> </tr> </table> ### 💡 Use Cases - **AI-Assisted Network Discovery**: Let Claude help you scan and analyze networks safely - **Automated Security Audits**: Run scheduled security scans with AI interpretation - **Lab Environment Management**: Safe tool execution in controlled environments - **Security Training**: Learn security tools with AI guidance - **Infrastructure Monitoring**: Combine network tools with AI analysis ### 🎬 Quick Demo ```bash # AI agent (Claude) asks: "Can you scan 192.168.1.0/24 for web servers?" # Security MCP Server: # ✓ Validates target (RFC1918 ✓) # ✓ Checks circuit breaker (CLOSED ✓) # ✓ Executes: nmap -sV -p 80,443 --top-ports 1000 192.168.1.0/24 # ✓ Records metrics # ✓ Returns structured results # Response: Found 5 hosts with HTTP/HTTPS services... ``` --- ## 🚀 Quick Start Get up and running in **under 5 minutes**! ### Prerequisites - ✅ Python 3.11 or higher - ✅ pip (Python package manager) - ✅ nmap installed (`sudo apt-get install nmap` on Ubuntu) - ✅ Virtual environment support (recommended) ### One-Command Installation ```bash # Clone the repository git clone https://github.com/nordeim/Security-MCP-Server.git cd Security-MCP-Server # Create virtual environment and install python -m venv venv source venv/bin/activate # On Windows: venv\Scripts\activate pip install -r requirements.txt ``` ### First Run ```bash # Start in HTTP mode for testing export MCP_SERVER_TRANSPORT=http python -m mcp_server.server # Server starts on http://localhost:8080 # ✓ Health check: http://localhost:8080/health # ✓ Tools list: http://localhost:8080/tools # ✓ Metrics: http://localhost:8080/metrics ``` ### Verify Installation ```bash # Check health curl http://localhost:8080/health # Expected response: { "status": "healthy", "timestamp": "2024-01-15T10:30:00Z", "checks": { "system_resources": {"status": "healthy", ...}, "process_health": {"status": "healthy", ...} } } # Test tool execution curl -X POST http://localhost:8080/tools/NmapTool/execute \ -H "Content-Type: application/json" \ -d '{ "target": "192.168.1.1", "extra_args": "-sV --top-ports 100" }' ``` ### Next Steps - 📖 Read the [Usage Guide](#-usage-guide) - 🔧 Configure for [Claude Desktop](#claude-desktop-integration) - 🐳 Try [Docker Deployment](#docker-installation) - 🛠️ Learn to [Create Custom Tools](#creating-custom-tools) --- ## 🏗️ Architecture ### System Architecture ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#0066cc','primaryTextColor':'#fff','primaryBorderColor':'#004499','lineColor':'#0066cc','secondaryColor':'#66ccff','tertiaryColor':'#fff'}}}%% graph TD A[AI Agent / Claude] -->|MCP Protocol| B[MCP Server] B --> C[Tool Registry] B --> D[Health Manager] B --> E[Metrics Manager] B --> F[Config Manager] C --> G[NmapTool] C --> H[Custom Tools] G --> I[Circuit Breaker] H --> I I --> J[Base Tool] J --> K[Input Validation] J --> L[Resource Limits] J --> M[Command Execution] D --> N[System Health] D --> O[Tool Health] D --> P[Dependency Health] E --> Q[Prometheus] E --> R[Internal Metrics] F --> S[Environment] F --> T[Config Files] F --> U[Defaults] style B fill:#0066cc,stroke:#004499,color:#fff style C fill:#66ccff,stroke:#0066cc style I fill:#ff9900,stroke:#cc7700 style D fill:#66cc66,stroke:#44aa44 style E fill:#cc66ff,stroke:#9944cc ``` ### Component Overview | Component | Responsibility | Key Features | |-----------|---------------|--------------| | **MCP Server** | Request handling, protocol compliance | Dual transport (stdio/HTTP), async execution | | **Tool Registry** | Tool discovery, lifecycle management | Auto-discovery, enable/disable, validation | | **Circuit Breaker** | Fault tolerance, failure prevention | Auto-recovery, adaptive timeout, metrics | | **Health Manager** | System monitoring, availability checks | Priority-based, staleness detection, aggregation | | **Metrics Manager** | Performance tracking, observability | Prometheus export, percentiles, caching | | **Base Tool** | Common tool functionality | Validation, execution, error handling | | **Config Manager** | Configuration loading, validation | Multi-source, hot-reload, type safety | ### Tool Execution Flow ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#0066cc','primaryTextColor':'#fff','primaryBorderColor':'#004499','lineColor':'#0066cc','secondaryColor':'#66ccff','tertiaryColor':'#fff'}}}%% sequenceDiagram participant AI as AI Agent participant MCP as MCP Server participant CB as Circuit Breaker participant Tool as Tool (e.g., Nmap) participant Metrics as Metrics AI->>MCP: Execute Tool Request MCP->>MCP: Validate Input alt Invalid Input MCP-->>AI: Validation Error end MCP->>CB: Check State alt Circuit Open CB-->>MCP: Circuit Open Error MCP-->>AI: Service Unavailable end CB->>Tool: Execute (with timeout) Tool->>Tool: Validate Target (RFC1918) Tool->>Tool: Sanitize Arguments Tool->>Tool: Apply Resource Limits Tool->>Tool: Execute Command alt Success Tool-->>CB: Success Result CB->>CB: Record Success CB->>Metrics: Record Metrics CB-->>MCP: Result MCP-->>AI: Formatted Response else Failure Tool-->>CB: Error Result CB->>CB: Record Failure CB->>Metrics: Record Failure alt Threshold Exceeded CB->>CB: Open Circuit end CB-->>MCP: Error MCP-->>AI: Error Response end ``` ### Health Check System ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#0066cc','primaryTextColor':'#fff','primaryBorderColor':'#004499','lineColor':'#0066cc','secondaryColor':'#66ccff','tertiaryColor':'#fff'}}}%% graph TD A[Health Check Manager] --> B{Run All Checks} B --> C[CRITICAL Priority] B --> D[IMPORTANT Priority] B --> E[INFORMATIONAL Priority] C --> C1[System Resources] C1 --> C1A[CPU < 80%] C1 --> C1B[Memory < 80%] C1 --> C1C[Disk < 80%] D --> D1[Process Health] D --> D2[Circuit Breakers] D1 --> D1A[Process Running] D1 --> D1B[Resource Usage OK] E --> E1[Tool Availability] E --> E2[Dependencies] E1 --> E1A[nmap Available] E1 --> E1B[Commands Resolve] C1 --> F{Aggregate Status} D1 --> F D2 --> F E1 --> F E2 --> F F -->|All CRITICAL OK| G[HEALTHY] F -->|Any CRITICAL Failed| H[UNHEALTHY] F -->|CRITICAL OK, IMPORTANT Failed| I[DEGRADED] style C fill:#ff4444,stroke:#cc0000,color:#fff style D fill:#ffaa44,stroke:#cc8800,color:#fff style E fill:#4444ff,stroke:#0000cc,color:#fff style G fill:#44ff44,stroke:#00cc00,color:#000 style H fill:#ff4444,stroke:#cc0000,color:#fff style I fill:#ffaa44,stroke:#cc8800,color:#000 ``` ### Technology Stack | Layer | Technologies | |-------|-------------| | **Protocol** | Model Context Protocol (MCP) 1.0 | | **Language** | Python 3.11+ | | **Async Framework** | asyncio, uvloop (optional) | | **Web Framework** | FastAPI, Uvicorn (HTTP mode) | | **Validation** | Pydantic v1/v2 compatible | | **Metrics** | Prometheus Client | | **Monitoring** | psutil, custom health checks | | **Configuration** | YAML, JSON, Environment Variables | | **Logging** | Python logging, structured output | | **Containerization** | Docker, Docker Compose | | **Testing** | pytest, pytest-asyncio | | **Security Tools** | nmap (extensible) | --- ## ✨ Features Deep Dive ### 🔒 Security Controls Security MCP Server implements **defense in depth** with multiple layers of protection: #### Network Restrictions - **RFC1918 Enforcement**: Only private IP ranges allowed (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) - **Domain Whitelisting**: Only `.lab.internal` domains permitted - **CIDR Validation**: Network ranges validated and size-limited (max 1024 hosts) - **IP Version**: IPv4 only (controlled attack surface) ```python # Automatic validation ToolInput(target="192.168.1.1") # ✓ Allowed ToolInput(target="8.8.8.8") # ✗ Rejected: Public IP ToolInput(target="server.lab.internal") # ✓ Allowed ToolInput(target="example.com") # ✗ Rejected: External domain ``` #### Input Validation - **Shell Metacharacter Blocking**: `; & | \` $ > < \n \r` completely blocked - **Whitelist-Based Flags**: Only pre-approved command flags allowed - **Token Sanitization**: All inputs validated against strict patterns - **Length Limits**: Arguments capped at 2048 bytes (configurable) #### Resource Limits (Linux) - **CPU Time**: Limited per execution - **Memory**: 512MB default limit - **File Descriptors**: 256 limit - **Output Size**: stdout 1MB, stderr 256KB - **Timeout**: 300s default (configurable) #### Intrusive Operation Control - **Policy-Based**: `-A` flag and vulnerability scripts gated by configuration - **Audit Logging**: All intrusive operations logged - **Granular Control**: Per-script and per-category filtering ### 🔄 Circuit Breaker Pattern Prevents cascade failures and enables graceful degradation: ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#0066cc','primaryTextColor':'#fff','primaryBorderColor':'#004499','lineColor':'#0066cc'}}}%% stateDiagram-v2 [*] --> CLOSED: Initial State CLOSED --> OPEN: Failures ≥ Threshold OPEN --> HALF_OPEN: After Recovery Timeout HALF_OPEN --> CLOSED: Success HALF_OPEN --> OPEN: Failure CLOSED --> CLOSED: Success note right of OPEN All requests rejected Retry after timeout end note note right of HALF_OPEN Test request allowed Evaluate recovery end note note right of CLOSED Normal operation Track failures end note ``` **Features**: - Adaptive timeout (exponential backoff) - Jitter to prevent thundering herd - Per-tool circuit breakers - Prometheus metrics integration - Detailed state tracking **Configuration**: ```bash MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 # Failures before opening MCP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=60 # Seconds to wait ``` ### 📊 Health Monitoring Three-tier priority system ensures critical issues are detected: | Priority | Impact | Examples | |----------|--------|----------| | **CRITICAL** (0) | System failure → UNHEALTHY | CPU, Memory, Disk usage | | **IMPORTANT** (1) | Degraded service → DEGRADED | Process health, Circuit breakers | | **INFORMATIONAL** (2) | Logged only → No impact | Tool availability, Dependencies | **Staleness Detection**: Health results older than 60s are considered stale **HTTP Endpoint**: ```bash GET /health Response codes: - 200: Healthy - 207: Degraded (some issues) - 503: Unhealthy (critical failure) ``` ### 📈 Metrics & Observability **Prometheus Metrics**: ``` # Execution metrics mcp_tool_execution_total{tool="NmapTool", status="success"} mcp_tool_execution_seconds{tool="NmapTool", quantile="0.99"} mcp_tool_active{tool="NmapTool"} # Circuit breaker circuit_breaker_state{name="NmapTool"} # 0=closed, 1=open, 2=half-open circuit_breaker_calls_total{name="NmapTool", result="success"} ``` **Internal Metrics**: - Success rate, latency percentiles (p50, p95, p99) - Error rates by type - Timeout counts - Active execution tracking - Historical trends (last 100 executions) ### ⚙️ Configuration Management **Multi-Source Priority** (highest to lowest): 1. Environment variables 2. Configuration file (YAML/JSON) 3. Default values **Hot Reload**: Configuration file changes detected and applied without restart **Type Safety**: All values validated and clamped to safe ranges **Example** (config.yaml): ```yaml server: transport: http port: 8080 host: 0.0.0.0 security: allow_intrusive: false max_args_length: 2048 timeout_seconds: 300 circuit_breaker: failure_threshold: 5 recovery_timeout: 60.0 health: check_interval: 30.0 cpu_threshold: 80.0 memory_threshold: 80.0 ``` ### 🛠️ Tool Ecosystem #### Current Tools **NmapTool** - Network Scanner - Host discovery - Port scanning - Service version detection - Safe script execution - Template-based scanning (Quick, Standard, Thorough) **Key Features**: - Network size limits (max 1024 hosts) - Port range limits (max 100 ranges) - Script filtering (safe vs. intrusive) - Optimization (smart defaults) #### Adding Custom Tools Inherit from `MCPBaseTool` and implement: ```python class MyTool(MCPBaseTool): command_name = "mytool" allowed_flags = ["-flag1", "-flag2"] default_timeout_sec = 60.0 # Auto-discovered and registered! ``` See [Developer Guide](#-developer-guide) for complete tutorial. --- ## 📦 Installation & Setup ### System Requirements | Component | Minimum | Recommended | |-----------|---------|-------------| | **Python** | 3.11 | 3.11+ | | **CPU** | 1 core | 2+ cores | | **Memory** | 512MB | 1GB+ | | **Disk** | 100MB | 500MB+ | | **OS** | Linux, macOS, Windows | Linux (Ubuntu 22.04+) | **System Tools** (Optional but recommended): - `nmap` - For NmapTool functionality - `curl` - For HTTP health checks - `docker` - For containerized deployment ### Non-Docker Installation #### 1. Clone Repository ```bash git clone https://github.com/nordeim/Security-MCP-Server.git cd Security-MCP-Server ``` #### 2. Create Virtual Environment ```bash # Create virtual environment python3.11 -m venv venv # Activate (Linux/macOS) source venv/bin/activate # Activate (Windows) venv\Scripts\activate ``` #### 3. Install Dependencies ```bash # Upgrade pip pip install --upgrade pip setuptools wheel # Install requirements pip install -r requirements.txt # Install in development mode (editable) pip install -e . ``` #### 4. Install System Tools ```bash # Ubuntu/Debian sudo apt-get update sudo apt-get install -y nmap netcat iputils-ping # macOS (using Homebrew) brew install nmap # Verify installation nmap --version which nmap ``` #### 5. Configure ```bash # Option 1: Environment variables export MCP_SERVER_TRANSPORT=http export MCP_SERVER_PORT=8080 export LOG_LEVEL=INFO # Option 2: Configuration file cp config/config.example.yaml config/config.yaml # Edit config/config.yaml as needed export MCP_CONFIG_FILE=config/config.yaml ``` #### 6. Verify Installation ```bash # Run validation ./scripts/mcp_server_launcher.sh validate # Expected output: # [SUCCESS] Python 3.11.x found # [SUCCESS] Virtual environment exists # [SUCCESS] mcp_server package found # [SUCCESS] All system tools available # [SUCCESS] Validation passed! Server is ready to start. ``` ### Docker Installation #### Option 1: Pre-Built Image (Recommended) ```bash # Pull latest image docker pull nordeim/security-mcp-server:latest # Run in HTTP mode docker run -d \ --name mcp-server \ -p 8080:8080 \ -e MCP_SERVER_TRANSPORT=http \ nordeim/security-mcp-server:latest # Check health curl http://localhost:8080/health ``` #### Option 2: Build from Source ```bash # Clone repository git clone https://github.com/nordheim/Security-MCP-Server.git cd Security-MCP-Server # Build image docker build -t mcp-server:latest . # Run docker run -d \ --name mcp-server \ -p 8080:8080 \ -e MCP_SERVER_TRANSPORT=http \ mcp-server:latest ``` #### Option 3: Docker Compose (Best for Development) ```bash # Create environment file cp .env.docker .env # Edit .env as needed nano .env # Start services docker-compose up -d # View logs docker-compose logs -f # Stop services docker-compose down ``` **docker-compose.yml highlights**: - Automatic restarts - Resource limits - Health checks - Volume persistence - Network isolation ### Configuration Guide #### Environment Variables Complete reference of all environment variables: <details> <summary><b>Server Configuration (click to expand)</b></summary> ```bash # Transport mode: stdio (for Claude) or http (for API) MCP_SERVER_TRANSPORT=http # HTTP server settings (http mode only) MCP_SERVER_HOST=0.0.0.0 MCP_SERVER_PORT=8080 MCP_SERVER_WORKERS=1 MCP_SERVER_MAX_CONNECTIONS=100 MCP_SERVER_SHUTDOWN_GRACE_PERIOD=30 ``` </details> <details> <summary><b>Security Settings (click to expand)</b></summary> ```bash # Allow intrusive operations (nmap -A, vuln scripts) # WARNING: Only enable in controlled environments! MCP_SECURITY_ALLOW_INTRUSIVE=false # Maximum argument length (bytes) MCP_SECURITY_MAX_ARGS_LENGTH=2048 # Maximum output size (bytes) MCP_SECURITY_MAX_OUTPUT_SIZE=1048576 # Default timeout (seconds) MCP_SECURITY_TIMEOUT_SECONDS=300 # Concurrent operation limit MCP_SECURITY_CONCURRENCY_LIMIT=2 ``` </details> <details> <summary><b>Circuit Breaker (click to expand)</b></summary> ```bash # Failure threshold before opening circuit MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 # Recovery timeout (seconds) MCP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=60 # Success threshold to close from half-open MCP_CIRCUIT_BREAKER_HALF_OPEN_SUCCESS_THRESHOLD=1 ``` </details> <details> <summary><b>Health & Metrics (click to expand)</b></summary> ```bash # Health check interval (seconds) MCP_HEALTH_CHECK_INTERVAL=30.0 # Resource thresholds (percentage) MCP_HEALTH_CPU_THRESHOLD=80.0 MCP_HEALTH_MEMORY_THRESHOLD=80.0 MCP_HEALTH_DISK_THRESHOLD=80.0 # Metrics MCP_METRICS_ENABLED=true MCP_METRICS_PROMETHEUS_PORT=9090 ``` </details> <details> <summary><b>Logging (click to expand)</b></summary> ```bash # Log level: DEBUG, INFO, WARNING, ERROR, CRITICAL LOG_LEVEL=INFO # Log format LOG_FORMAT="%(asctime)s - %(name)s - %(levelname)s - %(message)s" # Log file (optional, logs to stdout by default) # MCP_LOGGING_FILE_PATH=/app/logs/mcp_server.log ``` </details> #### Configuration File **config/config.yaml**: ```yaml server: transport: http # stdio or http host: 0.0.0.0 port: 8080 shutdown_grace_period: 30 security: allow_intrusive: false # Control intrusive operations max_args_length: 2048 timeout_seconds: 300 concurrency_limit: 2 allowed_targets: - RFC1918 # Private IP ranges - .lab.internal # Internal domains circuit_breaker: failure_threshold: 5 recovery_timeout: 60.0 health: check_interval: 30.0 cpu_threshold: 80.0 memory_threshold: 80.0 disk_threshold: 80.0 metrics: enabled: true prometheus_enabled: true prometheus_port: 9090 logging: level: INFO format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s" tool: default_timeout: 300 default_concurrency: 2 ``` **Load configuration**: ```bash export MCP_CONFIG_FILE=config/config.yaml python -m mcp_server.server ``` --- ## 🎮 Usage Guide ### Running the Server #### Stdio Mode (for Claude Desktop) ```bash # Activate virtual environment source venv/bin/activate # Run in stdio mode export MCP_SERVER_TRANSPORT=stdio python -m mcp_server.server # Server communicates via stdin/stdout # Perfect for MCP client integration ``` #### HTTP Mode (for API access) ```bash # Run in HTTP mode export MCP_SERVER_TRANSPORT=http export MCP_SERVER_PORT=8080 python -m mcp_server.server # Server starts on http://localhost:8080 # API endpoints available ``` #### Using Launcher Script ```bash # Make executable chmod +x scripts/mcp_server_launcher.sh # Start server ./scripts/mcp_server_launcher.sh start # Check status ./scripts/mcp_server_launcher.sh status # View logs ./scripts/mcp_server_launcher.sh logs # Stop server ./scripts/mcp_server_launcher.sh stop # Restart ./scripts/mcp_server_launcher.sh restart ``` ### Claude Desktop Integration 1. **Locate Claude Desktop config**: ```bash # macOS ~/Library/Application Support/Claude/config.json # Windows %APPDATA%\Claude\config.json # Linux ~/.config/Claude/config.json ``` 2. **Add MCP server configuration**: ```json { "mcpServers": { "security-tools": { "command": "/path/to/Security-MCP-Server/venv/bin/python", "args": ["-m", "mcp_server.server"], "env": { "MCP_SERVER_TRANSPORT": "stdio", "LOG_LEVEL": "INFO", "MCP_SECURITY_ALLOW_INTRUSIVE": "false" } } } } ``` 3. **Restart Claude Desktop** 4. **Test integration**: - Ask Claude: "Can you scan 192.168.1.1 for open ports?" - Claude will use the NmapTool via MCP ### Tool Invocation Examples #### Basic Network Scan ```bash # HTTP API curl -X POST http://localhost:8080/tools/NmapTool/execute \ -H "Content-Type: application/json" \ -d '{ "target": "192.168.1.0/24", "extra_args": "-sV --top-ports 100" }' ``` **In Claude**: ``` User: Scan my lab network 192.168.1.0/24 for web servers Claude: I'll scan the network for web servers using nmap. [Executes: NmapTool with target "192.168.1.0/24" and args "-p 80,443 -sV"] Results: Found 3 hosts running web servers: - 192.168.1.10: Apache 2.4.41 - 192.168.1.20: nginx 1.18.0 - 192.168.1.30: Microsoft IIS 10.0 ``` #### Service Version Detection ```bash curl -X POST http://localhost:8080/tools/NmapTool/execute \ -H "Content-Type: application/json" \ -d '{ "target": "192.168.1.10", "extra_args": "-sV --version-intensity 5" }' ``` #### Using Scan Templates ```python # Python client example import requests response = requests.post( "http://localhost:8080/tools/NmapTool/execute", json={ "target": "192.168.1.0/24", "extra_args": "-T4 -Pn --top-ports 1000 -sV", # Standard template "timeout_sec": 600 } ) result = response.json() print(f"Scan completed in {result['execution_time']}s") print(f"Return code: {result['returncode']}") print(f"Output: {result['stdout']}") ``` #### Safe Script Scanning ```bash # Safe scripts (always allowed) curl -X POST http://localhost:8080/tools/NmapTool/execute \ -H "Content-Type: application/json" \ -d '{ "target": "192.168.1.10", "extra_args": "--script safe -sV" }' # Intrusive scripts (requires MCP_SECURITY_ALLOW_INTRUSIVE=true) curl -X POST http://localhost:8080/tools/NmapTool/execute \ -H "Content-Type: application/json" \ -d '{ "target": "192.168.1.10", "extra_args": "--script vuln -sV" }' ``` ### HTTP API Reference #### Endpoints | Method | Endpoint | Description | |--------|----------|-------------| | `GET` | `/` | Server information | | `GET` | `/health` | Health check | | `GET` | `/tools` | List available tools | | `POST` | `/tools/{tool_name}/execute` | Execute a tool | | `POST` | `/tools/{tool_name}/enable` | Enable a tool | | `POST` | `/tools/{tool_name}/disable` | Disable a tool | | `GET` | `/metrics` | Prometheus metrics | | `GET` | `/events` | SSE event stream | | `GET` | `/config` | Current configuration (redacted) | #### Execute Tool **Request**: ```http POST /tools/NmapTool/execute HTTP/1.1 Content-Type: application/json { "target": "192.168.1.1", "extra_args": "-sV --top-ports 100", "timeout_sec": 300, "correlation_id": "scan-001" } ``` **Response (Success)**: ```json { "stdout": "Starting Nmap 7.94...", "stderr": "", "returncode": 0, "truncated_stdout": false, "truncated_stderr": false, "timed_out": false, "error": null, "error_type": null, "execution_time": 45.23, "correlation_id": "scan-001", "metadata": {} } ``` **Response (Validation Error)**: ```json { "detail": "Target must be RFC1918 IPv4 or a .lab.internal hostname" } ``` **Response (Rate Limited)**: ```json { "detail": { "error": "Rate limit exceeded", "message": "Too many requests for NmapTool. Try again later.", "retry_after": 60 } } ``` #### Health Check ```http GET /health HTTP/1.1 ``` **Response (Healthy - 200 OK)**: ```json { "status": "healthy", "timestamp": "2024-01-15T10:30:00Z", "transport": "http", "checks": { "system_resources": { "status": "healthy", "message": "System resources healthy", "metadata": { "cpu_percent": 25.5, "memory_percent": 45.2, "disk_percent": 60.0 } }, "process_health": { "status": "healthy", "message": "Process is running normally" } }, "summary": { "total_checks": 5, "healthy_checks": 5, "degraded_checks": 0, "unhealthy_checks": 0 } } ``` **Response (Degraded - 207 Multi-Status)**: ```json { "status": "degraded", "timestamp": "2024-01-15T10:30:00Z", "checks": { "system_resources": { "status": "degraded", "message": "Memory usage high: 85.0%" } } } ``` **Response (Unhealthy - 503 Service Unavailable)**: ```json { "status": "unhealthy", "timestamp": "2024-01-15T10:30:00Z", "checks": { "system_resources": { "status": "unhealthy", "message": "CPU usage critical: 92.0%" } } } ``` --- ## 🚀 Deployment Guide ### Development Deployment #### Local Development (Non-Docker) ```bash # 1. Clone and setup git clone https://github.com/nordeim/Security-MCP-Server.git cd Security-MCP-Server python -m venv venv source venv/bin/activate pip install -r requirements.txt pip install -e . # 2. Configure for development export MCP_SERVER_TRANSPORT=http export LOG_LEVEL=DEBUG export MCP_SECURITY_ALLOW_INTRUSIVE=true # For testing only! # 3. Run with hot-reload (install watchdog) pip install watchdog watchmedo auto-restart --directory=./mcp_server --pattern='*.py' \ --recursive -- python -m mcp_server.server # 4. In another terminal, test curl http://localhost:8080/health ``` #### Docker Development ```bash # 1. Use docker-compose with override docker-compose up -d # 2. Check logs docker-compose logs -f mcp-server # 3. Source code is mounted for hot-reload # Edit files in ./mcp_server/ and changes reflect immediately # 4. Run tests in container docker-compose exec mcp-server pytest # 5. Shell access docker-compose exec mcp-server bash ``` ### Production Deployment #### Production Non-Docker **Prerequisites**: - Dedicated server or VM - systemd (Linux) - Firewall configured - Monitoring setup **Steps**: 1. **Create dedicated user**: ```bash sudo useradd -r -s /bin/bash -d /opt/mcp-server mcp sudo mkdir -p /opt/mcp-server sudo chown mcp:mcp /opt/mcp-server ``` 2. **Install as mcp user**: ```bash sudo -u mcp bash cd /opt/mcp-server git clone https://github.com/nordeim/Security-MCP-Server.git . python3.11 -m venv venv source venv/bin/activate pip install -r requirements.txt pip install -e . ``` 3. **Create systemd service**: ```bash sudo nano /etc/systemd/system/mcp-server.service ``` ```ini [Unit] Description=MCP Network Tools Server After=network.target [Service] Type=simple User=mcp Group=mcp WorkingDirectory=/opt/mcp-server Environment="PATH=/opt/mcp-server/venv/bin" Environment="MCP_SERVER_TRANSPORT=http" Environment="MCP_SERVER_PORT=8080" Environment="LOG_LEVEL=INFO" Environment="MCP_SECURITY_ALLOW_INTRUSIVE=false" ExecStart=/opt/mcp-server/venv/bin/python -m mcp_server.server Restart=always RestartSec=10 StandardOutput=journal StandardError=journal SyslogIdentifier=mcp-server # Security hardening NoNewPrivileges=true PrivateTmp=true ProtectSystem=strict ProtectHome=true ReadWritePaths=/opt/mcp-server/logs /opt/mcp-server/data [Install] WantedBy=multi-user.target ``` 4. **Enable and start**: ```bash sudo systemctl daemon-reload sudo systemctl enable mcp-server sudo systemctl start mcp-server sudo systemctl status mcp-server ``` 5. **Configure reverse proxy** (nginx): ```nginx server { listen 80; server_name mcp.example.com; location / { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # SSE support proxy_buffering off; proxy_cache off; proxy_set_header Connection ''; proxy_http_version 1.1; chunked_transfer_encoding off; } } ``` #### Production Docker **Single Container**: ```bash # 1. Pull production image docker pull nordeim/security-mcp-server:latest # 2. Create production env file cat > /opt/mcp-server/.env << EOF MCP_SERVER_TRANSPORT=http MCP_SERVER_PORT=8080 LOG_LEVEL=INFO MCP_SECURITY_ALLOW_INTRUSIVE=false MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=5 MCP_HEALTH_CHECK_INTERVAL=30 MCP_METRICS_ENABLED=true EOF # 3. Run with restart policy docker run -d \ --name mcp-server \ --restart unless-stopped \ -p 8080:8080 \ --env-file /opt/mcp-server/.env \ --memory="1g" \ --cpus="2" \ -v mcp-logs:/app/logs \ -v mcp-data:/app/data \ --health-cmd='/app/docker/healthcheck.sh' \ --health-interval=30s \ nordeim/security-mcp-server:latest # 4. Verify docker ps curl http://localhost:8080/health ``` **Docker Compose Production**: ```bash # 1. Use production compose file only docker-compose -f docker-compose.yml up -d # 2. Monitor docker-compose -f docker-compose.yml logs -f # 3. Check health docker-compose -f docker-compose.yml ps ``` ### Kubernetes Deployment (Bonus) <details> <summary><b>Kubernetes Manifests (click to expand)</b></summary> **deployment.yaml**: ```yaml apiVersion: apps/v1 kind: Deployment metadata: name: mcp-server labels: app: mcp-server spec: replicas: 2 selector: matchLabels: app: mcp-server template: metadata: labels: app: mcp-server spec: containers: - name: mcp-server image: nordeim/security-mcp-server:latest ports: - containerPort: 8080 name: http - containerPort: 9090 name: metrics env: - name: MCP_SERVER_TRANSPORT value: "http" - name: MCP_SERVER_PORT value: "8080" - name: LOG_LEVEL value: "INFO" resources: requests: memory: "256Mi" cpu: "500m" limits: memory: "1Gi" cpu: "2000m" livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 30 periodSeconds: 30 readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 10 ``` **service.yaml**: ```yaml apiVersion: v1 kind: Service metadata: name: mcp-server spec: selector: app: mcp-server ports: - name: http port: 80 targetPort: 8080 - name: metrics port: 9090 targetPort: 9090 type: ClusterIP ``` **ingress.yaml**: ```yaml apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: mcp-server annotations: kubernetes.io/ingress.class: nginx spec: rules: - host: mcp.example.com http: paths: - path: / pathType: Prefix backend: service: name: mcp-server port: number: 80 ``` Deploy: ```bash kubectl apply -f deployment.yaml kubectl apply -f service.yaml kubectl apply -f ingress.yaml kubectl get pods -l app=mcp-server ``` </details> ### Deployment Checklist - [ ] **Pre-Deployment** - [ ] System requirements met - [ ] Dependencies installed - [ ] Configuration reviewed - [ ] Security settings verified - [ ] Firewall rules configured - [ ] Monitoring setup ready - [ ] **Deployment** - [ ] Application deployed - [ ] Health check passing - [ ] Metrics accessible - [ ] Logs flowing - [ ] Resource limits enforced - [ ] **Post-Deployment** - [ ] Smoke tests passed - [ ] Integration tests passed - [ ] Performance tests passed - [ ] Security scan passed - [ ] Documentation updated - [ ] Monitoring alerts configured - [ ] Backup/restore tested --- ## 🛠️ Developer Guide ### Project Structure ``` Security-MCP-Server/ ├── 📄 README.md # This file ├── 📄 LICENSE # MIT License ├── 📄 requirements.txt # Python dependencies ├── 📄 setup.py # Package setup ├── 📄 mcp.json # MCP protocol configuration ├── 📄 .env.docker # Docker environment template ├── 📄 .dockerignore # Docker build exclusions ├── 📄 Dockerfile # Container image definition ├── 📄 docker-compose.yml # Production orchestration ├── 📄 docker-compose.override.yml # Development overrides │ ├── 📁 mcp_server/ # Main application package │ ├── 📄 __init__.py │ ├── 📄 server.py # MCP server implementation │ ├── 📄 base_tool.py # Base tool class │ ├── 📄 config.py # Configuration management │ ├── 📄 health.py # Health monitoring system │ ├── 📄 metrics.py # Metrics collection │ ├── 📄 circuit_breaker.py # Circuit breaker pattern │ └── 📁 tools/ # Tool implementations │ ├── 📄 __init__.py │ └── 📄 nmap_tool.py # Nmap integration │ ├── 📁 scripts/ # Utility scripts │ └── 📄 mcp_server_launcher.sh # Server launcher │ ├── 📁 docker/ # Docker support files │ ├── 📄 entrypoint.sh # Container entrypoint │ └── 📄 healthcheck.sh # Container health check │ ├── 📁 config/ # Configuration files │ ├── 📄 config.example.yaml # Example configuration │ └── 📄 config.schema.json # Configuration schema │ ├── 📁 tests/ # Test suite │ ├── 📄 __init__.py │ ├── 📄 conftest.py # Pytest fixtures │ ├── 📁 unit/ # Unit tests │ │ ├── 📄 test_base_tool.py │ │ ├── 📄 test_config.py │ │ ├── 📄 test_health.py │ │ ├── 📄 test_metrics.py │ │ ├── 📄 test_circuit_breaker.py │ │ └── 📁 tools/ │ │ └── 📄 test_nmap_tool.py │ └── 📁 integration/ # Integration tests │ ├── 📄 test_server.py │ └── 📄 test_tool_execution.py │ ├── 📁 docs/ # Additional documentation │ ├── 📄 architecture.md │ ├── 📄 api_reference.md │ └── 📄 deployment.md │ ├── 📁 logs/ # Application logs (gitignored) └── 📁 data/ # Persistent data (gitignored) ``` ### Module Responsibilities | Module | Purpose | Key Classes/Functions | |--------|---------|----------------------| | **server.py** | MCP server, request handling, tool registry | `EnhancedMCPServer`, `ToolRegistry`, `main_enhanced()` | | **base_tool.py** | Base tool implementation, validation, execution | `MCPBaseTool`, `ToolInput`, `ToolOutput` | | **config.py** | Configuration loading, validation, hot-reload | `MCPConfig`, `get_config()`, `reset_config()` | | **health.py** | Health monitoring, status aggregation | `HealthCheckManager`, `HealthCheck`, `HealthStatus` | | **metrics.py** | Metrics collection, Prometheus integration | `MetricsManager`, `ToolMetrics`, `PrometheusRegistry` | | **circuit_breaker.py** | Failure protection, auto-recovery | `CircuitBreaker`, `CircuitBreakerState` | | **nmap_tool.py** | Nmap integration, security controls | `NmapTool`, `ScanTemplate` | ### Creating Custom Tools #### Step-by-Step Tutorial Let's create a simple `PingTool` that safely pings hosts. **1. Create tool file**: ```bash touch mcp_server/tools/ping_tool.py ``` **2. Implement tool class**: ```python """ Ping tool for network connectivity testing. """ import logging from typing import Optional from mcp_server.base_tool import MCPBaseTool, ToolInput, ToolOutput log = logging.getLogger(__name__) class PingTool(MCPBaseTool): """ ICMP ping tool for network connectivity testing. Features: - Safe ping execution - Packet count control - Timeout enforcement - RFC1918/lab.internal only Example: # Ping a host 5 times tool = PingTool() result = await tool.run(ToolInput( target="192.168.1.1", extra_args="-c 5" )) """ # Required: Command name command_name = "ping" # Optional: Allowed flags (whitelist) allowed_flags = [ "-c", # Count "-i", # Interval "-W", # Timeout "-q", # Quiet "-v", # Verbose ] # Optional: Flags that require values _FLAGS_REQUIRE_VALUE = {"-c", "-i", "-W"} # Optional: Extra allowed tokens (for values) _EXTRA_ALLOWED_TOKENS = {"1", "5", "10"} # Optional: Custom timeout default_timeout_sec = 30.0 # Optional: Concurrency limit concurrency = 5 # Optional: Circuit breaker config circuit_breaker_failure_threshold = 3 circuit_breaker_recovery_timeout = 30.0 def __init__(self): """Initialize ping tool.""" super().__init__() log.info("ping_tool.initialized") # Optional: Custom validation async def _execute_tool(self, inp: ToolInput, timeout_sec: Optional[float] = None) -> ToolOutput: """Execute ping with custom validation.""" # Add custom validation if needed if inp.extra_args: # Parse count if "-c" in inp.extra_args: # Ensure count is reasonable try: parts = inp.extra_args.split() c_index = parts.index("-c") count = int(parts[c_index + 1]) if count > 10: # Override with max parts[c_index + 1] = "10" inp.extra_args = " ".join(parts) log.warning("ping.count_clamped original=%d new=10", count) except (ValueError, IndexError): pass # Call parent implementation return await super()._execute_tool(inp, timeout_sec) ``` **3. Tool is auto-discovered!** The tool will be automatically discovered and registered when the server starts. **4. Test your tool**: ```python # tests/unit/tools/test_ping_tool.py import pytest from mcp_server.tools.ping_tool import PingTool from mcp_server.base_tool import ToolInput @pytest.mark.asyncio async def test_ping_tool_basic(): """Test basic ping execution.""" tool = PingTool() result = await tool.run(ToolInput( target="192.168.1.1", extra_args="-c 3" )) assert result.returncode == 0 or result.returncode == 1 # Success or host down assert not result.timed_out assert result.execution_time > 0 @pytest.mark.asyncio async def test_ping_tool_public_ip_rejected(): """Test that public IPs are rejected.""" tool = PingTool() with pytest.raises(ValueError, match="RFC1918"): await tool.run(ToolInput( target="8.8.8.8", extra_args="-c 1" )) @pytest.mark.asyncio async def test_ping_tool_count_clamping(): """Test that large counts are clamped.""" tool = PingTool() result = await tool.run(ToolInput( target="192.168.1.1", extra_args="-c 100" # Should be clamped to 10 )) # Verify clamping occurred assert "-c 10" in result.metadata.get("actual_command", "") ``` **5. Run tests**: ```bash pytest tests/unit/tools/test_ping_tool.py -v ``` **6. Use your tool**: ```bash # HTTP API curl -X POST http://localhost:8080/tools/PingTool/execute \ -H "Content-Type: application/json" \ -d '{"target": "192.168.1.1", "extra_args": "-c 5"}' ``` #### Advanced Tool Example <details> <summary><b>TracerouteTool with Custom Features (click to expand)</b></summary> ```python """ Traceroute tool with advanced features. """ import re from typing import Optional, List, Dict, Any from mcp_server.base_tool import MCPBaseTool, ToolInput, ToolOutput from mcp_server.config import get_config class TracerouteTool(MCPBaseTool): """Advanced traceroute tool with hop analysis.""" command_name = "traceroute" allowed_flags = ["-m", "-w", "-q", "-n"] _FLAGS_REQUIRE_VALUE = {"-m", "-w", "-q"} default_timeout_sec = 60.0 concurrency = 3 # Custom: Max hops limit MAX_HOPS = 30 def __init__(self): super().__init__() self.config = get_config() async def _execute_tool(self, inp: ToolInput, timeout_sec: Optional[float] = None) -> ToolOutput: """Execute with hop limit enforcement.""" # Enforce max hops if "-m" in (inp.extra_args or ""): inp.extra_args = self._enforce_max_hops(inp.extra_args) else: # Add default max hops inp.extra_args = f"-m {self.MAX_HOPS} {inp.extra_args or ''}" # Execute result = await super()._execute_tool(inp, timeout_sec) # Parse hops if result.returncode == 0: hops = self._parse_hops(result.stdout) result.metadata['hops'] = hops result.metadata['hop_count'] = len(hops) return result def _enforce_max_hops(self, args: str) -> str: """Enforce maximum hop count.""" parts = args.split() try: m_index = parts.index("-m") hops = int(parts[m_index + 1]) if hops > self.MAX_HOPS: parts[m_index + 1] = str(self.MAX_HOPS) log.warning("traceroute.hops_clamped original=%d new=%d", hops, self.MAX_HOPS) except (ValueError, IndexError): pass return " ".join(parts) def _parse_hops(self, output: str) -> List[Dict[str, Any]]: """Parse traceroute output into structured hops.""" hops = [] hop_pattern = re.compile( r'^\s*(\d+)\s+(\S+)\s+\((\d+\.\d+\.\d+\.\d+)\)\s+([\d.]+)\s*ms' ) for line in output.split('\n'): match = hop_pattern.match(line) if match: hop_num, hostname, ip, latency = match.groups() hops.append({ 'hop': int(hop_num), 'hostname': hostname, 'ip': ip, 'latency_ms': float(latency) }) return hops def get_tool_info(self) -> Dict[str, Any]: """Extended tool information.""" info = super().get_tool_info() info.update({ 'max_hops': self.MAX_HOPS, 'features': [ 'Hop limit enforcement', 'Structured hop parsing', 'Latency tracking' ] }) return info ``` </details> ### Best Practices #### Tool Design - ✅ **Inherit from MCPBaseTool**: Don't reinvent the wheel - ✅ **Define allowed_flags**: Whitelist approach for security - ✅ **Set reasonable timeouts**: Balance functionality and resource usage - ✅ **Handle errors gracefully**: Return ToolOutput even on failure - ✅ **Add comprehensive docstrings**: Help users understand your tool - ✅ **Validate inputs**: Additional validation beyond base class - ✅ **Parse outputs**: Structure results for easy consumption #### Security - ✅ **Validate all inputs**: Never trust user input - ✅ **Enforce resource limits**: Prevent DoS - ✅ **Use whitelist validation**: Block by default, allow explicitly - ✅ **Sanitize arguments**: Prevent injection attacks - ✅ **Audit intrusive operations**: Log all sensitive actions #### Performance - ✅ **Set appropriate concurrency**: Balance load and responsiveness - ✅ **Use timeouts**: Prevent hung operations - ✅ **Implement caching**: Where appropriate (validation, resolution) - ✅ **Optimize regex**: Compile patterns at class level - ✅ **Minimize I/O**: Async operations, batch when possible #### Testing - ✅ **Unit test validation**: Test all validation paths - ✅ **Test error handling**: Simulate failures - ✅ **Integration tests**: Test with real commands - ✅ **Mock external deps**: Don't rely on network in tests - ✅ **Test resource limits**: Verify enforcement ### Testing Guide #### Running Tests ```bash # All tests pytest # Unit tests only pytest tests/unit/ # Integration tests only pytest tests/integration/ # Specific test file pytest tests/unit/test_base_tool.py # Specific test pytest tests/unit/test_base_tool.py::test_input_validation # With coverage pytest --cov=mcp_server --cov-report=html # Verbose output pytest -v # Show print statements pytest -s # Stop on first failure pytest -x ``` #### Writing Tests **Fixture example** (conftest.py): ```python import pytest import asyncio from mcp_server.config import get_config, reset_config from mcp_server.base_tool import MCPBaseTool @pytest.fixture def event_loop(): """Create event loop for async tests.""" loop = asyncio.get_event_loop_policy().new_event_loop() yield loop loop.close() @pytest.fixture def test_config(): """Provide test configuration.""" reset_config() config = get_config(force_new=True) config.security.allowed_targets = ["RFC1918", ".lab.internal"] config.security.allow_intrusive = False yield config reset_config() @pytest.fixture def mock_tool(test_config): """Create mock tool for testing.""" class MockTool(MCPBaseTool): command_name = "echo" allowed_flags = ["-n", "-e"] return MockTool() ``` **Test example**: ```python import pytest from mcp_server.base_tool import ToolInput, ToolErrorType @pytest.mark.asyncio async def test_tool_execution_success(mock_tool): """Test successful tool execution.""" result = await mock_tool.run(ToolInput( target="192.168.1.1", extra_args="-n" )) assert result.returncode == 0 assert not result.timed_out assert result.execution_time > 0 assert result.correlation_id is not None @pytest.mark.asyncio async def test_input_validation_blocks_public_ip(mock_tool): """Test that public IPs are rejected.""" with pytest.raises(ValueError, match="RFC1918"): ToolInput(target="8.8.8.8") @pytest.mark.asyncio async def test_command_injection_blocked(mock_tool): """Test that shell metacharacters are blocked.""" with pytest.raises(ValueError, match="forbidden metacharacters"): ToolInput(target="192.168.1.1", extra_args="; rm -rf /") ``` ### Code Style & Standards - **Style Guide**: PEP 8 - **Docstrings**: Google style - **Type Hints**: Comprehensive, Python 3.11+ syntax - **Line Length**: 100 characters max - **Imports**: Grouped (stdlib, third-party, local) - **Logging**: Structured, consistent format **Example**: ```python """ Module docstring with description. This module provides... """ import asyncio import logging from typing import Optional, Dict, Any from third_party import SomeClass from mcp_server.base_tool import MCPBaseTool log = logging.getLogger(__name__) class MyTool(MCPBaseTool): """ Class docstring. Longer description... Attributes: command_name: The system command to execute Example: >>> tool = MyTool() >>> result = await tool.run(ToolInput(target="192.168.1.1")) """ command_name = "mytool" async def my_method(self, param: str) -> Optional[Dict[str, Any]]: """ Method docstring. Args: param: Description of parameter Returns: Dictionary with results or None Raises: ValueError: If param is invalid """ log.info("my_method.called param=%s", param) if not param: raise ValueError("param cannot be empty") return {"result": param} ``` --- ## 📊 Monitoring & Operations ### Health Checks #### Endpoint Usage ```bash # Basic health check curl http://localhost:8080/health # Detailed health information curl http://localhost:8080/health | jq . # Check specific aspect curl http://localhost:8080/health | jq '.checks.system_resources' # Monitor continuously watch -n 5 'curl -s http://localhost:8080/health | jq .status' ``` #### Interpreting Results **Status Codes**: - `200 OK`: System healthy, all checks passed - `207 Multi-Status`: System degraded, some issues detected - `503 Service Unavailable`: System unhealthy, critical failure **Check Priorities**: - **CRITICAL** (0): Failure causes UNHEALTHY status - CPU usage > 80% - Memory usage > 80% - Disk usage > 80% - **IMPORTANT** (1): Failure causes DEGRADED status - Process not running - Circuit breaker open - **INFORMATIONAL** (2): Logged only - Tool commands not found - Optional dependencies missing ### Metrics #### Prometheus Integration **Scrape configuration** (prometheus.yml): ```yaml scrape_configs: - job_name: 'mcp-server' static_configs: - targets: ['localhost:9090'] scrape_interval: 15s ``` #### Available Metrics **Tool Execution**: ``` # Total executions mcp_tool_execution_total{tool="NmapTool", status="success", error_type="none"} # Execution latency histogram mcp_tool_execution_seconds{tool="NmapTool", quantile="0.5"} # p50 mcp_tool_execution_seconds{tool="NmapTool", quantile="0.95"} # p95 mcp_tool_execution_seconds{tool="NmapTool", quantile="0.99"} # p99 # Active executions mcp_tool_active{tool="NmapTool"} # Errors mcp_tool_errors_total{tool="NmapTool", error_type="timeout"} ``` **Circuit Breaker**: ``` # State (0=closed, 1=open, 2=half-open) circuit_breaker_state{name="NmapTool_12345"} # Calls circuit_breaker_calls_total{name="NmapTool_12345", result="success"} # State transitions circuit_breaker_transitions_total{name="NmapTool_12345", from_state="CLOSED", to_state="OPEN"} ``` #### Grafana Dashboard <details> <summary><b>Example Grafana Dashboard JSON (click to expand)</b></summary> Import this into Grafana for instant monitoring: ```json { "dashboard": { "title": "MCP Server Monitoring", "panels": [ { "title": "Request Rate", "targets": [ { "expr": "rate(mcp_tool_execution_total[5m])" } ] }, { "title": "Success Rate", "targets": [ { "expr": "rate(mcp_tool_execution_total{status=\"success\"}[5m]) / rate(mcp_tool_execution_total[5m])" } ] }, { "title": "Latency Percentiles", "targets": [ { "expr": "histogram_quantile(0.50, mcp_tool_execution_seconds)", "legendFormat": "p50" }, { "expr": "histogram_quantile(0.95, mcp_tool_execution_seconds)", "legendFormat": "p95" }, { "expr": "histogram_quantile(0.99, mcp_tool_execution_seconds)", "legendFormat": "p99" } ] }, { "title": "Circuit Breaker States", "targets": [ { "expr": "circuit_breaker_state" } ] } ] } } ``` </details> ### Logging #### Log Levels | Level | Usage | Example | |-------|-------|---------| | **DEBUG** | Development, troubleshooting | Detailed function calls, variable values | | **INFO** | Normal operations | Request received, tool executed, config loaded | | **WARNING** | Potential issues | High resource usage, deprecated features | | **ERROR** | Errors requiring attention | Tool execution failed, validation errors | | **CRITICAL** | System-threatening issues | Cannot start, critical dependency missing | #### Log Format **Default** (human-readable): ``` 2024-01-15 10:30:45,123 - mcp_server.server - INFO - tool.execution tool=NmapTool target=192.168.1.1 duration=2.34 ``` **JSON** (machine-readable): ```bash export LOG_FORMAT=json ``` ```json { "timestamp": "2024-01-15T10:30:45.123Z", "level": "INFO", "logger": "mcp_server.server", "message": "tool.execution", "tool": "NmapTool", "target": "192.168.1.1", "duration": 2.34 } ``` #### Log Aggregation **Example: ELK Stack** ```yaml # filebeat.yml filebeat.inputs: - type: log enabled: true paths: - /var/log/mcp-server/*.log json.keys_under_root: true json.add_error_key: true output.elasticsearch: hosts: ["localhost:9200"] index: "mcp-server-%{+yyyy.MM.dd}" ``` ### Troubleshooting #### Common Issues **1. Server won't start** ```bash # Check Python version python --version # Should be 3.11+ # Check dependencies pip check # Check configuration python -c "from mcp_server.config import get_config; get_config()" # Check ports sudo lsof -i :8080 # HTTP port sudo lsof -i :9090 # Metrics port ``` **2. Tool execution fails** ```bash # Check tool availability which nmap # Check permissions ls -l /usr/bin/nmap # Test manually nmap -sV --top-ports 10 192.168.1.1 # Check logs ./scripts/mcp_server_launcher.sh logs ``` **3. High memory usage** ```bash # Check metrics curl http://localhost:8080/metrics | grep memory # Check active executions curl http://localhost:8080/health | jq '.checks.process_health.metadata' # Reduce concurrency export MCP_TOOL_DEFAULT_CONCURRENCY=1 ``` **4. Circuit breaker constantly open** ```bash # Check circuit breaker state curl http://localhost:8080/health | jq '.checks[] | select(.name | contains("circuit"))' # Check error rates curl http://localhost:8080/metrics | grep circuit_breaker # Increase threshold export MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=10 # Decrease recovery timeout for testing export MCP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30 ``` #### Debug Mode ```bash # Enable debug logging export LOG_LEVEL=DEBUG python -m mcp_server.server # Or in Docker docker run -e LOG_LEVEL=DEBUG nordheim/security-mcp-server ``` #### Getting Help - 📖 **Documentation**: This README, `/docs` folder - 🐛 **Issues**: [GitHub Issues](https://github.com/nordeim/Security-MCP-Server/issues) - 💬 **Discussions**: [GitHub Discussions](https://github.com/nordeim/Security-MCP-Server/discussions) - 📧 **Email**: [security-mcp@example.com](mailto:security-mcp@example.com) --- ## 🔒 Security ### Security Model Security MCP Server implements **defense in depth** with multiple security layers: ```mermaid %%{init: {'theme':'base', 'themeVariables': { 'primaryColor':'#0066cc'}}}%% graph TB A[Request] --> B{Input Validation} B -->|Invalid| C[Reject] B -->|Valid| D{Network Check} D -->|Public IP| C D -->|Private IP| E{Argument Sanitization} E -->|Dangerous| C E -->|Safe| F{Resource Limits} F -->|Exceeded| G[Timeout/Kill] F -->|OK| H{Command Execution} H --> I{Circuit Breaker} I -->|Open| C I -->|Closed| J[Execute] J --> K[Monitor & Log] K --> L[Return Result] style C fill:#ff4444,color:#fff style L fill:#44ff44,color:#000 ``` ### Network Restrictions **Allowed**: - ✅ RFC1918 Private IPs: `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16` - ✅ Loopback: `127.0.0.0/8` - ✅ .lab.internal domains: `*.lab.internal` **Blocked**: - ❌ Public IP addresses - ❌ External domains - ❌ IPv6 addresses (not yet supported) ### Input Validation **Shell Metacharacter Blocking**: - Blocked characters: `; & | \` $ > < \n \r` - Whitelist-based flag validation - Token pattern matching: `^[A-Za-z0-9.:/=+,\-@%_]+$` **Argument Limits**: - Maximum length: 2048 bytes (configurable) - Maximum port ranges: 100 - Maximum network size: 1024 hosts ### Resource Limits **Process Limits** (Linux only): - CPU time: Based on timeout setting - Memory: 512MB (configurable via `MCP_MAX_MEMORY_MB`) - File descriptors: 256 (configurable via `MCP_MAX_FILE_DESCRIPTORS`) - Core dump: Disabled **Output Limits**: - stdout: 1MB max (configurable via `MCP_MAX_STDOUT_BYTES`) - stderr: 256KB max (configurable via `MCP_MAX_STDERR_BYTES`) **Execution Limits**: - Timeout: 300s default (configurable) - Concurrency: 2 per tool (configurable) - Process isolation: New session group ### Reporting Vulnerabilities We take security seriously. If you discover a security vulnerability: 1. **DO NOT** open a public issue 2. Email: [security@example.com](mailto:security@example.com) 3. Include: - Description of the vulnerability - Steps to reproduce - Potential impact - Suggested fix (if any) 4. We will respond within **48 hours** 5. We will provide a fix within **7 days** for critical issues ### Security Best Practices **For Operators**: - ✅ Run as non-root user - ✅ Use firewall rules (allow only necessary ports) - ✅ Enable audit logging - ✅ Regularly update dependencies - ✅ Monitor for suspicious activity - ✅ Use TLS for HTTP mode (reverse proxy) - ✅ Implement rate limiting - ✅ Keep `MCP_SECURITY_ALLOW_INTRUSIVE=false` in production **For Developers**: - ✅ Validate all inputs - ✅ Use whitelist approach for flags - ✅ Sanitize before execution - ✅ Enforce resource limits - ✅ Log security events - ✅ Handle errors gracefully - ✅ Test security controls --- ## ❓ FAQ & Troubleshooting ### Frequently Asked Questions <details> <summary><b>Q: Can I scan public IP addresses?</b></summary> **A:** No, by design. Security MCP Server only allows RFC1918 private IPs and `.lab.internal` domains. This prevents accidental scanning of external networks and ensures the tool is used only in controlled environments. To scan external targets, you would need to modify the validation logic in `base_tool.py`, but this is strongly discouraged for security and legal reasons. </details> <details> <summary><b>Q: How do I enable intrusive scans (nmap -A)?</b></summary> **A:** Set the environment variable: ```bash export MCP_SECURITY_ALLOW_INTRUSIVE=true ``` Or in configuration file: ```yaml security: allow_intrusive: true ``` **WARNING**: Only enable in controlled lab environments. Intrusive scans can be detected and may violate policies. </details> <details> <summary><b>Q: Why is my circuit breaker always open?</b></summary> **A:** Circuit breakers open after consecutive failures. Check: 1. Tool is actually installed (`which nmap`) 2. Error logs for root cause 3. Failure threshold is appropriate 4. Network targets are reachable Adjust settings: ```bash # Increase threshold export MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=10 # Decrease recovery timeout export MCP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30 ``` Force close: ```python from mcp_server.tools.nmap_tool import NmapTool tool = NmapTool() await tool._circuit_breaker.force_close() ``` </details> <details> <summary><b>Q: Can I use this in production?</b></summary> **A:** Yes! Security MCP Server is production-ready with: - Circuit breakers for resilience - Health monitoring - Metrics & observability - Graceful shutdown - Resource limits - Comprehensive testing However, ensure you: - Use HTTPS (reverse proxy) - Enable authentication/authorization - Configure firewalls - Monitor actively - Keep dependencies updated - Follow security best practices </details> <details> <summary><b>Q: How do I add my own tools?</b></summary> **A:** See the [Creating Custom Tools](#creating-custom-tools) section. In summary: 1. Create a new file in `mcp_server/tools/` 2. Inherit from `MCPBaseTool` 3. Define `command_name` and `allowed_flags` 4. Optionally override methods for custom behavior 5. Tool is auto-discovered! </details> <details> <summary><b>Q: Does this work with Claude Desktop?</b></summary> **A:** Yes! Configure `mcp.json` in Claude Desktop: ```json { "mcpServers": { "security-tools": { "command": "/path/to/venv/bin/python", "args": ["-m", "mcp_server.server"], "env": { "MCP_SERVER_TRANSPORT": "stdio" } } } } ``` See [Claude Desktop Integration](#claude-desktop-integration) for details. </details> <details> <summary><b>Q: What's the difference between stdio and HTTP mode?</b></summary> **A:** | Feature | stdio | HTTP | |---------|-------|------| | **Use Case** | AI agents (Claude) | APIs, monitoring, web apps | | **Transport** | stdin/stdout | HTTP REST | | **I/O** | Line-based | JSON | | **Monitoring** | Limited | Full (health, metrics) | | **Multiple Clients** | No (single process) | Yes (concurrent) | | **Deployment** | Simple | Production-ready | Choose stdio for Claude Desktop, HTTP for everything else. </details> <details> <summary><b>Q: How do I monitor performance?</b></summary> **A:** Multiple options: 1. **Health Check**: ```bash curl http://localhost:8080/health ``` 2. **Prometheus Metrics**: ```bash curl http://localhost:8080/metrics ``` 3. **Server-Sent Events** (real-time): ```bash curl http://localhost:8080/events ``` 4. **Grafana Dashboard**: Import the provided JSON (see [Metrics](#metrics)) 5. **Logs**: ```bash ./scripts/mcp_server_launcher.sh logs ``` </details> ### Common Issues & Solutions | Issue | Symptoms | Solution | |-------|----------|----------| | **Import Error** | `ModuleNotFoundError: No module named 'mcp_server'` | Install in editable mode: `pip install -e .` | | **Permission Denied** | Tool execution fails with permission error | Check nmap capabilities: `getcap /usr/bin/nmap` | | **Port Already in Use** | Server won't start, `Address already in use` | Change port: `export MCP_SERVER_PORT=8081` or kill existing process | | **Health Check Fails** | `/health` returns 503 | Check logs for specific failing checks | | **Timeout Errors** | Tool execution times out | Increase timeout: `export MCP_TOOL_DEFAULT_TIMEOUT=600` | | **High Memory** | Container OOM or high usage | Reduce concurrency: `export MCP_TOOL_DEFAULT_CONCURRENCY=1` | --- ## 🤝 Contributing We welcome contributions! Here's how you can help: ### How to Contribute 1. **Fork the repository** ```bash git clone https://github.com/YOUR_USERNAME/Security-MCP-Server.git cd Security-MCP-Server ``` 2. **Create a feature branch** ```bash git checkout -b feature/amazing-feature ``` 3. **Make your changes** - Add features or fix bugs - Write tests - Update documentation - Follow code style 4. **Test your changes** ```bash pytest pytest --cov=mcp_server ``` 5. **Commit with clear messages** ```bash git commit -m "feat: add amazing feature" ``` Commit message format: - `feat:` New feature - `fix:` Bug fix - `docs:` Documentation - `test:` Testing - `refactor:` Code refactoring - `perf:` Performance improvement 6. **Push and create PR** ```bash git push origin feature/amazing-feature ``` Then create a Pull Request on GitHub ### Development Setup ```bash # Clone your fork git clone https://github.com/YOUR_USERNAME/Security-MCP-Server.git cd Security-MCP-Server # Add upstream remote git remote add upstream https://github.com/nordeim/Security-MCP-Server.git # Create virtual environment python3.11 -m venv venv source venv/bin/activate # Install dev dependencies pip install -r requirements.txt pip install -r requirements-dev.txt # If exists pip install -e . # Install pre-commit hooks pip install pre-commit pre-commit install # Run tests pytest # Run linters flake8 mcp_server/ black --check mcp_server/ mypy mcp_server/ ``` ### Pull Request Process 1. ✅ **Update documentation** if needed 2. ✅ **Add tests** for new features 3. ✅ **Ensure all tests pass** 4. ✅ **Update CHANGELOG.md** 5. ✅ **Follow code style** (PEP 8) 6. ✅ **Keep PRs focused** (one feature/fix per PR) 7. ✅ **Respond to review feedback** ### Code of Conduct - Be respectful and inclusive - Constructive feedback only - Focus on the code, not the person - Help others learn and grow ### Community - 💬 [GitHub Discussions](https://github.com/nordeim/Security-MCP-Server/discussions) - 🐛 [Issue Tracker](https://github.com/nordeim/Security-MCP-Server/issues) - 📧 [Mailing List](mailto:mcp-server-dev@example.com) --- ## 🗺️ Roadmap ### Current Version: 2.0.0 ✅ Production-ready release with comprehensive features. ### Planned Features #### v2.1.0 (Q2 2024) - [ ] Additional Tools - [ ] Masscan integration - [ ] Nikto web scanner - [ ] SSLScan for certificate analysis - [ ] Enhanced Metrics - [ ] OpenTelemetry support - [ ] Distributed tracing - [ ] Authentication - [ ] API key authentication - [ ] JWT support - [ ] OAuth2 integration #### v2.2.0 (Q3 2024) - [ ] Result Storage - [ ] Database integration (PostgreSQL) - [ ] Historical scan data - [ ] Result comparison - [ ] Scheduled Scans - [ ] Cron-like scheduling - [ ] Recurring scans - [ ] Email notifications - [ ] Web UI - [ ] Result visualization - [ ] Scan management - [ ] Real-time dashboard #### v3.0.0 (Q4 2024) - [ ] Multi-Tenancy - [ ] Organization support - [ ] User management - [ ] RBAC - [ ] Advanced Security - [ ] mTLS support - [ ] Hardware security module integration - [ ] Audit logging - [ ] High Availability - [ ] Redis for state - [ ] Leader election - [ ] Distributed execution ### Known Limitations - IPv6 support not yet implemented - Windows resource limits not enforced (Linux only) - Single-instance deployment (no clustering yet) - Limited to command-line tools (no native SDK integrations) ### Community Requests Vote on features in [GitHub Discussions](https://github.com/nordeim/Security-MCP-Server/discussions/categories/feature-requests)! --- ## 📄 License & Credits ### License This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details. ``` MIT License Copyright (c) 2024 Security MCP Server Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ``` ### Authors - **Nordeim** - *Initial work* - [@nordeim](https://github.com/nordeim) ### Contributors Thanks to all contributors who have helped make this project better! <!-- Contributors will be automatically listed here --> ### Acknowledgments - **Model Context Protocol** - For the excellent MCP specification - **Anthropic** - For Claude and MCP inspiration - **Nmap Project** - For the powerful network scanning tool - **FastAPI** - For the modern web framework - **Prometheus** - For metrics and monitoring - **Docker** - For containerization platform ### Third-Party Licenses This project uses the following open-source packages: | Package | License | Purpose | |---------|---------|---------| | Python | PSF | Programming language | | FastAPI | MIT | Web framework | | Uvicorn | BSD-3 | ASGI server | | Pydantic | MIT | Data validation | | prometheus-client | Apache-2.0 | Metrics | | psutil | BSD-3 | System monitoring | | PyYAML | MIT | Configuration | | nmap | GPL-2.0 | Network scanning | --- <div align="center"> ### ⭐ Star this repository if you find it helpful! ### 🐛 Found a bug? [Open an issue](https://github.com/nordeim/Security-MCP-Server/issues) ### 💡 Have an idea? [Start a discussion](https://github.com/nordeim/Security-MCP-Server/discussions) --- **Built with ❤️ by the Security MCP Server community** [⬆ Back to top](#-security-mcp-server) </div>

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/nordeim/Security-MCP-Server-v3'

If you have feedback or need assistance with the MCP directory API, please join our Discord server