Skip to main content
Glama

Security MCP Server

by nordeim

🛡️ Security MCP Server

Production-Ready Model Context Protocol Server for Network Security Tools

Build Status Coverage License: MIT Python 3.11+ Docker MCP Protocol

Quick StartDocumentationExamplesContributing


📋 Table of Contents

For Users

For Developers

For Operators

Additional


🌟 Overview

What is Security MCP Server?

Security MCP Server is a production-ready implementation of the Model Context Protocol (MCP) 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

🔒 Security First

  • RFC1918/private IP enforcement

  • Command injection prevention

  • Whitelist-based validation

  • Resource limits

  • Intrusive operation controls

🏗️ Production Ready

  • Circuit breaker pattern

  • Health monitoring

  • Prometheus metrics

  • Graceful shutdown

  • Hot-reload configuration

🚀 Developer Friendly

  • Easy tool creation

  • Comprehensive testing

  • Clear documentation

  • Docker support

  • Extensible architecture

🛠️ Tool Ecosystem

  • Nmap - Network scanning

  • Extensible - Add your own

  • Template-based - Quick scans

  • Validated - Safe inputs

📊 Observability

  • Real-time health checks

  • Prometheus metrics

  • Structured logging

  • Performance tracking

  • Error monitoring

🔄 Resilient

  • Auto-retry with backoff

  • Circuit breaker protection

  • Resource limits

  • Timeout enforcement

  • Graceful degradation

💡 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

# 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

# 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

# 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

# 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


🏗️ Architecture

System Architecture

%%{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

%%{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

%%{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)

# 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:

%%{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:

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:

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):

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:

class MyTool(MCPBaseTool): command_name = "mytool" allowed_flags = ["-flag1", "-flag2"] default_timeout_sec = 60.0 # Auto-discovered and registered!

See 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

git clone https://github.com/nordeim/Security-MCP-Server.git cd Security-MCP-Server

2. Create Virtual Environment

# Create virtual environment python3.11 -m venv venv # Activate (Linux/macOS) source venv/bin/activate # Activate (Windows) venv\Scripts\activate

3. Install Dependencies

# 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

# 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

# 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

# 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)

# 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

# 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)

# 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:

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

Configuration File

config/config.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:

export MCP_CONFIG_FILE=config/config.yaml python -m mcp_server.server

🎮 Usage Guide

Running the Server

Stdio Mode (for Claude Desktop)

# 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)

# 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

# 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:

# macOS ~/Library/Application Support/Claude/config.json # Windows %APPDATA%\Claude\config.json # Linux ~/.config/Claude/config.json
  1. Add MCP server configuration:

{ "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" } } } }
  1. Restart Claude Desktop

  2. 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

# 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

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

# 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:

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):

{ "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):

{ "detail": "Target must be RFC1918 IPv4 or a .lab.internal hostname" }

Response (Rate Limited):

{ "detail": { "error": "Rate limit exceeded", "message": "Too many requests for NmapTool. Try again later.", "retry_after": 60 } }

Health Check

GET /health HTTP/1.1

Response (Healthy - 200 OK):

{ "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):

{ "status": "degraded", "timestamp": "2024-01-15T10:30:00Z", "checks": { "system_resources": { "status": "degraded", "message": "Memory usage high: 85.0%" } } }

Response (Unhealthy - 503 Service Unavailable):

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

# 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

# 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:

sudo useradd -r -s /bin/bash -d /opt/mcp-server mcp sudo mkdir -p /opt/mcp-server sudo chown mcp:mcp /opt/mcp-server
  1. Install as mcp user:

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 .
  1. Create systemd service:

sudo nano /etc/systemd/system/mcp-server.service
[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
  1. Enable and start:

sudo systemctl daemon-reload sudo systemctl enable mcp-server sudo systemctl start mcp-server sudo systemctl status mcp-server
  1. Configure reverse proxy (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:

# 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:

# 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)

deployment.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:

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:

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:

kubectl apply -f deployment.yaml kubectl apply -f service.yaml kubectl apply -f ingress.yaml kubectl get pods -l app=mcp-server

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:

touch mcp_server/tools/ping_tool.py

2. Implement tool class:

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

# 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:

pytest tests/unit/tools/test_ping_tool.py -v

6. Use your tool:

# 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

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

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

# 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):

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:

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:

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

# 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):

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

Import this into Grafana for instant monitoring:

{ "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" } ] } ] } }

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):

export LOG_FORMAT=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

# 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

# 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

# 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

# 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

# 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

# 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


🔒 Security

Security Model

Security MCP Server implements defense in depth with multiple security layers:

