Production-ready MCP server for Industrial IoT, Edge Computing and SCADA/PLC systems.
Secure, enterprise-grade Model Context Protocol (MCP) server that exposes a unified tool interface over HTTP (FastAPI) and integrates MQTT + Modbus with InfluxDB (time-series) and Redis (cache).
Designed to work seamlessly with PolyMCP - enabling AI agents (Claude, OpenAI, Ollama, and more) to control industrial infrastructure through natural language.
| Protocol | Description |
|---|---|
| MQTT | IoT sensors and actuators (optional TLS) |
| Modbus TCP/RTU | PLCs and industrial devices |
| InfluxDB 2.x | Time-series data storage |
| Redis | High-performance caching |
| Simulation Mode | Full testing without hardware |
- Authentication: API key (
X-API-Key) + JWT bearer tokens - Access Control: IP allowlisting (CIDR), rate limiting
- Data Protection: Input validation, Fernet encryption, HMAC signatures
- Audit Trail: Tamper-evident logging with HMAC chaining
- Real-time sensor monitoring
- Historical queries with aggregation (mean, max, min, sum, count, median)
- Actuator command execution
- PLC register / coil read-write
- Multi-priority alarm system with acknowledge workflow
- Device topology and system status reporting
| Requirement | Notes |
|---|---|
| Python 3.8+ | 3.9+ recommended |
| Requirement | Notes |
|---|---|
| Python 3.8+ | 3.9+ recommended |
| MQTT Broker | Optional if using Modbus only |
| InfluxDB 2.0+ | Optional, for historical data |
| Redis | Optional, for caching |
| Modbus Devices | Optional, for PLC integration |
# Clone repository
git clone https://github.com/yourusername/iot-mcp-server.git
cd iot-mcp-server
# Create virtual environment
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# Install dependencies
pip install -r requirements.txt# MCP Server Framework
polymcp>=1.2.6
# Web Framework
fastapi>=0.104.1
uvicorn[standard]>=0.24.0
pydantic>=2.5.0
docstring-parser>=0.15
python-multipart>=0.0.6
# Protocols (Production Mode)
paho-mqtt>=1.6.1
pymodbus>=3.5.2
pyserial>=3.5
# Storage (Production Mode)
redis>=5.0.1
influxdb-client>=1.38.0
# Configuration
pyyaml>=6.0.1
# Security (Production Mode)
bleach>=6.0.0
cryptography>=41.0.0
passlib[bcrypt]>=1.7.4
pyjwt>=2.8.0
# Monitoring (Production Mode)
prometheus-client>=0.19.0# Minimal dependencies for simulation mode
polymcp>=1.2.6
fastapi>=0.104.1
uvicorn[standard]>=0.24.0
pydantic>=2.5.0
docstring-parser>=0.15
⚠️ Note: This project uses Pydantic v2 APIs. Pydantic v1 is not supported.
Perfect for testing and development:
python IoT_mcp_sim.pyOutput:
============================================================
IoT/Edge MCP Server - MODALITÀ SIMULAZIONE
============================================================
Dispositivi simulati disponibili:
- 10 Sensori
- 6 Attuatori
- 1 PLC Modbus
Server in ascolto su http://localhost:8000
Documentazione API: http://localhost:8000/docs
============================================================
# Set required environment variables
export IOT_ENV=production
export JWT_SECRET_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
export ENCRYPTION_KEY=$(python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())")
export AUDIT_HMAC_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
export MQTT_COMMAND_HMAC_KEY=$(python -c "import secrets; print(secrets.token_urlsafe(32))")
export ALLOWED_IP_RANGES="10.0.0.0/8,192.168.0.0/16"
export API_KEYS='{"admin":"your-secure-api-key"}'
# Start server
python IoT_mcp.pyDefault bind: http://0.0.0.0:8000
This MCP server is designed to work seamlessly with PolyMCP - a powerful framework for orchestrating MCP servers with AI agents.
pip install polymcp>=1.2.8#!/usr/bin/env python3
"""IoT MCP Chat - Control industrial equipment with AI"""
import asyncio
from polymcp.polyagent import UnifiedPolyAgent, OllamaProvider
async def main():
# Initialize your LLM provider
llm = OllamaProvider(model="llama3.1:8b", temperature=0.1)
# Connect to IoT MCP server
agent = UnifiedPolyAgent(
llm_provider=llm,
mcp_servers=["http://localhost:8000/mcp"],
verbose=True
)
async with agent:
print("✅ IoT MCP Server connected!\n")
# Chat loop
while True:
user_input = input("\n🏭 You: ")
if user_input.lower() in ['exit', 'quit']:
print("Goodbye!")
break
result = await agent.run_async(user_input, max_steps=5)
print(f"\n🤖 System: {result}")
if __name__ == "__main__":
asyncio.run(main())PolyMCP supports multiple LLM providers out of the box:
from polymcp.polyagent import UnifiedPolyAgent, OllamaProvider
llm = OllamaProvider(model="llama3.1:8b", temperature=0.1)
agent = UnifiedPolyAgent(llm_provider=llm, mcp_servers=["http://localhost:8000/mcp"])from polymcp.polyagent import UnifiedPolyAgent, OpenAIProvider
llm = OpenAIProvider(model="gpt-4", api_key="your-api-key")
agent = UnifiedPolyAgent(llm_provider=llm, mcp_servers=["http://localhost:8000/mcp"])from polymcp.polyagent import UnifiedPolyAgent, AnthropicProvider
llm = AnthropicProvider(model="claude-3-5-sonnet-20241022", api_key="your-api-key")
agent = UnifiedPolyAgent(llm_provider=llm, mcp_servers=["http://localhost:8000/mcp"])Once connected, you can ask the AI agent to:
| Command | What it does |
|---|---|
| "Check all temperature sensors" | Reads values from all temp sensors |
| "What's the average pressure in tank 1 over the last 6 hours?" | Queries historical data with aggregation |
| "Open the main valve to 75%" | Executes actuator command |
| "Show me all critical alarms" | Lists active alarms filtered by priority |
| "Read Modbus registers 0-10 from PLC 01" | Direct PLC communication |
| "If temperature exceeds 50°C, alert me" | Conditional monitoring |
| "Generate a status report" | Gets system topology and status |
That's it! PolyMCP handles all the complexity of:
- Tool discovery and selection
- Multi-step industrial process automation
- Real-time monitoring and alerting
- Complex decision logic implementation
This server exposes MCP tools through HTTP endpoints provided by polymcp-toolkit:
| Endpoint | Method | Description |
|---|---|---|
/mcp/list_tools |
GET | List all available tools |
/mcp/invoke/{tool_name} |
POST | Invoke a tool (JSON body) |
/health |
GET | Health check |
/metrics |
GET | Prometheus metrics (production) |
/docs |
GET | OpenAPI documentation |
| Tool | Parameters | Description |
|---|---|---|
read_sensor |
sensor_id |
Read current value from a sensor |
read_multiple_sensors |
sensor_ids (list) |
Batch read multiple sensors |
get_sensor_history |
sensor_id, hours, aggregation |
Query historical data (max 168h) |
| Tool | Parameters | Description |
|---|---|---|
execute_actuator_command |
actuator_id, command, parameters |
Send command to actuator |
| Tool | Parameters | Description |
|---|---|---|
get_device_topology |
- | View complete system architecture |
list_devices |
device_type (optional) |
List devices filtered by type |
get_system_status |
- | System health and statistics |
| Tool | Parameters | Description |
|---|---|---|
get_active_alarms |
priority (optional) |
View active alarms |
acknowledge_alarm |
alarm_id |
Acknowledge an alarm |
| Tool | Parameters | Description |
|---|---|---|
read_modbus_registers |
device_id, address, count |
Read holding registers |
write_modbus_register |
device_id, address, value |
Write single register |
Production mode adds:
| Tool | Parameters | Description |
|---|---|---|
read_modbus_coils |
device_id, address, count |
Read coils (digital inputs) |
write_modbus_coil |
device_id, address, value |
Write single coil |
In simulation mode, the following devices are available for testing:
| ID | Type | Location |
|---|---|---|
temp_sensor_01 |
Temperature | production_line_1 |
temp_sensor_02 |
Temperature | production_line_2 |
humidity_sensor_01 |
Humidity | room_a |
pressure_sensor_01 |
Pressure | tank_1 |
pressure_sensor_02 |
Pressure | tank_2 |
flow_sensor_01 |
Flow | main_pipe |
level_sensor_01 |
Level | tank_1 |
vibration_sensor_01 |
Vibration | motor_1 |
current_sensor_01 |
Current | motor_1 |
voltage_sensor_01 |
Voltage | main_panel |
| ID | Type | Commands |
|---|---|---|
valve_01 |
Valve | open, close, set_position |
valve_02 |
Valve | open, close, set_position |
pump_01 |
Pump | on, off, set_speed |
motor_01 |
Motor | start, stop, set_speed |
motor_02 |
Motor | start, stop, set_speed |
relay_01 |
Relay | on, off |
| ID | Type | Registers |
|---|---|---|
plc_01 |
Modbus PLC | 0-99 (simulated) |
export IOT_ENV=production
export JWT_SECRET_KEY="your-jwt-secret"
export ENCRYPTION_KEY="your-fernet-key"
export AUDIT_HMAC_KEY="your-audit-hmac-key"
export MQTT_COMMAND_HMAC_KEY="your-mqtt-hmac-key"export ALLOWED_IP_RANGES="10.0.0.0/8,192.168.0.0/16"
export API_KEYS='{"monitoring":"key1","automation":"key2"}'# MQTT
export MQTT_BROKER="localhost"
export MQTT_PORT="8883"
export MQTT_USE_TLS="true"
export MQTT_USERNAME="user"
export MQTT_PASSWORD="password"
# InfluxDB
export INFLUX_URL="https://localhost:8086"
export INFLUX_TOKEN="your-token"
export INFLUX_ORG="iot"
export INFLUX_BUCKET="sensors"
# Redis
export REDIS_HOST="localhost"
export REDIS_PORT="6379"
export REDIS_PASSWORD="redis-password"
# Rate Limits
export MAX_REQUESTS_PER_MINUTE="60"
export MAX_COMMANDS_PER_MINUTE="10"# ENCRYPTION_KEY (Fernet)
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
# JWT_SECRET_KEY / AUDIT_HMAC_KEY / MQTT_COMMAND_HMAC_KEY
python -c "import secrets; print(secrets.token_urlsafe(32))"Create iot_config.yaml:
mqtt:
broker: localhost
port: 8883
use_tls: true
ca_cert: /path/to/ca.crt
client_cert: /path/to/client.crt
client_key: /path/to/client.key
username: iot_user
password_encrypted: null
modbus:
devices:
- device_id: plc_01
type: tcp
host: 192.168.1.100
port: 502
unit: 1
max_read_registers: 100
allowed_addresses: [0, 1, 2, 3, 4, 5]
devices:
mqtt:
- id: temp_sensor_01
name: "Temperature Sensor Zone A"
type: sensor
topic: sensors/zone_a/temperature
metadata:
sensor_type: temperature
unit: celsius
- id: valve_01
name: "Main Water Valve"
type: actuator
topic: actuators/valves/main┌─────────────────────────────────────────────────────────────────┐
│ AI Agent │
│ (Claude / OpenAI / Ollama / etc.) │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PolyMCP │
│ (Tool Discovery & Orchestration) │
└────────────────────────────┬────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ IoT MCP Server │
│ (FastAPI + polymcp-toolkit) │
└────────────────────────────┬────────────────────────────────────┘
│
┌───────────────────┼───────────────────┐
│ │ │
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ MQTT Connector │ │ Modbus Connector│ │ Data Store │
│ (TLS, HMAC) │ │ (TCP/RTU) │ │ (Influx+Redis) │
└────────┬────────┘ └────────┬────────┘ └─────────────────┘
│ │
▼ ▼
┌─────────────────┐ ┌─────────────────┐
│ IoT Sensors & │ │ PLCs & RTUs │
│ Actuators │ │ │
└─────────────────┘ └─────────────────┘
Incoming Request
│
▼
┌─────────────────┐
│ Payload Size │ → 413 if > 1MB
│ Check │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Public Path? │ → /health, /metrics allowed
└────────┬────────┘
│
▼
┌─────────────────┐
│ IP Allowlist │ → 403 if not in CIDR range
└────────┬────────┘
│
▼
┌─────────────────┐
│ Rate Limit │ → 429 if exceeded
└────────┬────────┘
│
▼
┌─────────────────┐
│ Authentication │ → 401 if invalid
│ (API Key / JWT) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Tool Execution │
└─────────────────┘
| Type | Scope | Default Limit |
|---|---|---|
| HTTP Requests | Per IP | 60/minute |
| Actuator Commands | Global | 10/minute |
| Modbus Operations | Per device | 10/minute |
| Error | Code | Solution |
|---|---|---|
| Service not ready | 503 | Wait for startup; check logs |
| IP not allowed | 403 | Add IP to ALLOWED_IP_RANGES |
| Unauthorized | 401 | Check API key or JWT |
| Rate limit exceeded | 429 | Reduce frequency |
| Sensor not found | 400 | Check list_devices() for valid IDs |
# Check health
curl http://localhost:8000/health
# List available tools
curl http://localhost:8000/mcp/list_tools
# View logs
tail -f iot_mcp_server.log| Use Case | Description |
|---|---|
| Smart Factory | AI-driven production line optimization |
| Building Automation | Intelligent HVAC and lighting control |
| Energy Management | Real-time consumption monitoring |
| Predictive Maintenance | Equipment failure prediction |
| Quality Control | Automated anomaly detection |
| Emergency Response | AI-managed incident handling |
MIT License - See LICENSE file
- Fork the repository
- Create a branch:
git checkout -b feature/my-feature - Commit changes:
git commit -m "Add my feature" - Push branch:
git push origin feature/my-feature - Open a Pull Request
- PolyMCP - AI agent framework for MCP servers
- Model Context Protocol - Open protocol for AI tool integration
- MQTT Protocol - Lightweight IoT messaging
- Modbus Protocol - Industrial communication standard
This MCP server bridges Industrial IoT and AI agents. With PolyMCP, you can:
- Natural Language Control - "Check all pressure sensors and alert if any are abnormal"
- Complex Automation - AI orchestrates multi-step industrial processes
- Predictive Maintenance - AI analyzes trends and predicts failures
- Energy Optimization - AI optimizes equipment usage
- Incident Response - AI handles alarms and executes emergency procedures
No complex industrial protocols to learn - PolyMCP and AI handle everything!
⚠️ Production Deployment: Always use strong secrets, proper network isolation, and TLS termination via reverse proxy.
Designed for PolyMCP 🚀
Star ⭐ this repo if you find it useful!