Install
$ agentstack add mcp-aiops-tools-ot-aiops ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.1 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
About
OT-AIops
Governed, vendor-neutral industrial data tap + intelligent troubleshooting for AI agents — across OPC-UA (incl. Historical Access), Modbus-TCP, S7comm, Mitsubishi MC, MTConnect, MQTT/Sparkplug B (full decode), EtherNet/IP (Rockwell/Allen-Bradley Logix), and EtherCAT (pysoem/SOEM fieldbus master) — plus OEE/downtime, active asset-inventory, and change-of-value analytics.
OT-AIops is the OT/industrial member of AIops-tools. It is a factory-level, vendor-neutral, governed data tap that lets an AI agent safely read industrial control systems across many field protocols, plus a cross-protocol intelligence layer that localizes "no data" breaks, analyzes alarm floods (ISA-18.2), ranks unhealthy tags, computes OEE / categorizes downtime, and builds an active asset register. Read-first by design; the few write/command paths are OT-dangerous and gated by MOC discipline. Every tool runs through a vendored governance harness (audit / budget / risk-tier / undo).
> ⚠️ Preview / v0.3.0 — validated against an in-process OPC-UA simulator (incl. HDA), mocked Modbus/S7/Mitsubishi/EtherNet-IP(pycomm3)/EtherCAT(pysoem) clients, static MTConnect XML fixtures, and synthetic MQTT/Sparkplug B protobuf payloads. NOT tested against live PLCs / SCADA / brokers / Logix controllers / EtherCAT slaves. EtherCAT is hard-real-time and has no software simulator (Linux + root + a real bus only), so it is entirely unverified against hardware. See Safety.
Why
OT is exactly where you want an agent on a tight leash: read first, never blind-write. OT-AIops is the safe, neutral read wedge — one package, one MCP server, many protocols — with governance and an intelligence layer that turns raw reads into actionable diagnoses.
Consolidated capability matrix
| Protocol | Tool | Operation | R/W | risktier | Returns (key fields) | |----------|------|-----------|:---:|:---------:|----------------------| | OPC-UA | opcua_server_info | server status | R | low | state, productname, namespaces | | OPC-UA | opcua_browse | browse node tree | R | low | [{nodeid, browsename, depth}] | | OPC-UA | opcua_read_node | read one node | R | low | value, datatype, sourcetimestamp, good | | OPC-UA | opcua_read_many | batch read | R | low | [{nodeid, value, ...}] | | OPC-UA | opcua_subscribe_sample | bounded sample | R | low | {collected, samples[]} | | OPC-UA | opcua_read_alarms | alarm surfacing | R | low | {activealarms[], activecount} | | OPC-UA | opcua_read_history | Historical Access (HDA) | R | low | {supported, count, values[]} | | OPC-UA | health_summary | threshold classify | R | low | {overall, counts, offenders[]} | | OPC-UA | anomaly_scan | stddev outliers | R | low | {mean, stddev, outliers[]} | | Modbus | modbus_read_holding | FC03 | R | low | {rawregisters, decoded[]} | | Modbus | modbus_read_input | FC04 | R | low | {rawregisters, decoded[]} | | Modbus | modbus_read_coils | FC01 | R | low | {bits[]} | | Modbus | modbus_read_discrete | FC02 | R | low | {bits[]} | | Modbus | modbus_health_summary | threshold classify | R | low | {overall, counts, offenders[]} | | S7comm | s7_cpu_info | CPU id + run/stop | R | low | {cpustatus, cpuinfo} | | S7comm | s7_read_area | read DB/M/I/Q | R | low | {items:[{address, value}]} | | S7comm | s7_read_db | read data block | R | low | {items:[{address, value}]} | | S7comm | s7_read_many | batch addresses | R | low | {items:[{address, value}]} | | S7comm | s7_write_db | write data block | W | high/MOC | {before, written, undoid} | | Mitsubishi MC | mc_cpu_status | CPU type | R | low | {cputype, cpucode} | | Mitsubishi MC | mc_read_words | word devices | R | low | {words[]} | | Mitsubishi MC | mc_read_bits | bit devices | R | low | {bits[]} | | Mitsubishi MC | mc_read_many | random read | R | low | {words[], dwords[]} | | Mitsubishi MC | mc_write_words | write words | W | high/MOC | {before, written, undoid} | | MTConnect | mtconnect_probe | device model | R | low | {devices:[{components:[{dataitems}]}]} | | MTConnect | mtconnect_current | latest values | R | low | {observations[]} | | MTConnect | mtconnect_sample | bounded stream | R | low | {observations[]} | | MTConnect | mtconnect_assets | assets | R | low | {assets[]} | | MTConnect | mtconnect_oee_snapshot | OEE inputs | R | low | {availability, execution, verdict} | | MQTT/Sparkplug | mqtt_read_topic | bounded read | R | low | {messages:[{topic, payload}]} | | MQTT/Sparkplug | sparkplug_subscribe_sample | bounded SpB sample (full decode) | R | low | {samples:[{sparkplug, payload:{metrics[]}}], seqgapcount} | | MQTT/Sparkplug | sparkplug_decode_payload | decode raw SpB payload | R | low | {metrics:[{name, alias, datatype, value, ishistorical}]} | | MQTT/Sparkplug | sparkplug_node_list | node discovery + state | R | low | {nodes:[{groupid, edgenodeid, online, devices}], primaryhosts[]} | | MQTT/Sparkplug | uns_browse | topic-tree browse | R | low | {topics[], tree{}} | | MQTT/Sparkplug | mqtt_publish | publish/command | W | high/MOC | {publishedbytes, applied} | | EtherNet/IP | eip_controller_info | Logix controller id | R | low | {controller:{vendor, productname, revision, serial}} | | EtherNet/IP | eip_list_tags | tag discovery | R | low | {tagcount, tags:[{name, datatype, structure}]} | | EtherNet/IP | eip_read_tag | read one tag/array | R | low | {tag, value, type, good} | | EtherNet/IP | eip_read_many | batch read | R | low | {items:[{tag, value, type}]} | | EtherNet/IP | eip_write_tag | write tag | W | high/MOC | {before, written, undoid} | | Diagnostics | diagnose_dataflow | localize no-data | R | low | {verdict, diagnosis, hops[]} | | Diagnostics | alarm_bad_actors | ISA-18.2 flood | R | low | {floodverdict, topoffenders[]} | | Diagnostics | tag_health | offender ranking | R | low | {overall, offenders[]} | | Diagnostics | historian_health | gap/flatline | R | low | {verdict, gaps[]} | | Analytics | oee_compute | OEE = A×P×Q | R | low | {availability, performance, quality, oee, oeepct} | | Analytics | downtime_events | stoppage detect + categorize | R | low | {eventcount, totaldowntimes, bycategory, events[]} | | Analytics | oee_multidim | OEE machine×part×shift | R | low | {matrix[], worstperformers[], meanoee} | | Analytics | asset_inventory | active fingerprint | R | low | {assets:[{protocol, vendor, model, firmware, reachable}]} | | Analytics | monitor_changes | bounded change-of-value | R | low | {changecount, changes:[{value, previous, wallclock}]} | | EtherCAT | ethercat_master_state | master/WKC + slave count | R | low | {masterstate, expectedworkingcounter, slavesfound, slavesexpected} | | EtherCAT | ethercat_slaves | bus scan | R | low | {slavecount, slaves:[{index, name, vendorid, productcode, state}]} | | EtherCAT | ethercat_slave_info | slave detail | R | low | {syncmanagers[], fmmus[], objectdictionary[], inputbytes} | | EtherCAT | ethercat_read_sdo | CoE SDO upload | R | low | {index, bytelength, hex, asuint} | | EtherCAT | ethercat_read_pdo | input PDO snapshot | R | low | {workingcounter, inputhex, inputbytelength} | | EtherCAT | ethercat_write_sdo | CoE SDO download | W | high/MOC | {before, written, applied} | | EtherCAT | ethercat_set_state | AL-state transition | W | high/MOC | {before, requested, reached, applied} | | Self | protocols_supported | capability map | R | low | {protocols[], diagnostics[], analytics[]} |
57 tools = 51 read + 6 write (MOC). The 51 reads = 41 protocol-read · 4 diagnostics · 5 analytics · 1 self. Run protocols_supported() (or ot-aiops protocols) for the live map.
Per-protocol reference
OPC-UA
- Versions/variants: binary
opc.tcp://viaasyncua(sync facade). Security: anonymous + username/password. Certificate message security (Sign / SignAndEncrypt) = roadmap, not validated. - Connection params:
endpoint_url,username(password encrypted),security_mode,security_policy. - Not supported / planned: cert security; real Alarms & Conditions event subscriptions (alarms are surfaced best-effort by browsing alarm-like boolean nodes).
Modbus-TCP
- Versions/variants: Modbus-TCP via
pymodbus. Read function codes FC01 (coils), FC02 (discrete), FC03 (holding), FC04 (input). Write FCs (FC05/06/15/16) = not implemented (read-only preview). - Connection params:
host,port(502),unit_id. Registers are untyped 16-bit words →decodehint (uint16/int16/uint32/int32/float32/raw); big-endian word order. - Coverage: many domestic 国产 PLCs (汇川 Inovance / 信捷 Xinje / 和利时 Hollysys / 台达 Delta) and any Modbus-TCP vendor.
S7comm (Siemens + 仿西门子 国产)
- Versions/variants:
pyS7(pure-Python, ISO-on-TCP / RFC1006 — no nativelibsnap7). S7-300/400/1200/1500 and compatible clones. Memory areas DB / M (merker) / I / Q. No protocol auth (CPU gates via "Permit access with PUT/GET"). - Connection params:
host,port(102),rack,slot(0/1 for 1200/1500; 0/2 common for 300/400). - Write:
s7_write_db= high risk_tier, MOC, dry-run default, captures BEFORE value + undo. - Not supported / planned: optimized/symbolic DB access on 1500 with "optimized block access" can require absolute-addressing config on the CPU.
Mitsubishi MC
- Versions/variants:
pymcprotocol— MC 3E frame (binary) only. 1E / 4E frames = not supported. PLC types Q / L / QnA / iQ-R / iQ-L. Devices: D/W/R (word), M/X/Y/B (bit). - Connection params:
host,port(5007 default; set to the module's open MC port),plctype. - Write:
mc_write_words= high/MOC/dry-run default, captures BEFORE + undo.
MTConnect (ALL CNC machine tools)
- Versions/variants: agent REST + XML (
requests+xml.etree), namespace-agnostic (parses MTConnect 1.x Devices/Streams/Assets schemas). Endpoints:/probe,/current,/sample,/assets. Read-only by specification. XML parsing is hardened (DTD/entity declarations rejected — XXE/billion-laughs defense). - Connection params:
agent_url(e.g.http://host:5000). - Not supported / planned: MTConnect streaming (long-poll
interval=); only boundedcount=samples.
MQTT / Sparkplug B / UNS
- Versions/variants:
paho-mqtt— MQTT 3.1.1 & 5. Sparkplug B topic conventionspBv1.0/{group}/{type}/{edge}/[device](NBIRTH/DBIRTH/NDATA/DDATA/NDEATH/DDEATH/STATE). TLS + username/password supported. - Full Sparkplug B decode (no optional extra): payloads are protobuf-decoded with a vendored, byte-for-byte copy of the official Eclipse Tahu
sparkplug_b.protogenerated module (depends only onprotobuf). Per metric you get name, alias (resolved to its name via the BIRTH model), datatype (Int8…Int64/UInt…/Float/Double/Boolean/String/DateTime/Text/UUID/DataSet/Bytes/File/Template/PropertySet…), value, timestamp, and theis_historical/is_nullflags. A birth/death + seq model tracks node/device online state (NBIRTH/DBIRTH ↔ NDEATH/DDEATH), builds the alias→name map from BIRTH, applies NDATA/DDATA by alias, and flagsseqgaps / out-of-order. Primary-host awareness:STATE/topics surface insparkplug_node_list.sparkplug_decode_payloaddecodes a single raw payload (base64/hex) offline. - Connection params:
host/broker,port(1883 / 8883 TLS),topic,use_tls,username(password encrypted). - Command:
mqtt_publish= high/MOC/dry-run default; a published command has no automatic inverse.
EtherNet/IP (Rockwell / Allen-Bradley)
- Supported: ControlLogix / CompactLogix (and GuardLogix) via CIP / EtherNet-IP using
pycomm3(pure-Python — no native deps). Tag-based, symbolic access: read/write tags by name (Conveyor.Speed,Array[3],Program:Main.X) and discover the controller's tag list at runtime (eip_list_tags, the headline feature).eip_controller_inforeads the controller identity. - Connection params:
host,slot(0 for CompactLogix; the CPU slot for a ControlLogix chassis),port(44818).protocol: ethernetip(aliaseip). - Write:
eip_write_tag= high risk_tier, MOC, dry-run default, captures BEFORE value + undo. - Not supported / planned: PLC-5 / SLC-500 (PCCC) and Micro800 are not supported = roadmap (Logix tag model only).
EtherCAT (pysoem / SOEM fieldbus master)
- Supported: a real EtherCAT master via
pysoem(the Python binding for the SOEM C stack). CoE SDO read (ethercat_read_sdo, acyclic mailbox upload) + SDO write (ethercat_write_sdo, download), input PDO read (ethercat_read_pdo, one bounded cyclic snapshot), bus scan / slave enumeration (ethercat_slaves,ethercat_slave_info— identity, SM/FMMU mapping, object-dictionary summary), master/working-counter state (ethercat_master_state), and AL-state transitions INIT↔PREOP↔SAFEOP↔OP (ethercat_set_state). - HARD REQUIREMENTS (no way around them): Linux, root or
CAP_NET_RAW, a dedicated NIC cabled to the bus, and real EtherCAT slave hardware.pysoemis an OPTIONAL extra:pip install ot-aiops[ethercat]— the base package installs and imports without it, and every EtherCAT tool then degrades to a teaching error (never crashes, never imports pysoem at module load). - NOT supported: no software simulator exists (unlike OPC-UA / Modbus) — EtherCAT is hardware-only and not testable in mock-only CI; macOS is unsupported. EoE / FoE / SoE mailbox protocols and full PDO-mapping decode/expansion = roadmap.
- Connection params:
nic(the dedicated interface name, e.g.eth1; aliasinterface), optionalexpected_slaves(a sanity check vs the bus scan).protocol: ethercat. - Operations matrix:
| Tool | Op | R/W | risk | Capture/notes | |------|----|:---:|:----:|---------------| | ethercat_master_state | master + WKC state, slave count | R | low | expected vs found | | ethercat_slaves | bus scan / enumerate | R | low | index/vendor/product/rev/addr/AL-state | | ethercat_slave_info | one-slave detail | R | low | SM/FMMU + OD summary | | ethercat_read_sdo | CoE SDO upload | R | low | hex + uint interpretation | | ethercat_read_pdo | input PDO snapshot | R | low | single cycle, never loops | | ethercat_write_sdo | CoE SDO download | W | high/MOC | before-value (SDO read-back) + undo | | ethercat_set_state | AL-state transition | W | high/MOC | before-state + undo; can start/stop motion |
- Write/state safety:
ethercat_write_sdo(hex little-endian bytes) andethercat_set_stateare high risk_tier, MOC, dry-run by default, capture the BEFORE value/state for undo, and need a CLI double-confirm. Changing EtherCAT state can START or STOP machine motion — treat with extreme care. 未经授权勿对生产控制系统写入.
OEE / downtime analytics (cross-protocol, read-only)
oee_compute— OEE = Availability × Performance × Quality from production inputs (planned time, run time, ideal cycle, total/good counts). Each factor is reported raw + clamped to [0,1]; acappedperformance >1.0 flags an optimistic ideal cycle.downtime_events— auto-detects running→stopped transitions in a{timestamp, state}series and produces stoppage events with durations, categorized (changeover / material / mechanical / quality / break / unknown, by keyword heuristics or a{state: category}override).oee_multidim— aggregates OEE across machine × part × shift (or any dimensions) from labelled records → the matrix + worst performers.- Operate over provided/collected inputs (fully testable without a plant). `mtconnectoeesnapsho
…
Source & license
This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: AIops-tools
- Source: AIops-tools/OT-AIops
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.1 Imported from the upstream source.