AgentStack
MCP verified MIT Self-run

OT AIops

mcp-aiops-tools-ot-aiops · by AIops-tools

Governed OT data tap + diagnostics: OPC-UA/Modbus/S7/MC/MTConnect/MQTT-Sparkplug.

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add mcp-aiops-tools-ot-aiops

✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.

Security review

✓ Passed

No 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
Are you the author of OT AIops? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.

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:// via asyncua (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 → decode hint (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 native libsnap7). 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: pymcprotocolMC 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 bounded count= samples.

MQTT / Sparkplug B / UNS

  • Versions/variants: paho-mqttMQTT 3.1.1 & 5. Sparkplug B topic convention spBv1.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.proto generated module (depends only on protobuf). 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 the is_historical / is_null flags. 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 flags seq gaps / out-of-order. Primary-host awareness: STATE/ topics surface in sparkplug_node_list. sparkplug_decode_payload decodes 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_info reads the controller identity.
  • Connection params: host, slot (0 for CompactLogix; the CPU slot for a ControlLogix chassis), port (44818). protocol: ethernetip (alias eip).
  • 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. pysoem is 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; alias interface), optional expected_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) and ethercat_set_state are 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_computeOEE = Availability × Performance × Quality from production inputs (planned time, run time, ideal cycle, total/good counts). Each factor is reported raw + clamped to [0,1]; a capped performance >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.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet — be the first.

Versions

  • v0.1.1 Imported from the upstream source.