%%{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

  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

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.

A: Set the environment variable:

export MCP_SECURITY_ALLOW_INTRUSIVE=true

Or in configuration file:

security: allow_intrusive: true

WARNING: Only enable in controlled lab environments. Intrusive scans can be detected and may violate policies.

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:

# Increase threshold export MCP_CIRCUIT_BREAKER_FAILURE_THRESHOLD=10 # Decrease recovery timeout export MCP_CIRCUIT_BREAKER_RECOVERY_TIMEOUT=30

Force close:

from mcp_server.tools.nmap_tool import NmapTool tool = NmapTool() await tool._circuit_breaker.force_close()

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

A: See the 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!

A: Yes! Configure mcp.json in Claude Desktop:

{ "mcpServers": { "security-tools": { "command": "/path/to/venv/bin/python", "args": ["-m", "mcp_server.server"], "env": { "MCP_SERVER_TRANSPORT": "stdio" } } } }

See Claude Desktop Integration for details.

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.

A: Multiple options:

  1. Health Check:

    curl http://localhost:8080/health
  2. Prometheus Metrics:

    curl http://localhost:8080/metrics
  3. Server-Sent Events (real-time):

    curl http://localhost:8080/events
  4. Grafana Dashboard: Import the provided JSON (see Metrics)

  5. Logs:

    ./scripts/mcp_server_launcher.sh logs

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

    git clone https://github.com/YOUR_USERNAME/Security-MCP-Server.git cd Security-MCP-Server
  2. Create a feature branch

    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

    pytest pytest --cov=mcp_server
  5. Commit with clear messages

    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

    git push origin feature/amazing-feature

    Then create a Pull Request on GitHub

Development Setup

# 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


🗺️ 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!


📄 License & Credits

License

This project is licensed under the MIT License - see the 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

Contributors

Thanks to all contributors who have helped make this project better!

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


⭐ Star this repository if you find it helpful!

🐛 Found a bug? Open an issue

💡 Have an idea? Start a discussion


Built with ❤️ by the Security MCP Server community

⬆ Back to top

-
security - not tested
F
license - not found
-
quality - not tested

hybrid server

The server is able to function both locally and remotely, depending on the configuration or use case.

Provides AI agents like Claude with secure, controlled access to network security tools like nmap for scanning private networks and lab environments. Features comprehensive safety controls, circuit breakers, and production-ready monitoring.

  1. Production-Ready Model Context Protocol Server for Network Security Tools
    1. 📋 Table of Contents
      1. For Users
      2. For Developers
      3. For Operators
      4. Additional
    2. 🌟 Overview
      1. What is Security MCP Server?
      2. 🎯 Key Features
      3. 💡 Use Cases
      4. 🎬 Quick Demo
    3. 🚀 Quick Start
      1. Prerequisites
      2. One-Command Installation
      3. First Run
      4. Verify Installation
      5. Next Steps
    4. 🏗️ Architecture
      1. System Architecture
      2. Component Overview
      3. Tool Execution Flow
      4. Health Check System
      5. Technology Stack
    5. ✨ Features Deep Dive
      1. 🔒 Security Controls
      2. 🔄 Circuit Breaker Pattern
      3. 📊 Health Monitoring
      4. 📈 Metrics & Observability
      5. ⚙️ Configuration Management
      6. 🛠️ Tool Ecosystem
    6. 📦 Installation & Setup
      1. System Requirements
      2. Non-Docker Installation
      3. Docker Installation
      4. Configuration Guide
    7. 🎮 Usage Guide
      1. Running the Server
      2. Claude Desktop Integration
      3. Tool Invocation Examples
      4. HTTP API Reference
    8. 🚀 Deployment Guide
      1. Development Deployment
      2. Production Deployment
      3. Kubernetes Deployment (Bonus)
      4. Deployment Checklist
    9. 🛠️ Developer Guide
      1. Project Structure
      2. Module Responsibilities
      3. Creating Custom Tools
      4. Best Practices
      5. Testing Guide
      6. Code Style & Standards
    10. 📊 Monitoring & Operations
      1. Health Checks
      2. Metrics
      3. Logging
      4. Troubleshooting
    11. 🔒 Security
      1. Security Model
      2. Network Restrictions
      3. Input Validation
      4. Resource Limits
      5. Reporting Vulnerabilities
      6. Security Best Practices
    12. ❓ FAQ & Troubleshooting
      1. Frequently Asked Questions
      2. Common Issues & Solutions
    13. 🤝 Contributing
      1. How to Contribute
      2. Development Setup
      3. Pull Request Process
      4. Code of Conduct
      5. Community
    14. 🗺️ Roadmap
      1. Current Version: 2.0.0 ✅
      2. Planned Features
      3. Known Limitations
      4. Community Requests
    15. 📄 License & Credits
      1. License
      2. Authors
      3. Contributors
      4. Acknowledgments
      5. Third-Party Licenses
      6. ⭐ Star this repository if you find it helpful!
      7. 🐛 Found a bug? Open an issue
      8. 💡 Have an idea? Start a discussion

    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