“读取出厂温度”--Modbus MCP
   
看,没人想记住那个登记簿 40001 是温度传感器。生命太短暂,Modbus地址太多。这是一个用于Modbus TCP设备的MCP服务器——您可以在YAML中定义设备配置文件,然后AI代理可以像文明人一样按名称读/写PLC寄存器。
它还附带了 内置模拟器,因为我们都知道你的桌子上没有PLC。(如果你这样做,请拂去灰尘。)
______________________________________________________________________
为什么存在
我一直在查看现有的Modbus MCP服务器,并不断发现同样的四个令人失望的地方:
- 无语义寄存器映射 --人工智能必须知道原始地址,比如
40001要求它“读取温度”会让你一脸茫然。 - 无数据类型转换 --所有内容都以原始uint16的形式返回,因为显然float32太花哨了。
- 无内置模拟器 --想测试吗?去买硬件。或者乞求同事。或者盯着天花板看。
- 无设备配置文件 --无法预先配置连接细节和注册映射,因此您可以像1998年一样一遍又一遍地键入相同的主机/端口/slave_id。
所以我做了不合理的事情,自己修好了这四个。
______________________________________________________________________
建筑
User (CLI / Chat / OpenClaw)
→ AI Agent (Claude / OpenClaw / etc.)
→ MCP Protocol (Streamable HTTP)
→ kc_modbus_mcp (FastMCP Server)
→ Profile Manager (YAML device profiles)
→ pymodbus (async Modbus TCP client)
→ Modbus TCP Device / Built-in Simulator特性
- 自然语言控制 --“读取出厂温度”就行了。显示器上没有粘贴地址查找表。
- YAML设备配置文件 --将寄存器名称映射到地址、数据类型、单位和缩放比例。最后,配置读起来像英语。
- 8个MCP工具 --5个基于配置文件的+3个原始模式,用于需要完全黑客的时候。
- 自动数据类型转换 --float32、int32、uint16、bool——支持字节顺序和小数位数,因为凌晨2点在脑子里做算术运算不是一种性格特征。
- 内置Modbus TCP模拟器 --正弦波温度、随机湿度/压力、可写线圈。你想象中的工厂做得很好。
- Docker就绪 --
docker compose up -d你在做生意。两个集装箱,零借口。 - OpenClaw技能 --为喜欢命令行生活方式的本地LLM代理编写包装器脚本。
______________________________________________________________________
演示
______________________________________________________________________
安全通知: 这是一个为可信局域网环境设计的POC/开发项目。MCP服务器未实现身份验证。原始模式允许对任何可访问的Modbus设备进行读/写访问。在没有额外安全措施的情况下,不要将服务端口暴露给公共互联网。
快速开始
三个端子,五分钟,无需焊接。
1.克隆并安装
git clone https://github.com/KerberosClaw/kc_modbus_mcp.git
cd kc_modbus_mcp
uv sync2.启动模拟器
uv run python simulator.py
# Modbus TCP simulator running on port 50203.启动MCP服务器
# In another terminal
uv run python server.py
# MCP server running on port 8765, loaded devices.yaml4.使用MCP客户端进行测试
npm install -g mcporter
mcporter config add modbus --url http://localhost:8765/mcp
mcporter call modbus.list_devices
mcporter call modbus.read_device device=factory_sensor register=temperature
mcporter call modbus.write_device device=factory_sensor register=motor_speed value=1500
mcporter call modbus.device_status device=factory_sensor或者使用Docker Compose
对于“我不想打开三个终端”的人群(可以理解):
docker compose up -d
# Simulator on :5020, MCP server on :8765______________________________________________________________________
设备配置文件(YAML)
这就是魔法发生的地方。好吧,“魔法”是慷慨的——它只是YAML。但这比记住十六进制地址要好。在中定义Modbus设备 devices.yaml:
devices:
factory_sensor:
host: 192.168.1.100
port: 502
slave_id: 1
byte_order: big # big | little | mixed
registers:
temperature:
address: 0
function_code: 3 # 3=holding, 4=input
data_type: float32 # uint16, int16, uint32, int32, float32, bool
scale: 0.1
unit: "°C"
access: read
description: "Ambient temperature sensor"
motor_speed:
address: 4
function_code: 3
data_type: uint16
unit: "RPM"
access: read_write
description: "Motor speed setpoint"
pump_on:
address: 0
function_code: 1 # 1=coil
data_type: bool
access: read_write
description: "Pump on/off switch"支持的数据类型
| 类型 | 寄存器 | 范围 |
|---|---|---|
bool | 线圈(1位) | 真/假 |
uint16 | 1 | 0 – 65535 |
int16 | 1 | -32768 – 32767 |
uint32 | 2 | 0 – 4294967295 |
int32 | 2 | -2147483648 – 2147483647 |
float32 | 2 | ieee754 |
支持的功能代码
| 代码 | 名称 | 访问权限 |
|---|---|---|
| 1 | 读取线圈 | 读取 |
| 2 | 读取离散输入 | 读取 |
| 3 | 读保持寄存器 | 读/写 |
| 4 | 读取输入寄存器 | 读取 |
______________________________________________________________________
MCP工具
配置文件模式(主)
用户友好的东西。这个项目存在的原因。
| 工具 | 说明 |
|---|---|
list_devices | 列出所有已配置的设备 |
list_registers | 列出带有元数据的设备的所有寄存器 |
read_device | 读取命名寄存器--返回转换值+单位 |
write_device | 将值写入命名寄存器 |
device_status | 检查设备是否在线 |
原始模式(高级)
因为当你需要绕过所有这些漂亮的抽象概念,像周二一样与寄存器交谈时。
| 工具 | 说明 |
|---|---|
read_registers | 按主机/端口/slave_id/fc/地址读取原始数据 |
write_registers | 按主机/端口/slave_id/fc/地址进行原始写入 |
scan_registers | 扫描非零值的地址范围 |
______________________________________________________________________
内置模拟器
一个基于pymodbus的Modbus TCP服务器,假装是一个工厂。数据是假的,但协议是真实的。不需要硬件——你的笔记本电脑现在就是工厂。
| 注册 | 地址 | FC | 类型 | 行为 |
|---|---|---|---|---|
| 温度 | HR 0-1 | 3 | float32 | 正弦波20~30°C |
| 湿度 | HR 2-3 | float32 | 随机40~60%RH | |
| motor_speed | HR 4 | 3 | uint16 | 保存写入值 |
| 压力 | IR 0 | 4 | uint16 | 随机900~1100kPa |
| pump_on | 线圈0 | 1 | bool | 保存写入值 |
| valve_open | 线圈1 | 1 | bool | 保存写入值 |
______________________________________________________________________
项目结构
kc_modbus_mcp/
├── server.py # MCP Server entry point
├── simulator.py # Built-in Modbus TCP simulator
├── devices.yaml # Example device profile
├── src/
│ ├── profile.py # YAML profile loader + register resolver
│ ├── client.py # pymodbus async client wrapper
│ ├── converter.py # Data type conversion (raw ↔ engineering value)
│ └── tools.py # MCP tool definitions
├── openclaw-skill/ # OpenClaw skill wrapper
├── tests/ # Automated tests
├── docker-compose.yml
├── Dockerfile
├── pyproject.toml
├── DESIGN.md # Design document (Chinese)
├── .env.example
└── LICENSE______________________________________________________________________
环境变量
包括合理的默认值,因为任何人都不应该仅仅为了看看它们是否正常工作而进行配置。
| 变量 | 默认值 | 描述 |
|---|---|---|
MODBUS_PROFILE | devices.yaml | 设备配置文件YAML的路径 |
MCP_HOST | 0.0.0.0 | MCP服务器绑定地址 |
MCP_PORT | 8765 | MCP服务器端口 |
SIMULATOR_HOST | 0.0.0.0 | 模拟器绑定地址 |
SIMULATOR_PORT | 5020 | 模拟器端口 |
______________________________________________________________________
OpenClaw 集成
对于OpenClaw/local LLM代理,包装器脚本将冗长的MCP调用转换为您可以实际键入而不会出现腕管综合征的内容:
modbus list
modbus status factory_sensor
modbus read factory_sensor temperature
modbus write factory_sensor motor_speed 1500看 openclaw-skill/SKILL.md 了解详情。
______________________________________________________________________
待办事项
我一定会做的事情。最终。可能。
- \[\]多设备连接池
- \[\]具有可配置缓存间隔的轮询模式
- \[\]更改检测(值更改时通知)
- \[\]Modbus RTU(串行)支持
- \[\]用于设备配置文件编辑的Web UI
______________________________________________________________________
