Skip to main content
Glama
industrial-aiops

OT-AIops

Industrial-AIOps

English · 中文

Ask an AI agent why the line stopped — and get an answer that cites its evidence.

A vendor-neutral, read-first data tap for the factory floor. It speaks 14 field protocols, correlates what it reads across them, and hands your agent an evidence-cited verdict instead of a guess. Every call is audited, and no reading ever phones home.

pip install "iaiops[opcua]"      # pick your protocol — or [all]
iaiops init                      # write ~/.iaiops/config.yaml
iaiops doctor                    # check the setup before you trust it

Prefer a container? The published image is cosign-signed and runs non-root. It speaks MCP over stdio, so keep stdin open and mount a volume for the audit store:

cosign verify --key deploy/margo/cosign.pub ghcr.io/industrial-aiops/iaiops:0.27.0-factory
docker run -i --rm -v iaiops-state:/home/iaiops/.iaiops \
  ghcr.io/industrial-aiops/iaiops:0.27.0-factory

For a hardened or air-gapped deployment (read-only rootfs, cap_drop: ALL, no-new-privileges, optional on-box LLM) use deploy/margo/compose.yaml and deploy/airgap/. The analysis engine needs no GPU and no model API — it is deterministic; an LLM is optional and only phrases the verdict.

What you get

Reads

OPC-UA (+ Historical Access, tag auto-discovery) · Modbus TCP/RTU · S7comm · Mitsubishi MC · Omron FINS · MTConnect · MQTT/Sparkplug B · EtherNet/IP · EtherCAT · PROFINET · SECS/GEM · HART-IP · BACnet/IP · IO-Link — plus read-only REST layers for BAS supervisors (Metasys / Niagara) and Ignition Gateway

Figures out

downtime root cause (the flagship copilot), alarm floods (ISA-18.2), broken dataflows, data trustworthiness, OEE, asset inventory, legacy PLC program explainer (ST/AWL/L5X)

Governs

audit · budget · risk-tier · undo — on every call, through one engine, from both MCP and CLI

Stays yours

no telemetry, no phone-home. Six tools can send data off-box by design (stream_publish, stream_publish_event, uns_publish, historian_push, mqtt_publish, rca_narrate) — IAIOPS_NO_EGRESS=1 withholds all six for an air-gapped posture

Nine per-industry editions ship in this package — fab · factory · process · building · water · warehouse · clinical · renewables · plcnext — each adding its own read-only advisory checks. Substation / utility telecontrol (IEC-104 · DNP3 · IEC-61850) ships separately as iaiops-energy.

Related MCP server: @inscada/mcp-server

Your first five minutes

Four commands. Only one of them touches a device, and it prints what it will send before it sends anything.

pip install "iaiops[modbus]"     # pick the protocol you actually have, or [all]
iaiops onboard status            # ← run this first. Contacts NOTHING.
iaiops doctor                    # config, secrets, reachability — and the version
iaiops readiness                 # every scenario and what each gap needs

onboard status answers the smaller question you have first: which of the six steps is this site on, and what is the one command that advances it? The six were always there and nothing stated the order. It is derived from your store and config.yaml every time, so there is no onboarding state to go stale — edit config.yaml by hand and the answer stays true.

readiness reads your config and local store and answers one question: which scenarios can this site run today, and what does each gap need? Every gap comes with the command that closes it, ranked by how much it unlocks. No agent, no cloud, no account, and nothing on the wire.

Then the path, in the order that matters — survey what is there, take a bounded sample, and only then explain it:

contacts a device?

Survey

iaiops scan planiaiops scan run

preview sends nothing; the run itemises every packet class it sent

Configure

iaiops onboard draft → you merge it into config.yaml

no — it reads the stored scan, and writes nothing

Tap

iaiops collect run line1 --duration 7d

yes — and it reports what it saw and what it missed

Declare

iaiops tags export → a person fills in roleiaiops tags apply --by <you>

no — the role column comes out empty on purpose

Explain

iaiops oee measure --since … --until … · iaiops investigate open · iaiops diag rca

no — all over collected history

See the whole thing run against a real device in about two minutes, including a genuine mid-run outage, with ./demo/oee-line/run_demo.sh — no hardware, no configuration, nothing written outside a temporary directory. demo/oee-line/ explains what each step is for and what the numbers do and do not claim.

Why read-first

OT is exactly where you want an agent on a tight leash. The read paths are the product; the few write paths are OT-dangerous, off by default, and gated by MOC discipline — dry-run, one-shot approval, undo capture, hash-chained audit.

Proving the analysis needs no model

The analysis layers cannot reach a language model. That is a guard, not a slogan: tests/test_brain_is_llm_free.py scans eight packages — brain, discovery, runtime, readiness, collect, knowledge, retain, connectors — for any import that could reach one, and an empty result is the guarantee. A model is used in exactly two places, and neither is load-bearing: rca_narrate rephrases a verdict that was already computed and already cited, and an agent front-end decides which tool to call. Remove both and the numbers are the same numbers.

That guard is static — it proves nothing can call a model. For a validation team the sentence they are asked to accept is the executed one, so it is executed:

iaiops verify determinism --out determinism-record.json

A pinned in-repo dataset goes through availability, production counts, the Six Big Losses, ISA-18.2 alarm load, control charts, the conservative baseline and the RCA copilot. Each result is canonically encoded and digested; the suite runs twice in this process and once in each of two fresh interpreters started at different PYTHONHASHSEED values — the arm that catches a set or dict iteration order reaching a result, which a single run never can. The socket API raises throughout, so a computation that reached for a device or a hostname fails here instead of quietly working on a machine that happened to be online. Afterwards the run is asked what it pulled in: a model library that was already loaded (an MCP server holds iaiops.core.llm for the opt-in narration tool) is recorded, not judged — only what the suite itself imported can condemn it.

The record separates result (identical every run — the part to sign) from context (when and where this run happened). Two good runs are not byte-identical records, and someone will diff them, so the halves are named rather than mixed.

This is the form the claim has to take to be usable: not "our model is accurate", which is not evidence in a GxP context, but a test case someone can write into an IQ/OQ protocol — remove the model, block the network, re-run the standard dataset, compare the hash — execute, and sign. verify_determinism is the same check from the MCP side; iaiops verify suite lists what it covers without running it.

How far it's actually been verified

Short version: verified against real protocol libraries, containers and in-process servers — not yet against real plant gear. We grade evidence rather than saying "tested", because a real container round-trip and a synthetic fixture are not the same claim.

Rung

What it means

Status

Real libraries / containers / in-process servers

OPC-UA (incl. cert Sign/SignAndEncrypt + A&C), Modbus-RTU over a socat PTY + pymodbus, BACnet/IP via bacpypes3 on a two-IP subnet, MTConnect against the Institute's own cppagent, IoTDB / TDengine live write→read, HART codec vs hart-protocol, PLCnext route via asyncua

Mock-verified (protocol logic exercised, no real device)

Omron FINS, IO-Link, BAS (Metasys / Niagara), Ignition Gateway, EtherNet/IP PCCC, Sparkplug B, S7 / MC / SECS-GEM

⚠️

Real gear

physical RS-485 devices, EtherCAT slaves, live HART gateways, live HVAC / BAS / Ignition, real PLCs

zero, for every protocol

Per-protocol evidence — including what each test does not cover — is in docs/VERIFICATION-RECORD.md, one row per protocol, naming the test behind each claim. Every 待核实 is hardware-gated, not forgotten — each one names the equipment that would settle it.

🧪 测试与共创 / Beta testing & co-creation

我们在找现场测试伙伴。 软件里能验证的我们都验证了(真实 in-process 服务器、真实协议库、Docker 容器 loopback)——剩下的 待核实 清单只有真设备能回答:物理 Modbus-RTU(RS-485)、EtherCAT 从站、HART 网关、在线 BACnet 楼宇设备、在线 Metasys/Niagara BAS 控制器、在线 Ignition 网关、国产 PLC(汇川/信捷)、真机 PLCnext、真实变电站 RTU/IED、欧姆龙 FINS 真机、IO-Link 主站。如果你是 OT 工程师、系统集成商或工厂团队,手上有任何这类设备:装上 iaiops,对你的设备跑一遍 iaiops doctor,把结果告诉我们。经你验证的设备会署名写进支持矩阵;现场反馈的问题我们优先分诊;功能可以通过 GitHub Issues/Discussions 直接共创。

We're looking for field-testing partners. Everything software-verifiable has been verified; what's left on the honest 待核实 list only real equipment can answer — physical Modbus-RTU (RS-485), EtherCAT slaves, HART gateways, live BACnet HVAC, live Metasys/Niagara BAS controllers, live Ignition gateway, domestic PLCs (Inovance/Xinje), live PLCnext, substation RTUs/IEDs, live Omron FINS PLCs, IO-Link masters. If you're an OT engineer, integrator, or factory team with access to any of these: install iaiops, run iaiops doctor against your gear, and tell us what happened. Verified-equipment reports get credited in the support matrix, field-reported issues get fast triage, and features are co-designed in the open via GitHub Issues/Discussions.

👉 参与入口 | Start here: open an issue with the protocol and device model in the title, or email zhouwei008@gmail.com. Either reaches a person, and a report gets answered against the current release.


Consolidated capability matrix

Protocol

Tool

Operation

R/W

risk_tier

Returns (key fields)

OPC-UA

opcua_server_info

server status

R

low

state, product_name, namespaces

OPC-UA

opcua_browse

browse node tree

R

low

[{node_id, browse_name, depth}]

OPC-UA

opcua_read_node

read one node

R

low

value, datatype, source_timestamp, good

OPC-UA

opcua_read_many

batch read

R

low

[{node_id, value, ...}]

OPC-UA

opcua_subscribe_sample

bounded sample

R

low

{collected, samples[]}

OPC-UA

opcua_read_alarms

alarm surfacing

R

low

{active_alarms[], active_count}

OPC-UA

opcua_read_history

Historical Access (HDA)

R

low

{supported, count, values[]}

OPC-UA

opcua_diagnose_connection

connection triage

R

low

{verdict, checks[]}

OPC-UA

opcua_discover_tags

tag auto-discovery → semantic asset model

R

low

{tag_count, assets[], naming_report}

OPC-UA

opcua_health_summary

threshold classify (was health_summary¹)

R

low

{overall, counts, offenders[]}

OPC-UA

opcua_anomaly_scan

stddev outliers (was anomaly_scan¹)

R

low

{mean, stddev, outliers[]}

Modbus

modbus_read_holding

FC03

R

low

{raw_registers, decoded[]}

Modbus

modbus_read_input

FC04

R

low

{raw_registers, decoded[]}

Modbus

modbus_read_coils

FC01

R

low

{bits[]}

Modbus

modbus_read_discrete

FC02

R

low

{bits[]}

Modbus

modbus_detect_byte_order

byte/word-order auto-detect

R

low

{best_order, candidates[]}

Modbus

modbus_list_templates

vendor register templates

R

low

{templates[]}

Modbus

modbus_apply_template

decode block via template

R

low

{values:{name: engineering_value}}

Modbus

modbus_health_summary

threshold classify

R

low

{overall, counts, offenders[]}

S7comm

s7_cpu_info

CPU id + run/stop

R

low

{cpu_status, cpu_info}

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, _undo_id}

Mitsubishi MC

mc_cpu_status

CPU type

R

low

{cpu_type, cpu_code}

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, _undo_id}

Omron FINS

fins_cpu_info

controller data read (0501)

R

low

{controller_model, controller_version}

Omron FINS

fins_cpu_status

controller status (0601)

R

low

{run_mode, status}

Omron FINS

fins_read_words

memory-area word read (DM/CIO/W/H/A/EM)

R

low

{words[]}

Omron FINS

fins_read_bits

memory-area bit read

R

low

{bits[]}

Omron FINS

fins_read_many

batch reads

R

low

{items[]}

Omron FINS

fins_write_words

memory-area write

W

high/MOC

{before, written, _undo_id}

MTConnect

mtconnect_probe

device model

R

low

{devices:[{components:[{data_items}]}]}

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[]}}], seq_gap_count}

MQTT/Sparkplug

sparkplug_decode_payload

decode raw SpB payload

R

low

{metrics:[{name, alias, datatype, value, is_historical}]}

MQTT/Sparkplug

sparkplug_node_list

node discovery + state

R

low

{nodes:[{group_id, edge_node_id, online, devices}], primary_hosts[]}

MQTT/Sparkplug

uns_browse

topic-tree browse

R

low

{topics[], tree{}}

MQTT/Sparkplug

uns_topic_audit

UNS naming + sprawl governance

R

low

{verdict, sprawl_findings, findings{casing_collisions[], scattered_leaves[], …}}

MQTT/Sparkplug

uns_schema_drift

Sparkplug schema-drift (baseline vs current)

R

low

{verdict (none/additive/breaking), node_changes[]}

MQTT/Sparkplug

uns_live_audit

live UNS audit (bounded broker sample)

R

low

{verdict, findings{}}

MQTT/Sparkplug

sparkplug_live_schema

live NBIRTH schema snapshot

R

low

{nodes[], metrics[]}

MQTT/Sparkplug

uns_live_drift

live drift vs stored baseline

R

low

{verdict, node_changes[]}

MQTT/Sparkplug

mqtt_publish

publish/command

W

high/MOC

{published_bytes, applied}

EtherNet/IP

eip_controller_info

Logix controller id

R

low

{controller:{vendor, product_name, revision, serial}}

EtherNet/IP

eip_list_tags

tag discovery

R

low

{tag_count, tags:[{name, data_type, 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, _undo_id}

Diagnostics

diagnose_dataflow

localize no-data

R

low

{verdict, diagnosis, hops[]}

Diagnostics

alarm_bad_actors

ISA-18.2 flood

R

low

{flood_verdict, top_offenders[]}

Diagnostics

tag_health

offender ranking

R

low

{overall, offenders[]}

Diagnostics

historian_health

gap/flatline

R

low

{verdict, gaps[]}

Diagnostics

subscription_health

sequenced-feed loss/reorder/overload

R

low

{verdict, missed_count, overloaded_channels[]}

Diagnostics

downtime_root_cause

AI downtime RCA copilot (cited, advisory)

R

low

{verdict, primary_cause, hypotheses:[{cause, confidence, evidence[]}]}

Diagnostics

downtime_root_cause_live

RCA copilot that gathers its own live evidence

R

low

{…downtime_root_cause…, collected_evidence}

Diagnostics

learn_cause_weights

learn per-site RCA cause weights from labeled incidents

R

low

{cause_weights{}, rationale}

Diagnostics

data_quality_scorecard

fleet data-trust rollup

R

low

{fleet_score, fleet_status, issue_breakdown, worst_tags[], endpoints[]}

Diagnostics

data_quality_fleet_rollup

cross-endpoint fleet view

R

low

{fleet_score, endpoints[]}

Diagnostics

heartbeat_health

heartbeat/watchdog liveness

R

low

{alive, distinct_transitions, longest_stall_s, reason}

Alarm (ISA-18.2)

alarm_flood_analysis

flood episodes / chattering / stale / summary

R

low

{episodes[], chattering[], stale[], summary{}}

Alarm (ISA-18.2)

alarm_rationalization_worksheet

CSV-exportable rationalization rows

R

low

{rows[], csv_path?}

Baseline

baseline_learn

conservative change-log baseline (refuses thin history)

R

low

{band{p1,p99,median,mad} | insufficient_data}

Baseline

baseline_check

silent-by-default violation check

R

low

{status, violations[] (cited)}

Baseline

baseline_record_change

record operator change (restarts learning)

R

low

{recorded, change_point}

Baseline

baseline_status

no_baseline / learning / ok / violation

R

low

{status, window}

Historian

historian_query

read history back out of sqlite/TDengine/IoTDB

R

low

{rows[], truncated}

Historian

historian_coverage

per-tag row counts + first/last ts

R

low

{tags:[{tag, rows, first, last}]}

PLC program

plc_program_outline

structure of exported ST/AWL/L5X program

R

low

{blocks[], call_graph, timers[]}

PLC program

plc_program_xref

symbol/address cross-reference (cited lines)

R

low

{sites:[{kind, source_file, line, quote}]}

PLC program

plc_program_section

one named block's source (≤200 lines)

R

low

{text, source_file}

Export

export_data

export local store → CSV/SQLite/Parquet

R

low

{path, row_count, preview[]}

Analytics

oee_compute

OEE = A×P×Q

R

low

{availability, performance, quality, oee, oee_pct}

Analytics

downtime_events

stoppage detect + categorize

R

low

{event_count, total_downtime_s, by_category, events[]}

Analytics

oee_multidim

OEE machine×part×shift

R

low

{matrix[], worst_performers[], mean_oee}

Analytics

asset_inventory

active fingerprint

R

low

{assets:[{protocol, vendor, model, firmware, reachable}]}

Analytics

cross_protocol_asset_model

merge discovered tags into one asset model

R

low

{assets[], tag_count}

Analytics

adopt_alias_map / diff_alias_map

tag alias-map adopt/diff

R

low

{aliases{}, changes[]}

Analytics

monitor_changes

bounded change-of-value

R

low

{change_count, changes:[{value, previous, wall_clock}]}

EtherCAT

ethercat_master_state

master/WKC + slave count

R

low

{master_state, expected_working_counter, slaves_found, slaves_expected}

EtherCAT

ethercat_slaves

bus scan

R

low

{slave_count, slaves:[{index, name, vendor_id, product_code, state}]}

EtherCAT

ethercat_slave_info

slave detail

R

low

{sync_managers[], fmmus[], object_dictionary[], input_bytes}

EtherCAT

ethercat_read_sdo

CoE SDO upload

R

low

{index, byte_length, hex, as_uint}

EtherCAT

ethercat_read_pdo

input PDO snapshot

R

low

{working_counter, input_hex, input_byte_length}

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}

PROFINET

profinet_discover

DCP IdentifyAll (segment-wide)

R

low

{station_count, stations:[{name_of_station, mac, ip, vendor_id, device_roles[]}]}

PROFINET

profinet_identify_station

identify by name-of-station

R

low

{found, name_of_station, mac, ip, device_family}

PROFINET

profinet_station_params

targeted DCP Get (by MAC)

R

low

{found, name_of_station, ip, netmask, gateway}

PROFINET

profinet_asset_inventory

DCP asset register

R

low

{asset_count, io_controller_count, assets[]}

PROFINET

profinet_dcp_set

DCP Set (station name / IP suite)

W

high/MOC

{before, applied, _undo_id}

SECS/GEM

secsgem_equipment_status

GEM link + identity (S1F1/F2)

R

low

{communication_state, are_you_there}

SECS/GEM

secsgem_list_status_variables

SVID namelist (S1F11/F12)

R

low

{count, status_variables[]}

SECS/GEM

secsgem_read_status_variables

SVID values (S1F3/F4)

R

low

{svids, values[]}

SECS/GEM

secsgem_list_equipment_constants

ECID namelist (S2F29/F30)

R

low

{count, equipment_constants[]}

SECS/GEM

secsgem_read_equipment_constants

ECID values (S2F13/F14)

R

low

{ecids, values[]}

SECS/GEM

secsgem_list_alarms

alarm list (S5F5/F6)

R

low

{count, alarms[]}

SECS/GEM

secsgem_list_process_programs

PPID directory (S7F19/F20)

R

low

{count, process_programs[]}

BACnet (building)

bacnet_discover

Who-Is device discovery

R

low

{device_count, devices:[{device_id, address}]}

BACnet (building)

bacnet_object_list

a device's objects

R

low

{object_count, objects:[{object_type, instance}]}

BACnet (building)

bacnet_read_property

one object property

R

low

{object_type, instance, property, value}

BACnet (building)

bacnet_read_points

all present-values (HVAC snapshot)

R

low

{point_count, points:[{object_type, instance, present_value}]}

BACnet (building)

bacnet_cov_subscribe

bounded COV capture (always unsubscribes)

R

low

{notifications[], terminated_reason}

BACnet (building)

bacnet_read_trend_log

TrendLog readRange (bounded)

R

low

{records:[{timestamp, value}]}

BACnet (building)

bacnet_write_property

present-value write (priority)

W

high/MOC

{before, written, _undo_id}

HART-IP (process)

hart_device_identity

cmd 0 identity

R

low

{manufacturer, device_type, revision}

HART-IP (process)

hart_primary_variable

cmd 1 PV

R

low

{value, unit}

HART-IP (process)

hart_dynamic_variables

cmd 3 PV/SV/TV/QV + loop current

R

low

{variables[], loop_current}

HART-IP (process)

hart_burst_sample

bounded burst-variable sampling

R

low

{samples[]}

IO-Link

iolink_master_info

master identity

R

low

{vendor, product, serial}

IO-Link

iolink_ports

≤32-port sweep (mode/status/device id)

R

low

{ports[]}

IO-Link

iolink_device_info

per-port device identity

R

low

{vendor_id, device_id, product_name}

IO-Link

iolink_read_pdin

process-data-in (raw hex + bytes)

R

low

{hex, bytes[]}

IO-Link

iolink_read_isdu

ISDU acyclic parameter read

R

low

{index, subindex, value}

IO-Link

iolink_scan

master + all connected devices

R

low

{master{}, devices[]}

BAS (Metasys/Niagara)

bas_point_list

supervisory point directory

R

low

{point_count, points:[{id, name, type}]}

BAS (Metasys/Niagara)

bas_point_read

read one supervisory point

R

low

{point, value, unit, status}

BAS (Metasys/Niagara)

bas_alarm_list

active controller alarms

R

low

{alarm_count, alarms:[{id, priority, state}]}

BAS (Metasys/Niagara)

bas_trend_read

trend/history samples (bounded)

R

low

{records:[{timestamp, value}]}

BAS (Metasys/Niagara)

bas_command

supervisory command (default-OFF; life-safety object denylist refuses fire/smoke/egress/pressurization before any I/O)

W

high/MOC

{before, written, _undo_id}

Ignition

ignition_gateway_status

Gateway + module health

R

low

{state, version, modules:[{name, state}]}

Ignition

ignition_tag_browse

tag-tree browse

R

low

{tags[], tree{}}

Ignition

ignition_tag_read

current tag values

R

low

{values:[{path, value, quality, timestamp}]}

Ignition

ignition_alarm_status

active alarms

R

low

{alarm_count, alarms:[{path, priority, state}]}

Ignition

ignition_tag_history

tag-history query (bounded)

R

low

{rows:[{path, timestamp, value}]}

信创 / compliance

compliance_mapping

《工控网络安全防护指南》↔ iaiops

R

low

{pillars[], status_summary, controls:[{pillar, status, gap}]}

信创 / compliance

compliance_frameworks

等保 2.0 + IEC 62443 FR1–6 crosswalk

R

low

{controls:[{crosswalk}]}

信创 / compliance

compliance_dengbao_levels

等保 二级 baseline vs 三级 增量

R

low

{pillars:[{l2, l3_delta, status}]}

信创 / compliance

compliance_report

deliverable compliance report (md/html)

R

low

{markdown | out_path}

信创 / compliance

compliance_evidence_bundle

audit-evidence zip (hash-chain verified)

R

low

{bundle_path, manifest}

信创 / historian

historian_push

push telemetry to sqlite/TDengine/IoTDB

R(→historian)

low

{sink, received, written, skipped_non_numeric}

Self

protocols_supported

capability map

R

low

{protocols[], diagnostics[], analytics[]}

(The energy protocols — IEC-104 / DNP3 / IEC-61850 — moved to iaiops-energy in 0.8.0; their tool matrix lives in that repo.)

196 governed tools = 183 read + 10 MOC-gated device writes + historian_push (a write, to a historian rather than to a device: [WRITE][risk=low]) + the 2 deprecated aliases below. The device writes are (s7_write_db, mc_write_words, fins_write_words, mqtt_publish, eip_write_tag, ethercat_write_sdo, ethercat_set_state, profinet_dcp_set, bacnet_write_property, bas_command). The read side now includes two vendor-REST read-only layers above the field protocols — a BAS controller layer (Metasys/Niagara, building edition) and an Ignition Gateway MES/SCADA layer (factory edition). ¹ The 2 deprecated aliases are the two deprecated brain aliases health_summary / anomaly_scan, renamed to opcua_health_summary / opcua_anomaly_scan in 0.10.0 — the deprecated aliases are still registered and will be removed in a future release (target: 1.0.0). Read-only per-edition tools load ONLY under their edition (see per-edition tool modules below), so a bare protocol / single-edition surface is smaller than this line-wide total. The table above is representative, not exhaustive; run protocols_supported() (or iaiops protocols) for the live map.


Per-protocol reference

OPC-UA

  • Versions/variants: binary opc.tcp:// via asyncua (sync facade). Security: anonymous + username/password, plus application-certificate message security (Sign / SignAndEncrypt) — set client_cert + client_key (+ optional server_cert) and the client opens a signed/encrypted secure channel (no cert ⇒ the anonymous / username path is unchanged). Validated end-to-end against an in-process asyncua server (tests/test_opcua_security.py) for Basic256Sha256 in both Sign and SignAndEncrypt modes: server_cert pinning and client-side server-cert auto-discovery are exercised, and the test asserts the negotiated policy URI + message-security mode on the live encrypted channel (plus a negative test that anonymous is refused by a secure-only server).

  • Connection params: endpoint_url, username (password encrypted), security_mode, security_policy; for cert security client_cert / client_key / optional server_cert (PEM or DER paths; aliases certfile / keyfile).

  • Alarms & Conditions: opcua_alarm_events — bounded event subscription + ConditionRefresh, events carry the server's own timestamps (verified against an in-process asyncua server; third-party A&C servers 待核实). Untimed fallback: opcua_read_alarms browses alarm-like boolean nodes.

  • Not supported / planned (待核实): cert-security interop with third-party / vendor servers (KEPServerEX / Prosys / Siemens / real PLCs), the other policies (Aes128Sha256RsaOaep / Aes256Sha256RsaPss / Basic128Rsa15 / Basic256), strict server-side certificate-trust enforcement, and cert-based user identity (X509 identity token, distinct from channel security).

Modbus-TCP / Modbus-RTU

  • Versions/variants: Modbus-TCP and Modbus-RTU (serial RS-485/232) via pymodbus (+ pyserial). Read function codes FC01 (coils), FC02 (discrete), FC03 (holding), FC04 (input). Write FCs (FC05/06/15/16) = not implemented (read-only).

  • Connection params: TCP — host, port (502), unit_id. RTU — transport: rtu, serial_port (e.g. /dev/ttyUSB0), baudrate, unit_id. Registers are untyped 16-bit words → decode hint (uint16/int16/uint32/int32/float32/raw); modbus_detect_byte_order auto-detects the byte/word order (AB/BA · ABCD/DCBA/BADC/CDAB) from hint values — pure logic, no extra device load.

  • Vendor register templates (modbus_list_templates / modbus_apply_template): named register maps decoding a block into engineering values — energy meters (Eastron SDM630, Schneider PM5xxx, Carlo Gavazzi EM24), PV inverters (Huawei SUN2000, Growatt), Phoenix PLCnext process data, and water-industry templates (E+H Promag, Hach SC controller, generic dosing pump). Each template carries an explicit 待核实 caveat — no invented "verified" addresses.

  • Coverage: many domestic 国产 PLCs (汇川 Inovance / 信捷 Xinje / 和利时 Hollysys / 台达 Delta) and any Modbus vendor. RTU framing is live-verified over a real serial link (socat PTY + pymodbus RTU server); specific physical RS-485 devices stay 待核实.

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.

Omron FINS (CS/CJ/CP/NX-via-FINS)

  • Versions/variants: in-repo, stdlib-only FINS client (no third-party dependency — the iaiops[fins] extra pins nothing): 10-byte FINS header framing, FINS/UDP (default port 9600) and FINS/TCP (node-address handshake per Omron W342), SID matching, bounded response parsing, end-code table per W227/W342. Commands: 0101 memory-area read (words/bits over DM/CIO/W/H/A/EM), 0102 write, 0501 controller data read, 0601 controller status.

  • Connection params: host, port (9600), transport (udp default / tcp), FINS network/node/unit addressing.

  • Write: fins_write_words = high/MOC/dry-run default, captures BEFORE + undo; CLI double-confirm on --apply.

  • Validation: verified against an in-repo mock FINS UDP/TCP responder (tests/test_fins.py); live Omron PLC behaviour and banked-EM access stay 待核实.

  • Versions/variants: sensor-level visibility via the IO-Link master's HTTP/JSON interface (IO-Link consortium "JSON Integration"), both dialects selectable per endpoint via flavor:iotcore (ifm IoT-Core POST envelope, default) and rest (plain-REST GET, Balluff/Turck-style). Reads: master identity, bounded ≤32-port sweep, per-port device identity, process-data-in (raw hex + bytes), ISDU acyclic parameter read. NO write tools. Bounded/size-capped HTTP (256 KiB response cap), schema-checked JSON with teaching errors. Reuses the MTConnect HTTP pin (iaiops[iolink]requests).

  • Connection params: master host/URL, flavor, timeout_s. protocol: iolink.

  • Validation: in-process mock master in both flavors (tests/test_iolink.py); live master datapoint paths stay 待核实.

HART-IP (process instrumentation — read-only)

  • Versions/variants: HART universal commands over HART-IP UDP (default, port 5094) or TCP (transport: tcp, length-delimited framing) via an in-tree transport; the HART command codec is verified vs hart-protocol. Tools: hart_device_identity (cmd 0), hart_primary_variable (cmd 1), hart_dynamic_variables (cmd 3, PV/SV/TV/QV + loop current), hart_burst_sample (bounded sampling of burst-published variables). No write / device-specific commands exposed (OT-dangerous on live instruments).

  • Connection params: host (HART-IP server/gateway), port (5094), transport (udp default / tcp).

  • Validation: TCP transport loopback-verified (in-process HART-IP server, real long-frame ACK through the real codec path); live gateway behaviour and a true unsolicited burst subscription stay 待核实.

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/<host_id> 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 transient publish has no automatic inverse (delivered is delivered); a retained one overwrites durable broker state, so it captures the prior retained payload and records an 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 iaiops[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. 未经授权勿对生产控制系统写入.

PROFINET (DCP discovery / identify + gated DCP Set)

  • Supported: layer-2 PROFINET-DCP via pnio-dcpprofinet_discover (DCP IdentifyAll: one broadcast surfaces every station on the segment — name-of-station, MAC, IP, vendor/device id, role — closer to passive discovery than a per-device fingerprint), profinet_identify_station (by name-of-station), profinet_station_params (targeted DCP Get by MAC → name + IP suite), and profinet_asset_inventory (a register with IO-controller vs IO-device role decoding).

  • Write: profinet_dcp_set re-addresses one station (name-of-station and/or IP suite, by MAC) — high risk_tier, MOC, dry-run default, captures the BEFORE addressing + undo descriptor. Re-addressing a live station can disrupt its IO connection.

  • Scope (deliberate): no RT cyclic process data (that needs an IO-controller/IO-device stack and hard real-time — out of scope and unsafe to tap); the blink / factory-reset DCP services stay unexposed.

  • HARD REQUIREMENTS: raw-socket access (root / admin / CAP_NET_RAW) on the NIC on the PROFINET subnet. pnio-dcp is an OPTIONAL extra: pip install iaiops[profinet] — the base package installs/imports without it, and every tool then degrades to a teaching error.

  • Connection params: hostTHIS machine's IP on the PROFINET subnet (the DCP broadcast goes out on it). protocol: profinet.

  • Preview caveat: validated against a mocked pnio-dcp DCPnot verified against live PROFINET devices yet.

Energy edition (electrical substation / utility telecontrol) → iaiops-energy

The energy vertical — IEC 60870-5-104 / DNP3 / IEC 61850 MMS read-only monitoring for substation RTUs/IEDs — moved to its own package in 0.8.0: iaiops-energy (pip install iaiops-energy), built on iaiops.core (shared governance / brain / runtime). Its protocol reference, support matrix, and validation status live in that repo.

Building edition (facility / HVAC / 厂务)

The building vertical adds BACnet/IP (ASHRAE 135) — the dominant building-automation protocol for HVAC, lighting, metering, and facility plant. Install with pip install iaiops[building] and expose with IAIOPS_MCP=building (bundle: bacnet + modbus + opcua + iolink).

  • BACnet/IP (BAC0 over bacpypes3): bacnet_discover (Who-Is device discovery), bacnet_object_list (a device's objects), bacnet_read_property (one object property), bacnet_read_points (present-value of all analog/binary/multistate points — the HVAC snapshot), bacnet_cov_subscribe (bounded change-of-value capture — capped by count AND wall-clock, always unsubscribes), bacnet_read_trend_log (TrendLog buffered records via one bounded readRange). Config: host = THIS machine's BACnet/IP interface (ip or ip/mask) / port (47808).

  • Write: bacnet_write_property (present-value at a BACnet priority 1..16, or relinquish) = high risk_tier, MOC, dry-run default, BEFORE-value read-back + undo. Overriding a live building-control point can move real HVAC/plant.

  • Validation: the read path is verified against a real bacpypes3 virtual BACnet/IP device through the actual async BAC0 stack (tests/test_bacnet_live.py); COV / trend-log / writes on live HVAC gear stay 待核实.

Water treatment edition (水处理)

IAIOPS_MCP=water (or iaiops-mcp-water, pip install iaiops[water]) exposes modbus + opcua + hart + the brain — the protocol set waterworks / wastewater plants actually run. Adds water-domain tag semantics (溶解氧 DO / ORP / 余氯 chlorine / 氨氮 ammonia / TSS/MLSS / 跨膜压差 TMP / UV / 加药 dosing / 曝气 aeration) and water-industry Modbus templates (E+H Promag, Hach SC controller, generic dosing pump — all with explicit 待核实 caveats).

Warehouse / intralogistics edition (仓储 / 物料搬运)

IAIOPS_MCP=warehouse (or iaiops-mcp-warehouse, pip install iaiops[warehouse]) exposes eip + profinet + modbus + opcua + sparkplug + the brain — conveyor & sorter drives over EtherNet/IP (Rockwell) and Profinet (Siemens), VFD / energy meters over Modbus (conveyor_vfd / agv_battery templates), WMS/WCS gateways over OPC-UA, and AMR/IoT telemetry over MQTT-Sparkplug. Edition tools (read-only, advisory): line_bottleneck (Theory-of-Constraints throughput bottleneck across stations) + sortation_health. PdM (pdm_forecast), downtime_triage and OEE are reused as-is.

Clinical-facility edition (医疗设施)

IAIOPS_MCP=clinical (or iaiops-mcp-clinical, pip install iaiops[clinical]) exposes bacnet + modbus + opcua + the brain — hospital facilities as a distinct patient-safety vertical over the building brain. Edition tools (read-only, advisory): isolation_room_check (负压/正压 isolation-room pressurization), medical_gas_check (medical-gas alarm-panel safety), or_environment_check (OR temperature / humidity / pressure envelope). BACnet BMS + Modbus gas-alarm panels + OPC-UA plant SCADA.

Pharmaceutical-manufacturing edition (制药)

IAIOPS_MCP=pharma (or iaiops-mcp-pharma, pip install iaiops[pharma]) exposes bacnet + modbus + hart + opcua + the brain. No new protocol — that is the point: no field protocol is specific to pharma. Cleanrooms run BACnet, purified-water systems run Modbus and HART, filling and lyophilization run S7, DCS and bioreactors run OPC-UA, and all of it was already here. What pharma needed was semantics: the water edition's indicators are municipal (DO, ORP, chlorine, turbidity) and the clinical edition grades one room's pressure, where Annex 1 inspects the cascade.

Edition tools (read-only, advisory): cleanroom_pressure_cascade (EU GMP Annex 1, door by door — adjacency is declared, never inferred from a room list), cleanroom_particle_check, pharma_water_check (USP <645> stage-1 procedure: the non-temperature-compensated reading, the measured temperature rounded down to the tabulated step, and exceeding stage 1 reported as proceed to Stage 2 rather than as a failure).

No compendial limit tables are shipped. The particle limits, the stage-1 conductivity table and the TOC limit belong to the site's qualified specification at its compendial revision. A transcription nobody in this repository can verify would end up deciding whether a batch environment passed — and the error that hurts is the flattering one, since a limit set too loose reads as "in specification". Limits are passed in and cited back; anything not declared is reported no_limit / not_graded and named, never counted as passing. Known gaps are listed in the edition's skill: no PI historian connector, S7 without hardware verification, no GxP (Annex 11 / Part 11) crosswalk yet, and LIMS / QMS deliberately out of scope — they run REST and databases, not field protocols.

Renewables edition (光伏 / 风电)

IAIOPS_MCP=renewables (or iaiops-mcp-renewables, pip install iaiops[renewables]) exposes modbus + opcua + sparkplug + the brain — PV inverters (SUN2000 / Growatt templates) + wind-turbine controllers over Modbus, OPC-UA plant SCADA, and MQTT-Sparkplug telemetry. Edition tool (read-only, advisory): pv_performance (PV string performance vs expectation). Device-level monitoring + PdM via baseline / RCA.

PLCnext packaging edition (Phoenix Contact vPLC)

IAIOPS_MCP=plcnext (or iaiops-mcp-plcnext, pip install iaiops[plcnext]) exposes opcua + modbus + the brain — the Phoenix Contact PLCnext virtualized PLC reached over its built-in OPC-UA server (opc.tcp 4840, Arp.Plc.Eclr address space) + Modbus-TCP process-data server; no new connector. Route-verified in-process; live PLCnext hardware reads stay 待核实 (see How far it's actually been verified).

信创 / China entry (offline · 国产 TSDB · compliance)

For 自主可控 / 信创 deployments — see docs/CHINA.md for the full guide.

  • Air-gapped install: pure-Python core + per-protocol optional extras → install from a local wheelhouse with pip install --no-index --find-links ./wheelhouse "iaiops[...]"; secrets stay local (encrypted store), no cloud KMS.

  • National TSDB historian sink (historian_push, CLI iaiops historian push): write collected telemetry to TDengine (iaiops[tdengine]) or Apache IoTDB (iaiops[iotdb]) — domestic, controllable; we don't build our own store or bind InfluxDB. Data egress to the operator's own historian, not a control write.

  • Compliance mapping (compliance_mapping, CLI iaiops compliance): an honest 《工控系统网络安全防护指南》 ↔ iaiops self-assessment across 分区隔离 / 可审计 / 双向认证 / 最小权限 / 数据保护 / 自主可控, with per-control status (addressed / partial / 待核实) and the named gap.

  • 国产 PLC: 汇川 / 台达 / 信捷 over the existing Modbus-TCP / S7 connectors.

  • ⚠️ 待核实: 国产 OS (麒麟/统信) · 芯 (鲲鹏/海光) · PLC validation and the TSDB write paths are documented but not yet hardware-verified — see the validation matrix in docs/CHINA.md.

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). mtconnect_oee_snapshot surfaces the live MTConnect availability/execution inputs that feed these.

Active asset inventory / fingerprint (read-only)

  • asset_inventory — for each configured (or named) endpoint, actively connects with our own protocol client and reads its identity call (S7 s7_cpu_info, EtherNet/IP eip_controller_info, OPC-UA server build info, Modbus Device Identification FC43/0x2B, Mitsubishi CPU type, MTConnect device model), aggregating vendor / model / firmware / serial / reachable / last_seen into an asset register.

  • Honest scope (IEC 62443-flavored): this is ACTIVE fingerprinting via our client connections, NOT passive SPAN/tap discovery — it only finds devices we are configured to reach and adds light load to each. Passive, traffic-mirroring discovery is roadmap.

OPC-UA Historical Access (HDA)

  • opcua_read_history — reads stored historical values for a node over a [start,end] ISO-8601 window via the server's HistoryRead service (asyncua read_raw_history), bounded by max_points (≤2000). Returns {supported:false, note} gracefully when the server does not historize the node (no crash). Read-only.

Change-of-value (CoV) monitor

  • monitor_changes — bounded deadband report: polls a point and returns only the value CHANGES (with timestamps), not every sample. Works over OPC-UA / Modbus / S7 / Mitsubishi MC / EtherNet-IP. Never an infinite loop — hard-capped by both duration_s (≤120) and max_changes (≤500). Read-only.

Cross-protocol brain — 0.9/0.10 additions (all read-only)

  • Conservative baseline learning (baseline_learn/check/record_change/status, CLI iaiops baseline …) — a change-log baseline, explicitly NOT black-box anomaly detection: robust p1/p99 + median/MAD band over the local history, refuses thin history (<100 samples or <24h) with an explicit insufficient_data verdict, restarts at recorded operator changes, and is **silent by default** — a violation needs >3×MAD beyond the band AND ≥3 consecutive samples, and every violation cites its baseline window and offending samples.

  • Historian READ integration (historian_query / historian_coverage, CLI iaiops historian query|coverage) — query history back out of the sqlite/TDengine/IoTDB sinks; an optional per-site historian: config block lets the RCA copilot pull the 2h pre-incident window as one more cited evidence class (strictly additive — without the config, RCA output is byte-identical, test-proven).

  • Legacy PLC program explainer (plc_program_outline/xref/section, CLI iaiops program …) — structural extraction over exported program files (Siemens SCL/ST .scl/.st, AWL/STL .awl, Rockwell Studio 5000 .L5X — never a live PLC upload); every element carries source_file + line (rung for L5X) so the explaining agent must cite real locations. XXE-hardened, ≤5 MB, extension allowlist.

  • ISA-18.2 alarm flood deep-dive (alarm_flood_analysis / alarm_rationalization_worksheet, CLI iaiops diag alarm-flood|alarm-worksheet) — flood episodes (≥10 alarms/10 min), chattering, stale/standing (>24h), percent-time-in-flood vs target, and a CSV-exportable rationalization worksheet; over injected events or a live OPC-UA active-condition scan.

  • Open-format export + metrics bridgeiaiops export csv|sqlite|parquet (from the local SQLite sink; Parquet via iaiops[export]) / MCP export_data; iaiops metrics serve --port 9184 exposes Prometheus /metrics (latest tag values + counters, binds 127.0.0.1 by default) — Grafana recipe in docs/GRAFANA.md.

  • Compliance deliverablesiaiops compliance report (等保 2.0 L2/L3 status + IEC 62443 FR1–6 crosswalk + honest gap list, md/html) and iaiops compliance evidence (audit-evidence zip with hash-chain verification + manifest); MCP compliance_report / compliance_evidence_bundle. Onboarding aids, 非认证.

Cross-protocol brain & editions — 0.11/0.12 additions (all read-only)

  • Downtime triage copilot (downtime_triage) — composes alarm cascade + RCA verdict + PdM precursors into one triage and cross-checks whether the first-out alarm agrees with the diagnosed cause; advisory, cite-first (builds on the earlier alarm_cascade first-out reconstruction and pdm_forecast time-to-threshold early-warning).

  • Legacy-PLC maintainability (plc_program_visibility) — a risk/maintainability read over an exported ST/AWL/L5X program (size, block count, xref density, undocumented sections), never a live upload — pairs with the plc_program_outline/xref/section explainer.

  • Per-edition tool modules (EDITION_MODULES in mcp_server/profiles.py) — a named edition can carry its own @mcp.tool group that loads only when that edition is selected — never for a bare protocol key and never in the always-on brain, so edition-specific tools stay off other surfaces and don't inflate the base. Every edition tool is read-only, cite-first, advisory:

    • warehouseline_bottleneck (Theory-of-Constraints throughput bottleneck) + sortation_health

    • clinicalisolation_room_check (负压隔离病房 pressurization) + medical_gas_check + or_environment_check

    • buildingeconomizer_check (AHU economizer FDD) + zone_comfort

    • processcontrol_loop_health (PID oscillation/offset/saturation) + heat_exchanger_fouling

    • fabspc_check (SPC control-chart rules) + defect_pareto

    • factorychangeover_analysis (SMED)

    • waterdisinfection_ct + water_quality_compliance

    • renewablespv_performance (PV string performance)

  • Agent skills — the repo ships a router skill (skills/iaiops) plus ten per-edition skills (iaiops-fab / iaiops-factory / iaiops-process / iaiops-building / iaiops-water / iaiops-warehouse / iaiops-clinical / iaiops-pharma / iaiops-renewables / iaiops-plcnext) that route an agent to the right MCP server and document the tool surface.

Deployment & ecosystem fit (edge-native / Margo)

iaiops is designed to ride on a hardened, centrally-managed edge host as a portable, governed edge application — not to own the host or the fleet manager. It maps naturally onto the Margo edge-interoperability roles: the host/device is the immutable edge OS, a compliant orchestrator places workloads by desired-state, and iaiops is the OT-domain application — read-first tap + cross-protocol RCA, exposed as governed MCP tools, with an optional on-box LLM brain for a fully air-gapped diagnostic path (data never leaves the plant).

Honest status: iaiops is a natural Margo edge application but is NOT Margo-compliant yet — a container image + application description + a published conformance-toolkit result are roadmap (see docs/MARGO-ALIGNMENT.md and docs/ROADMAP.md). No material claims Margo-compliant until that test result exists.

A container + application-description skeleton lives in deploy/margo/ (hardened Dockerfile · compose · 待核实-marked app descriptor); per-host distribution overlays that reuse it live under deploy/ (one folder per candidate edge host).


Install

Protocol client libraries are optional extras — install only the 1–2 protocols a site actually runs (every protocol library is imported lazily; the base package installs and imports without any of them, and a call to a not-installed protocol returns a teaching error pointing at the right extra):

uv tool install "iaiops[opcua,modbus]"   # just the protocols you need
# or one per site:  pip install "iaiops[s7]"   ·   everything:  pip install "iaiops[all]"
# or a per-industry edition bundle:        pip install "iaiops[fab]"

iaiops init                 # interactive: add endpoints, store passwords encrypted
iaiops doctor               # config + per-protocol connectivity probe (point at simulators)
iaiops protocols            # the capability map

Protocol extras: opcua · modbus · s7 · mc · fins (stdlib — pins nothing) · eip · mtconnect · sparkplug · secsgem · ethercat · profinet · bacnet · hart · iolink · bas (BAS supervisory REST — reuses the mtconnect HTTP pin) · ignition (Ignition Gateway read layer — reuses the mtconnect HTTP pin) · plus tdengine · iotdb · influxdb (historian sinks) · nats (stream egress) · ollama (on-box LLM narration) · export (Parquet) · all (every pip-installable connector).

Adapter belt (docs/ADAPTERS.md): iaiops is a small neutral core (ingress → normalize/govern/RCA → egress) with pluggable, lazily-imported adapters — bind no store/bus/host/model, install only what a site runs. The RCA core is deterministic + cited, not a black box (docs/RCA.md); footprint is small by design (docs/FOOTPRINT.md).

Edition bundles (match the same-named IAIOPS_MCP profiles — install the protocols a vertical runs): fab (secsgem + opcua + s7 + modbus) · factory (the discrete-manufacturing set: opcua + modbus + s7 + mc + fins + eip + mtconnect + sparkplug + ethercat + profinet + iolink + ignition) · process (opcua + modbus + hart) · building (bacnet + modbus + opcua + iolink + bas) · water (modbus + opcua + hart) · warehouse (仓储/物料搬运: eip + profinet + modbus + opcua + sparkplug) · clinical (医疗设施: bacnet + modbus + opcua) · renewables (光伏/风电: modbus + opcua + sparkplug — PV inverters (SUN2000/Growatt) + wind turbines + plant SCADA; device-level monitoring + PdM via baseline/RCA) · plcnext (opcua + modbus). The grid/substation energy bundle (IEC-104/DNP3/61850) ships in iaiops-energy.

Master password

Secrets (per-endpoint passwords, MQTT credentials) are never stored in plaintext — they live in ~/.iaiops/secrets.enc (Fernet + scrypt). Export IAIOPS_MASTER_PASSWORD so the MCP server/CLI can unlock non-interactively:

export IAIOPS_MASTER_PASSWORD='…'

Example ~/.iaiops/config.yaml (one block per protocol)

endpoints:
  - name: line1
    protocol: opcua
    endpoint_url: opc.tcp://plc.lan:4840
    # username: operator           # password stored encrypted via init/secret set
    tags:
      - { ref: "ns=2;i=5", label: temp, warn_high: 70, alarm_high: 90 }
  - name: plc2
    protocol: modbus
    host: 10.0.0.5
    port: 502
    unit_id: 1
  - name: press1
    protocol: s7
    host: 10.0.0.6
    rack: 0
    slot: 1                        # S7-1200/1500
  - name: cell3
    protocol: mc
    host: 10.0.0.7
    port: 5007
    plctype: iQ-R
  - name: meter1
    protocol: modbus                 # Modbus-RTU (serial): set transport + serial_port
    transport: rtu
    serial_port: /dev/ttyUSB0
    baudrate: 9600
    unit_id: 1
  - name: omron1
    protocol: fins                   # Omron FINS (UDP default; transport: tcp for FINS/TCP)
    host: 10.0.0.11
    port: 9600
  - name: xmtr1
    protocol: hart                   # HART-IP gateway (read-only; udp default / transport: tcp)
    host: 10.0.0.20
  - name: iolm1
    protocol: iolink                 # IO-Link master JSON integration (read-only)
    host: 10.0.0.21
    flavor: iotcore                  # ifm IoT-Core (default) | rest (Balluff/Turck-style)
  - name: vmc1
    protocol: mtconnect
    agent_url: http://10.0.0.8:5000
  - name: uns
    protocol: mqtt
    host: broker.lan
    use_tls: true                  # → port 8883
    topic: spBv1.0/#
    # username: edge1              # password stored encrypted
  - name: cell5
    protocol: ethernetip           # alias: eip
    host: 10.0.0.9
    slot: 0                        # 0 for CompactLogix; CPU slot for ControlLogix
  - name: bus1
    protocol: ethercat             # Linux + root/CAP_NET_RAW + pip install iaiops[ethercat]
    nic: eth1                      # dedicated NIC cabled to the EtherCAT bus
    expected_slaves: 8             # optional sanity check vs the bus scan

iaiops init walkthrough (per protocol)

$ iaiops init
Step 1 — master password: ********
Step 2 — add an endpoint
  Endpoint name (e.g. line1): press1
  Protocol ('opcua','modbus','s7','mc','mtconnect','mqtt') [opcua]: s7
  S7 PLC host (IP/FQDN): 10.0.0.6
  Port [102]: 102
  Rack (0 for S7-1200/1500) [0]: 0
  Slot (1 for S7-1200/1500, 2 for S7-300/400) [1]: 1
✓ Saved endpoint 'press1'.

(MQTT prompts add TLS/topic/username; MTConnect prompts for agent_url; EtherCAT prompts for the nic + expected_slaves and warns about the Linux/root/NIC/optional-extra requirement; OPC-UA/MQTT prompt for a hidden password stored encrypted.)

Test against a simulator (per protocol)

  • OPC-UA — an asyncua demo server (the test suite runs a real in-process one).

  • Modbus — ModbusPal or a pymodbus server simulator.

  • S7 — a pyS7/snap7 S7 server sim (Snap7 server) on :102.

  • MTConnect — the public MTConnect demo agent, or a local agent.

  • MQTT — a local mosquitto broker (+ a Sparkplug edge for SpB topics).

  • Mitsubishi MC — GX Simulator / an MC 3E server sim.

  • EtherNet/IP — a pycomm3-compatible CIP/Logix simulator (or a spare CompactLogix).

  • Omron FINS — the in-repo mock FINS UDP/TCP responder (tests/test_fins.py) or a spare CP/CJ PLC.

  • IO-Link — the in-process mock master (tests/test_iolink.py, both JSON dialects) or any ifm/Balluff/Turck master on the bench.

  • EtherCATno simulator exists (hard-real-time, raw-Ethernet). Validate only on Linux, as root / with CAP_NET_RAW, on a dedicated NIC wired to real slaves (e.g. a Beckhoff EK1100 coupler + EL terminals). iaiops doctor reports a clear "needs Linux/root/NIC/pysoem" status off the bus rather than failing.


Usage

Site survey — find what is on a network you have not been given a list for

Every other command needs an endpoint you already configured. scan answers the question that comes first. It has no full-port mode, no raw sockets, no half-open SYNs, and no write path of any kind; what it may touch is a fixed industrial port allowlist, and how fast is capped by a ceiling the caller cannot raise.

iaiops scan profiles                                   # what each posture does
iaiops scan plan --targets 10.0.0.0/24                 # sends NOTHING — the artifact you get signed
iaiops scan run  --targets 10.0.0.0/24 --site "Line 1" \
                 --approved-by "J. Controls" --ticket CHG-91 \
                 --report survey.html                  # scan → store → one HTML file
iaiops scan list                                       # stored surveys
iaiops scan report --out survey.html                   # re-render the latest

scan plan puts nothing on the wire. It prints every host and port that would be touched, every class of packet that would be sent, the worst-case duration, and the explicit list of what this tool never does — so you can run it against a network before you have permission to scan it, and hand the output to whoever grants that permission. scan run shows the same preview and asks once before it sends anything (--yes to skip).

Postures run from passive (reads the local ARP cache, emits nothing at all) to legacy-safe (reachability only, one host at a time, five connects a second — for 1990s controllers where even a well-formed identify request is a risk). standard and deep refuse to run without a recorded sign-off.

The HTML report is self-contained: no fonts, scripts, styles or images from anywhere, and no network request when opened. Its first section is what the scan touched — per-class emission counts, including requests that failed — followed by the list of things it never does. The device table comes after that.

From a survey to a measured OEE — the path the site actually walks

scan answers what is out there. These answer what can I do with it, and what is the number. Each step is a real command; nothing here is a roadmap item.

iaiops readiness                                    # contacts NOTHING

What this installation can run today, and for each thing it cannot, the specific input that is missing — ranked by how much supplying it would unlock. It touches no device, so you can run it against a site you have not been authorised to probe, which is the site that most needs the answer. It reports gaps; it never fills one in (§9.4/D16 — a guessed production counter yields a plausible-looking OEE, which is worse than an error).

iaiops collect plan line1 --duration 7d --interval-ms 1000   # contacts NOTHING
iaiops collect run  line1 --duration 7d --interval-ms 1000
iaiops collect run  line1 --duration 7d --resume             # after a closed lid
iaiops store status                                          # what the store holds
iaiops store prune --sealed-before 2026-08-01 --apply        # refuses without a seal

A bounded assessment run — capped at 14 days, and the operator must state the end. There is deliberately no run-forever mode: a resident process on an OT network needs change management, a laptop running for a week does not (D21). Every run records the windows it could not see, so a gap is never silently readable as a stoppage.

To get an OEE out of it, three tags have to be declared — which value means running, which register counts parts, and (for Quality) which counts good ones:

endpoints:
  - name: line1
    ideal_cycle_time_s: 0.1
    tags:
      - {ref: "0",  role: run_state,   running_when: [2]}   # 2 = running
      - {ref: "10", role: total_count}
      - {ref: "11", role: good_count}

running_when is declared, never inferred. On the 0=stopped 1=idle 2=running 3=fault status word most PLCs expose, "any non-zero means running" counts three states of four as production.

iaiops oee measure line1 --reported 97               # against the figure the site keeps
iaiops oee measure line1 --since 2026-03-02T06:00:00Z --until 2026-03-09T06:00:00Z
iaiops oee measure line1 --report oee.html --lang zh --site "一号厂区"

Scope the measurement with --since / --until, together. Without them the period is everything the store holds for that endpoint — fine for one assessment run, wrong the moment there are two: the idle weeks between a March run and an August one become one enormous blind span and neither run can be measured.

The window is charged for in full. The parts of it that were never sampled — before the first sample and after the last — count as blind exactly like a gap in the middle, so narrowing the question to the minutes that happen to have data cannot raise your coverage. Ask about a shift you observed two hours of, and the answer is 25% coverage and a refusal, not "100% of what we saw".

Availability measured over the time the collector could see, with blind windows excluded rather than counted as downtime; plus Performance, Quality and the Six Big Losses. Each factor is reported only when its inputs were declared — a partial OEE that names what is missing beats a whole one with a guess inside it.

--report writes one self-contained HTML file — no fonts, scripts, styles or images from anywhere, and no network request when opened, so it works on an air-gapped laptop and survives being forwarded as an attachment. Its first section is what the measurement could see (coverage, blind time, sample cadence), before the number, and it carries the row a sales deck usually leaves out: what had to be declared to produce each figure, and what is still missing.

iaiops case open line1 --min-stop-s 300              # one case per long stoppage
iaiops case list                                     # each carries what someone DID after it
iaiops case causes                                   # the vocabulary a confirmation may use
iaiops case confirm <id> --cause material_starvation --by wei
iaiops case agreement                                # >90% agreement is a WARNING, not a score
iaiops diag learn-weights --site default             # learn a per-site cause profile
iaiops diag rca --input bundle.json --from-case <id> # a person's answer reaches the verdict

The label is a by-product of work already being done: the audit trail already recorded that someone ran a write four minutes after the line stopped, so the case shows it. Confirmation is one choice from a fixed vocabulary, never free text, and a dismissal is a label too. Whether an answer counts as independent is derived from whether the tool had suggested it — the answerer cannot claim it.

The investigation itself — eight steps, and what each one needs

readiness answers which scenarios this site can run. This answers the next question down: if something stopped tomorrow, how far could we actually get?

iaiops investigate plan                              # contacts NOTHING

Eight evidence steps — define the incident, collect the evidence, normalize and check it, compress and rank, correlate the timeline, test the hypotheses, check against known mechanisms, conclude and close. For each one it cannot walk, it says whether that is something you have not supplied (with the command that would) or something this product cannot express at all. Those two send a person to very different places.

iaiops investigate open line1 --start <iso> --end <iso> --asset "Line 1"
iaiops investigate show <id>                         # the state it was left in
iaiops investigate list

The same eight steps over a real past window, persisted so it can be re-read and advanced later. No device is contacted — the window is already over, and its evidence is whatever was collected at the time.

Any of the three writes the forwardable version — one self-contained HTML file that opens on an air-gapped laptop in a plant office:

iaiops investigate plan --report readiness.html --lang zh
iaiops investigate open line1 --start <iso> --end <iso> --report incident.html

Unlike oee measure --report, which refuses to write a file for a refused measurement, this one writes for a blocked investigation on purpose. An OEE report is a number, so a file existing at all claims one was measured. This report's content is how far this got and what each step still needs — which makes the blocked case the one most worth handing over, and for a site nobody has instrumented yet it is the whole deliverable. What it will not do is let a blocked investigation look finished: the headline is always the walk (2 / 8), never a conclusion, and no step's own words appear above it.

From a scan to a config

Everything on the path existed; nothing joined it. A site could scan forty devices and then retype all forty by hand, and nothing anywhere said which of the six commands came next.

iaiops onboard status                 # where am I, and what is the ONE next command
iaiops onboard draft                  # the newest scan → config.yaml endpoints
iaiops onboard draft --out draft.yaml # ...to a file you can review and merge

draft writes nothing into config.yaml — you merge it, exactly as with tags apply. What it emits is constrained on purpose:

  • Only CONFIRMED protocols become endpoints. An open 502 means something is listening, not that it is a Modbus device, and a config that said so would be believed. Those hosts are listed as skipped, with the reason.

  • Every value names the observation that justifies it — and the interesting half is what the scan learned that you would otherwise have hunted for: the S7 slot the CPU actually answered on, the MELSEC CPU's own plctype, whether an OPC-UA server advertises an unsecured endpoint or will need credentials.

  • A field the scan could not settle goes out commented, saying what it is waiting for — never omitted. Omission lets the protocol default apply in silence, which is how a Modbus gateway gets read at unit 1 and shows a confident number for the wrong machine.

  • tags: comes out empty. A scan finds devices; it establishes nothing about what their data means. That step is the next one, below.

  • Absence is not evidence. The draft states what it structurally cannot contain — BACnet/FINS/HART are UDP and never swept; MQTT and the supervisory layers are never identified, by design.

status is derived from the store and config.yaml every time. There is no onboarding state file, so a hand-edited config or a restored backup still gets a true answer rather than a remembered one — and a step that is genuinely done stays done even if you did the steps out of order.

For the point-list step it names the command for your protocol: opcua browse, eip tags, mtconnect probe, iolink ports, mqtt browse, bacnet objects, ethercat slaves, hart dynamic, or modbus templates. Where there genuinely is nothing to ask — an S7 CPU exposes no symbol table on the wire, and MELSEC and Omron memory carry none either — it says so in that protocol's own terms and tells you where the addresses do come from, rather than one sentence covering everything that is not OPC-UA.

Confirming what the point list means

The one thing this product refuses to infer, and until now the only way to supply it was hand-editing role: in a config file — which is exactly what stops working at a hundred rows.

iaiops tags export sheet.csv          # every monitored tag; `role` column EMPTY
# a person fills in role + running_when
iaiops tags apply sheet.csv --by wei  # prints the exact config.yaml edit

The role column comes out empty even next to a tag called GoodPartsCounter. A name is not a declaration; plenty of plants have one that counts something else, and a wrong production counter yields a plausible OEE — worse than an error (D16).

apply emits the patch rather than writing it. config.yaml stays the single source of truth: oee measure reads roles off the config tag objects, so a parallel store would let readiness call the mapping met while oee measure still could not run. A run_state with no running_when is refused here, for the same reason MonitorTag refuses it — "anything non-zero" counts idle and fault as production.

Or tick it through in a page instead of a spreadsheet:

iaiops tags page confirm.html --lang zh

HLD §13.9's App front end, delivered as a file rather than a served app. A localhost server inside an OT box has to answer which address it binds and who authenticates — and since every declaration here requires --by, a page with no identity cannot record who confirmed a tag, which is the one thing this step exists to capture. So the page collects, and the author is supplied at apply.

The page re-implements no refusal. run_state needing running_when, a ref having to be monitored, a role claimed twice — reproducing any of those in JavaScript is how they drift from the ones that actually gate the config, and a page that says "looks fine" while apply refuses is worse than no page. It ships script (it is a form) but makes no network request: it works with the cable out.

There is deliberately no MCP tool for this. An agent filling in the role column is precisely the guess D16 exists to forbid.

Two of the steps need something a person has to state:

iaiops relations declare press oven --by wei         # which asset feeds which
iaiops relations downstream press                    # nearest first

The second axis of root-cause analysis. With time alone, an upstream stoppage produces a string of equally-confident downstream false causes — on a line, downstream co-occurrence is guaranteed whatever the cause. That guarantee is why this is declared and not inferred (D25). Without it the timeline still runs; it degrades to a single asset and says so.

iaiops knowledge mount mechanisms.yaml --by wei      # what is known about this equipment
iaiops knowledge check sensor_fault --protocol modbus

A fault-mechanism library, shaped by ISO 14224: the failure mode (what you saw), the mechanism (what to go and check) and the cause (what to fix) stay separate, because they answer different questions. Entries attach to the seven taxonomy causes; they never add new ones — past roughly forty codes, two operators stop picking the same one.

It may exclude and never confirm. A mechanism that cannot apply to this equipment rules the candidate out, which is the strong move a ranker cannot make:

✗ sensor_fault — excluded
  every mounted mechanism for 'sensor_fault' applies only to hart, opcua — not to modbus

And a cause the library has never heard of reports nothing known — never "no objection". A knowledge base that knows nothing about something has not cleared it.

Program change baseline — has the approved logic moved?

A control program is a controlled document, and the usual way an undocumented change to one gets noticed is that somebody remembers. Record the version you consider approved, then ask a later export whether anything moved:

iaiops program snapshot ~/exports/Line3.scl --name Line3 --label "approved v3.2 / MOC-118"
iaiops program drift    ~/exports/Line3_today.scl --name Line3

The snapshot stores the file's SHA-256 plus a per-block structural fingerprint — name/kind/language, declared variables, calls, branch conditions, timers — and deliberately excludes line numbers, comments and block order, so adding one comment at the top of a file does not report the whole program as changed. What is stored on disk is block names, hashes and counts; never a declaration, a source line or a comment, so the baseline store is not a second copy of your program.

Three verdicts, and each word is load-bearing:

Verdict

Means

identical

The same SHA-256. Nothing else earns the word.

logic_changed

The extracted structure differs — reported per block, naming which of variables / calls / branches / timers_counters moved.

changed_outside_extracted_structure

The bytes differ and every block fingerprint matched.

That third one is the honest one. It is usually comments or formatting — but these parsers extract structure, they do not parse a grammar, so a real change inside a construct they do not model looks identical from here. Calling it "documentation only" would be the comfortable reading of evidence that does not support it, so it is not called that: line and comment counts are reported beside it and the verdict still says look. A drift report is a reason to read the diff, never a clearance.

iaiops program history lists what is tracked; iaiops program compare <name> <before> <after> diffs two stored snapshots. Deleting history is iaiops program forget and is CLI-only — an agent should not be one call away from removing change-control evidence. Nothing is pruned automatically. The name (not the path) is the identity, because the export directory changes every time somebody opens the engineering station and the program does not; absent --name the file stem is used and the output says so. No device is touched at any point — this reads a file a person exported.

CLI (read)

iaiops opcua read "ns=2;i=5" -e line1
iaiops modbus holding 0 -e plc2 --count 4 --decode float32
iaiops s7 read-db 1 REAL 4 -e press1 --count 2
iaiops mc words D100 -e cell3 --count 8
iaiops fins words 100 --area DM -e omron1 --count 8   # Omron FINS memory-area read
iaiops hart pv -e xmtr1                            # HART primary variable
iaiops iolink scan -e iolm1                        # IO-Link master + connected devices
iaiops mtconnect oee -e vmc1
iaiops mqtt nodes -e uns --timeout-s 15
iaiops eip tags -e cell5                           # Logix tag discovery
iaiops eip read "Conveyor.Speed" -e cell5
iaiops ethercat slaves -e bus1                     # EtherCAT bus scan (Linux+root)
iaiops ethercat read-sdo 0 4120 --subindex 1 -e bus1   # CoE SDO 0x1018:1
iaiops opcua history "ns=2;i=5" -e line1 --start 2026-06-28T08:00:00Z   # HDA
iaiops opcua monitor "ns=2;i=5" -e line1 --duration-s 20 --deadband 0.5 # CoV
iaiops diag dataflow -e line1 --ref "ns=2;i=5" --freshness-s 30
iaiops analytics oee 28800 25200 2.0 12000 11800   # OEE from five numbers you already have
                                                   # (for a measured one, see `oee measure` above)
iaiops analytics asset -e press1 -e cell5           # active asset register

CLI (write — dry-run by default, double-confirm on --apply)

iaiops s7 write-db 1 INT 0 42 -e press1            # dry-run preview
iaiops s7 write-db 1 INT 0 42 -e press1 --apply    # double-confirm prompt
iaiops mqtt publish factory/line1/cmd '{"setpoint":50}' -e uns --apply
iaiops eip write-tag Setpoint 42 -e cell5 --apply  # Logix tag write (double-confirm)
iaiops fins write-words 100 42 --area DM -e omron1 --apply  # Omron FINS write (double-confirm)
iaiops ethercat write-sdo 0 24698 e8030000 -e bus1 --apply   # CoE SDO 0x607A download
iaiops ethercat set-state PREOP --slave 0 -e bus1 --apply     # AL-state (can stop motion!)

MCP tool calls (JSON args → sample structured return)

s7_read_db:

{ "db": 1, "dtype": "REAL", "start": 4, "endpoint": "press1", "count": 2 }
{ "endpoint": "press1", "area": "DB", "db": 1, "dtype": "REAL", "start": 4,
  "count": 2, "items": [ {"address": "DB1,REAL4", "value": 20.5},
                         {"address": "DB1,REAL8", "value": 4.2} ] }

s7_write_db (dry-run):

{ "db": 1, "dtype": "INT", "start": 0, "value": 42, "endpoint": "press1" }
{ "address": "DB1,INT0", "dry_run": true, "before": 7, "would_write": 42,
  "note": "Dry run — nothing written. Re-run with dry_run=false AND a recorded approver…" }

mtconnect_oee_snapshot:

{ "availability": "AVAILABLE", "execution": "ACTIVE", "controller_mode": "AUTOMATIC",
  "program": "O1234", "available": true, "running": true, "verdict": "running" }

eip_read_tag:

{ "tag": "Conveyor.Speed", "endpoint": "cell5" }
{ "endpoint": "cell5", "tag": "Conveyor.Speed", "value": 1500.0, "type": "REAL",
  "error": "", "good": true }

eip_write_tag (dry-run):

{ "tag": "Setpoint", "value": 42, "endpoint": "cell5" }
{ "endpoint": "cell5", "tag": "Setpoint", "dry_run": true, "before": 7,
  "would_write": 42, "note": "Dry run — nothing written. Re-run with dry_run=false AND a recorded approver…" }

ethercat_read_sdo (CoE SDO upload):

{ "slave": 0, "index": 4120, "subindex": 1, "endpoint": "bus1" }
{ "endpoint": "bus1", "slave": 0, "index": "0x1018", "subindex": 1,
  "byte_length": 4, "hex": "9a020000", "as_uint": 666 }

ethercat_set_state (dry-run; can start/stop motion):

{ "state": "OP", "slave": 0, "endpoint": "bus1" }
{ "endpoint": "bus1", "scope": "slave[0]", "dry_run": true, "before": "SAFEOP",
  "would_request": "OP", "note": "Dry run — no state change. … Changing EtherCAT state can start/stop machine motion." }

sparkplug_decode_payload (full SpB metric decode):

{ "payload": "CAESBwoDYWJjEAE=", "encoding": "base64" }
{ "encoding": "sparkplug_b", "seq": 0, "metric_count": 2, "historical_count": 0,
  "metrics": [ {"name": "Temperature", "alias": 1, "datatype": "Double", "value": 21.5,
                "is_historical": false, "is_null": false} ] }

oee_compute:

{ "planned_time_s": 28800, "run_time_s": 25200, "ideal_cycle_time_s": 2.0,
  "total_count": 12000, "good_count": 11800 }
{ "availability": {"raw": 0.875, "value": 0.875, "capped": false},
  "performance": {"value": 0.952381}, "quality": {"value": 0.983333},
  "oee": 0.819444, "oee_pct": 81.94 }

asset_inventory (active fingerprint):

{ "endpoints": ["press1", "cell5"] }
{ "asset_count": 2, "reachable_count": 2, "method": "active_fingerprint",
  "assets": [ {"endpoint": "press1", "protocol": "s7", "vendor": "Siemens/compatible",
               "model": "CPU 1511-1 PN", "firmware": "2.8", "reachable": true,
               "last_seen": "2026-06-28T10:00:00+00:00"} ] }

Diagnostics (multi-dimensional JSON for an agent to visualize)

diagnose_dataflow(endpoint="line1", ref="ns=2;i=5", freshness_threshold_s=30):

{ "verdict": "comms_ok_value_stale",
  "diagnosis": "Connected with good status, but the value is STALE (age 412s > 30s) — the source/field upstream has stopped updating this point.",
  "recommended_action": "Trace upstream: the device serves the last value fine, so suspect the source/scanner/field signal that should refresh it.",
  "hops": [ {"hop":"connect","protocol":"opcua","ok":true,"detail":"OPC-UA state=0"},
            {"hop":"read_tag","ref":"ns=2;i=5","ok":true,"detail":"5.0"},
            {"hop":"freshness","evaluated":true,"stale":true,"age_seconds":412.0} ] }

alarm_bad_actors(events=[…]):

{ "event_count": 55, "window_minutes": 0.82, "alarms_per_hour": 4024.4,
  "isa_18_2": {"ok_max":6,"manageable_max":12,"flood_min":30},
  "flood_verdict": "flood",
  "priority_distribution": {"high":50,"low":5},
  "pareto_sources_for_80pct": ["FIC101"],
  "top_offenders": [ {"source":"FIC101","count":50,"share_pct":90.9,"chattering":true,"standing":false} ],
  "chattering": ["FIC101"], "standing": [] }

tag_health(tags=[…]):

{ "evaluated": 4, "overall": "alarm", "offender_count": 3,
  "offenders": [ {"ref":"hot","latest":99,"flags":["out_of_range_alarm"],"severity":3},
                 {"ref":"flat","latest":5,"flags":["flatline"],"severity":2},
                 {"ref":"bad","latest":null,"flags":["bad_quality"],"severity":3} ] }

AI downtime root-cause copilot (flagship)

downtime_root_cause correlates whatever evidence you can hand over — alarm events, tag samples, a diagnose_dataflow verdict, a machine-state series — around an incident window and returns an evidence-cited, advisory verdict. Read-first: it proposes a human-approved, MOC-gated, undoable action and executes nothing. Anti-hallucination by design — it cites only signals actually present in the input, weights them by temporal proximity to onset (a cause precedes its effect), and downgrades to insufficient_evidence (with a recommended_next_data list) rather than guessing when evidence is thin.

downtime_root_cause(window={"start":"2026-06-28T10:00:00Z","asset":"line1"}, alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:52Z","message":"motor overload trip"}], tags=[{"ref":"DRV1.Torque","samples":[10,11,99,99],"alarm_high":80}], dataflow={"verdict":"healthy"}):

{ "window": {"start":"2026-06-28 10:00:00+00:00","asset":"line1","duration_s":300.0},
  "verdict": "root_cause_identified",
  "primary_cause": {
    "cause": "mechanical_fault", "confidence": 0.722, "confidence_band": "high",
    "evidence": [
      {"signal":"alarm","ref":"M1_DRIVE","at":"2026-06-28 09:59:52+00:00","lead_time_s":8.0,
       "detail":"motor overload trip","weight":0.4959},
      {"signal":"tag","ref":"DRV1.Torque","detail":"flags=out_of_range_alarm severity=3","weight":0.45} ],
    "recommended_action": "Dispatch maintenance to inspect the faulting unit; if a latch/interlock is set, the reversible step is to clear the fault and reset the latch (MOC-approved, undo captures the prior latch state)." },
  "evidence_summary": {"alarms_supplied":1,"tags_supplied":1,"dataflow_verdict":"healthy","total_evidence_items":2},
  "anti_hallucination": "Advisory only — nothing is executed. Every cited signal is present in the supplied evidence …" }

The same copilot is on the CLI: iaiops diag rca --input bundle.json where the bundle is {window, alarms?, tags?, dataflow?, state_series?}.

Let it gather its own evidence. downtime_root_cause_live (CLI iaiops diag rca-live) takes just an endpoint + window + the refs to look at, then pulls the evidence itself — a cross-protocol diagnose_dataflow probe, a short sampled series per ref (so flatline / bad-quality / anomaly surface via tag_health), and active OPC-UA conditions — before running the same advisory, read-only copilot. The gathered bundle is echoed back under collected_evidence (no hidden inputs):

iaiops diag rca-live -e line1 --start 2026-06-28T10:00:00Z \
  --asset line1 --ref "ns=2;i=5" --ref "ns=2;i=6"

Data-quality watchdog & UNS governance (read-only intelligence)

Two more pure-analysis layers — fully testable without live gear, and they feed the RCA copilot.

  • data_quality_scorecard (CLI iaiops diag dataquality) — a fleet data-TRUST rollup: scores each tag 0-100 on whether its data can be believed — staleness, dead heartbeat (first-class), bad-quality, flatline, gaps, anomaly — then rolls up per endpoint and across the fleet with an issue breakdown and ranked worst offenders. Distinct from process health: it asks "can I trust this number," not "is this number alarming." heartbeat_health (CLI iaiops diag heartbeat) is the standalone watchdog-liveness check (a flatlined heartbeat = dead upstream even when comms look fine).

  • uns_topic_audit (CLI iaiops mqtt uns-audit) — governs a UNS topic tree: naming conformance (allowed roots / min depth) + topic sprawl (casing collisions of the same logical name, leaf metrics scattered under many parents, depth outliers, duplicates) → a clean/minor/sprawling verdict. uns_schema_drift (CLI iaiops mqtt uns-drift) — compares two Sparkplug NBIRTH-style snapshots and classifies the change none / additive / breaking (a metric removed or its datatype changed). Positions the UNS as a governable neutral data source, not just a broker.

MCP server

IAIOPS_MCP=opcua iaiops-mcp   # stdio transport (`iaiops mcp` is equivalent)

Menu — expose only the protocols a site runs. A fab usually runs 1–2 protocols; exposing all 14 floods the model with tools it can't use. Set IAIOPS_MCP to a comma-list of protocols and/or a named profile. There is no default (since 0.10.0): a bare iaiops-mcp prints the selection menu (profiles, protocol keys, tool counts) to stderr and exits 2 instead of silently exposing 100+ tools. The cross-protocol brain (OEE / downtime / diagnostics / asset / analysis) is included by default with every selection.

IAIOPS_MCP=menu         iaiops-mcp   # print the menu (selections + tool counts)
IAIOPS_MCP=opcua,modbus iaiops-mcp   # two protocols + brain
IAIOPS_MCP=fab          iaiops-mcp   # named profile (secsgem+opcua+s7+modbus)
IAIOPS_MCP=opcua        iaiops-mcp   # effectively a single-protocol MCP
IAIOPS_MCP=all          iaiops-mcp   # everything — explicit opt-in only
                                     # (logs a tool-flood warning above 100 tools)

Named entry-point sugar. For the common single-protocol / single-edition case there is a pre-scoped console script per protocol and per named profile — no env var to set. Each is a thin shim over the same server:

iaiops-mcp-opcua     # == IAIOPS_MCP=opcua    iaiops-mcp
iaiops-mcp-modbus    # == IAIOPS_MCP=modbus   iaiops-mcp
iaiops-mcp-fab       # == IAIOPS_MCP=fab      iaiops-mcp  (per-edition)
iaiops-mcp-building  # == IAIOPS_MCP=building iaiops-mcp
iaiops-mcp-brain     # == IAIOPS_MCP=brain    iaiops-mcp  (brain only, 0 protocols)

Multi-process sites — 1 brain MCP + N protocol MCPs. Running several protocol servers side by side (e.g. iaiops-mcp-opcua + iaiops-mcp-modbus) would duplicate the ~30 brain tools in every server. Instead run one dedicated iaiops-mcp-brain and set IAIOPS_MCP_NO_BRAIN=1 on the protocol servers to strip the brain from them — the protocols_supported discovery tool stays exposed everywhere:

iaiops-mcp-brain                          # the one cross-protocol brain server
IAIOPS_MCP_NO_BRAIN=1 iaiops-mcp-opcua    # lean protocol server, no brain
IAIOPS_MCP_NO_BRAIN=1 iaiops-mcp-modbus

Write authorisation is not the tap's job. iaiops does not withhold write tools behind a server switch. Whether a write is allowed is the caller's decision — the agent's judgement or account/permission management — and the tap's job is to make that write accurate, efficient, and un-bypassably audited. Every call, read or write, on either front-end (MCP tool and iaiops CLI), goes through @governed_tool and leaves a row in ~/.iaiops/audit.db. Writes are additionally HIGH risk_tier and MOC-gated (dry-run + double confirmation + undo capture + a recorded approver). protocols_supported reports this posture so the model is told the rules rather than left to infer them.

Since 0.20.3 that promise is held by contract tests over the real tool surface rather than by synthetic stand-ins: every one of the ten high-risk writes is driven end to end and must be denied without an approver with the connector never reached — "it raised" only proves an exception, not that nothing reached the device. Two things those tests exposed on the way in: a call that failed was audited as ok (tools return the canonical {error, hint} envelope rather than raising, so the governance wrapper saw an ordinary return), which also told the pattern circuit breaker "success" on every failure; and the runaway guard, blind to a caller retrying a denial forever, let 500 identical denied writes through a ceiling of 10. Both are fixed and pinned.

Sealed sites — make the data-shipping tools cease to exist. IAIOPS_NO_EGRESS=1 removes every tool whose job is to transmit local or plant data to a destination the caller names, at registration time so a weak or prompt-injected model cannot call what it cannot see:

IAIOPS_NO_EGRESS=1 iaiops-mcp-factory   # 134 tools -> 129; 5 withheld

Withheld: stream_publish, stream_publish_event (NATS message bus), uns_publish (MQTT broker / Unified Namespace), historian_push (external TSDB), mqtt_publish (broker), rca_narrate (POSTs the RCA verdict — plant tags, values and citations — to a caller-supplied model base_url). This is a data-exfiltration / airgap axis, not read/write authorisation: historian_push is risk_level="low" — it changes no plant state — yet it ships telemetry off-box, so this switch withholds it. It gates MCP tools only, and is not a firewall (reads still open sockets to plant devices). protocols_supported reports each posture independently.

Scope, stated plainly — this is not a firewall:

  • It gates MCP tools only. iaiops audit forward (SIEM) is a CLI path no registry gate can reach; block it at the host if the box must be sealed.

  • Reads still open outbound sockets. iaiops is a network tap — it must talk to PLCs, brokers and historians to read anything at all. The gate removes the tools whose purpose is sending data outward, not the network itself.

  • It does not police arguments. A tool is present or absent as a whole; nothing is inspected at call time (that would be the call-time refusal this design rejects). This is why a tool with a caller-supplied destination is withheld even when its default points at localhost — the model picks the argument.

  • Local file writes are not egress: export_data and compliance_evidence_bundle stay exposed. The bytes never leave the box; getting them off it afterwards is a host-level concern.

  • Both switches cover the iaiops-mcp server only (including its per-protocol / per-edition entry-point shims). iaiops-energy-mcp is a separate server in a separate package and does not honour them yet — it mirrors in the base brain/compliance tools, so IAIOPS_NO_EGRESS=1 there still leaves historian_push, rca_narrate, stream_publish and stream_publish_event exposed on iaiops-energy 0.1.6 and earlier. Fixed in iaiops-energy 0.1.7, which pins iaiops>=0.17 for exactly this reason. Said out loud because a switch believed to be on is worse than one known to be absent.

Named profiles: all · brain · fab · factory · process · building · plcnext · water · renewables · warehouse · clinical. In an MCP client (e.g. Claude Desktop) set IAIOPS_MCP per server entry — or point the entry straight at the matching iaiops-mcp-<name> script — one entry per site/line, each a lean single- or dual-protocol server.


Safety & governance

  • Read-first. 185 of the 196 tools are read-only, and historian_push writes to a historian rather than to a device. The 10 write/command tools (s7_write_db, mc_write_words, fins_write_words, mqtt_publish, eip_write_tag, ethercat_write_sdo, ethercat_set_state, profinet_dcp_set, bacnet_write_property, bas_command) are OT-dangerous: governed at high risk_tier, off by default (dry-run), require a double-confirm in the CLI, and a recorded approver (one-shot iaiops approve tokens; with no risk_tiers configured, high/critical operations default to the dual tier) — MOC discipline. All ten declare an undo (no exemptions since 0.20.3); a successful write captures the BEFORE value/state and registers an inverse descriptor. The inverse honestly reports "none" where none exists — a transient (retain=False) mqtt_publish cannot be unsent, and ethercat_set_state's +ERR/NONE/BOOT are not cleanly re-requestable AL-states. An undo that over-promises is worse than none, because someone will replay it onto live equipment. ethercat_set_state can START or STOP machine motion. 未经授权勿对生产控制系统写入.

  • Read/write authorisation is the caller's, not the tap's. iaiops does not encode "this server may not write" by hiding tools — that decision belongs to the agent's judgement or account/permission management. The tap's guarantee is un-bypassable audit on both front-ends: every call, read or write, via an MCP tool or the iaiops CLI, runs through @governed_tool and leaves a row in ~/.iaiops/audit.db. Writes are additionally high risk_tier, MOC-gated, and undo-captured (see above). High/critical calls fail closed when the audit DB cannot be written.

  • No-egress mode is enforced at registration. IAIOPS_NO_EGRESS=1 withholds the 6 tools that ship data off-box (stream_publish, stream_publish_event, uns_publish, historian_push, mqtt_publish, rca_narrate), fail-closed, for airgap/sealed-box deployments. This is a data-exfiltration axis, not authorisationhistorian_push is low-risk (it changes nothing) yet pushes telemetry to an external TSDB, so this switch withholds it. Which tools count is derived from @governed_tool(egress=True) metadata and guarded by an AST scan in CI, so the next egress tool cannot silently escape the gate.

  • Do not point this at a production control system without authorization. OT networks are safety-critical; even reads add load. Test against a simulator first.

  • All endpoint-returned text is sanitized (prompt-injection defense); secrets are never returned by any tool; MTConnect XML is parsed with DTD/entity declarations refused.

  • Every tool runs through the vendored governance harness: SQLite audit (~/.iaiops/audit.db, SHA-256 hash-chained rows + iaiops audit verify; audit fails closed for high/critical writes), token/call budget + runaway breaker, risk-tier gate (policy engine fails closed on a broken rules.yaml), undo recording. The MCP server refuses to start if any registered tool lacks the governance marker.

Roadmap

Four items that used to sit here had in fact shipped — including two this same README already listed as verified, three sections above. Listing built work as future work is the same defect as claiming unbuilt work, so they are gone: EtherNet/IP PCCC (PLC-5/SLC-500) and Micro800, passive asset discovery (iaiops scan --posture passive, ARP-cache only, emits nothing), OPC-UA certificate security, and MTConnect streaming long-poll.

What is genuinely open:

  • EtherCAT EoE / FoE / SoE mailbox protocols and full PDO-mapping decode (CoE SDO/PDO read+write and AL-state landed in 0.3.0 via the optional pysoem extra).

  • Sparkplug B Template deep expansion (DataSet landed in 0.17.0).

  • Contextual baselines — one normal band per tag today, but an OT normal range moves with shift, product and start-up. Learn per bucket, and refuse a bucket with too few samples rather than falling back to a global band, which would disguise "never seen this regime" as "this regime is normal".

  • Relationship-aware root cause — evidence is weighted by time only, so one upstream stoppage yields a run of equally-confident downstream false causes. A human-declared line order is enough to start.

  • Passive discovery from a SPAN/tap — the ARP-cache posture is built; reading a mirror port is not.

Missing a protocol, device, or feature? 缺功能提 issue/PR 欢迎留言 — open a GitHub issue or PR.

License

MIT © wei

Available Tools

153 tools
adopt_alias_mapA
Read-only

[READ][risk=low][PERSIST] Adopt + persist the canonical alias map for a site.

Writes a local owner-only advisory JSON file (NOT an OT-device write — hence
risk=low); see the persistence note below.

Runs the cross-protocol asset model over ``feeds``, extracts the adopted map
``{canonical_alias: {ref, protocol, asset, name, class}}``, and persists it as
the site's baseline (owner-only JSON under the iaiops home). Re-running
overwrites the baseline. Advisory — the map is a SUGGESTION, never a
server-side rename (OT-dangerous).

Args:
    feeds: Per-protocol tag feeds ``[{protocol, source, asset?, tags:[...]}]``,
        the SAME shape ``cross_protocol_asset_model`` takes.
    site: Site label (a safe file leaf: alphanumeric/_/-). Default 'site'.

Returns dict: {site, path, tag_count, adopted:{alias: {...}}}.

Example: adopt_alias_map(feeds=[{"protocol":"opcua","source":"l1","tags":[...]}],
    site="plant").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that it writes a local file (persistence), is non-destructive, and re-running overwrites baseline. Annotations already indicate readOnly, but description clarifies it's a safe local write, adding value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Structured with intro, details, args, returns, example. Some redundancy in advisory messaging, but overall efficient and front-loaded with risk and purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers key aspects: persistence, advisory nature, return structure, parameter details. Lacks error handling or edge cases, but sufficient for a moderate-complexity tool with no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% coverage, but description explains feeds shape (referencing sibling) and site constraints. Adds default and format, compensating for lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it adopts and persists the canonical alias map for a site. It distinguishes from siblings by noting it runs cross_protocol_asset_model and is advisory, not server-side rename.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides context that it writes a local advisory file and is not an OT-device write, implying when not to use. However, lacks explicit alternatives or exclusions beyond the warning.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

alarm_bad_actorsA
Read-only

[READ][risk=low] ISA-18.2 alarm-flood analysis over a list of alarm events.

Args:
    events: Alarm/condition events — {source, timestamp (ISO-8601), priority?,
        state? (ACTIVE/RTN/ACK)}.
    window_minutes: Analysis window; omitted → inferred from event timestamps.
    chatter_window_s: A source with >=3 transitions inside this window chatters.
    standing_s: An alarm active longer than this is 'standing/stale' (default 24h).
    top_n: How many top offenders to return.

Returns dict: {event_count, window_minutes, alarms_per_hour,
    isa_18_2:{ok_max:6, manageable_max:12, flood_min:30},
    flood_verdict ('ok'|'manageable'|'over_target'|'flood'),
    priority_distribution, pareto_sources_for_80pct, top_offenders:[{source,
    count, share_pct, chattering, standing}], chattering:[...], standing:[...]}.

Example: alarm_bad_actors(events=[{"source":"FIC101","timestamp":"...",
    "priority":"high"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
top_nNo
eventsYes
standing_sNo
window_minutesNo
chatter_window_sNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant behavioral details beyond annotations, including analysis thresholds (chatter window, standing time, flood limits), return structure, and risk level. It discloses defaults and algorithm behavior, giving the agent a clear understanding of side effects and safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary line, parameter list, return dict, and example. It is slightly verbose due to redundant example details, but every sentence serves a purpose and it is front-loaded with key context.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the absence of an output schema and the moderate complexity (5 params, no enums), the description provides a complete understanding: all parameters are explained, return format is detailed with example values, and context signals (readOnly, low risk) are reinforced.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully explains all 5 parameters—their purpose, expected format (e.g., ISO-8601 timestamps), defaults, and constraints (e.g., chatter_window_s logic). This compensates completely for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs 'ISA-18.2 alarm-flood analysis over a list of alarm events', specifying the standard and action. The [READ] tag confirms the operation type. It differentiates from siblings like 'alarm_flood_analysis' by referencing the specific standard and parameterization.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does and provides an example, but lacks explicit guidance on when to use this tool versus alternatives (e.g., alarm_flood_analysis, alarm_cascade). It does not state prerequisites or exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

alarm_cascadeA
Read-only

[READ][risk=low] Collapse an alarm flood into cascades + each cascade's first-out root.

Answers "which alarm to look at first" when 100+ alarms hit in minutes: groups annunciations
into cascades (a new cascade starts after a quiet gap > window_s) and reports the FIRST-OUT
alarm (earliest in the burst) as the likely root, plus downstream members and any chattering
sources. First-out is a transparent heuristic cited by timestamp — NOT causal (use
downtime_root_cause for causality). Pass 'events' for pure analysis, or an endpoint to collect
live via the OPC-UA active-condition scan. Read-only; bounded.

Args:
    endpoint: Endpoint name from config (used only when events is omitted).
    duration_s: Live collection window in seconds (1..300, default 60).
    window_s: Quiet gap (seconds) that separates one cascade from the next (default 60).
    min_cascade: Minimum annunciations for a group to count as a cascade (default 2).
    events: Injected alarm events — {source, timestamp (ISO-8601), state?}; skips live collect.

Returns dict: {cascade_count, total_activations, cascades:[{root:{source, ts}, size,
    distinct_sources, span_s, members[], chattering[]}], collected?}.

Example: alarm_cascade(events=[{"source": "PT101", "timestamp": "2026-06-28T10:00:00Z"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
window_sNo
duration_sNo
min_cascadeNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the agent knows it's safe. The description adds valuable behavioral context: the first-out heuristic is transparent ('cited by timestamp'), cascades are separated by a quiet gap, and it mentions chattering sources. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a front-loaded purpose statement, clear usage guidance, and a parameter list. While slightly verbose, every sentence adds value. The example and return dict description enhance usability without unnecessary fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, no output schema, no schema descriptions), the description covers all needed context: use cases, parameter details, return format (dict structure), example, and relationship to siblings. It leaves no gaps for an agent to misunderstand.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description fully compensates by explaining each parameter: `endpoint` (used only when `events` omitted), `duration_s` (live window 1-300s), `window_s` (quiet gap), `min_cascade` (minimum annunciations), and `events` (format `{source, timestamp, state?}`). Defaults and constraints are also provided.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Collapse an alarm flood into cascades + each cascade's first-out root.' It specifies the resource (alarm events) and the unique output (cascade root identification). It distinguishes from sibling `downtime_root_cause` by explicitly stating it is not causal.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: use when '100+ alarms hit in minutes' to find 'which alarm to look at first.' It tells when not to use ('NOT causal – use downtime_root_cause for causality') and describes two usage modes (pass `events` or `endpoint`), covering both analytical and live scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

alarm_event_clustersA
Read-only

[READ][risk=low] Collapse ten phrasings of one fault into one row.

`alarm_bad_actors` ranks by SOURCE, which answers "which instrument is
noisiest" and not "which fault is noisiest". A plant that words one condition
ten ways — `PT-101 HIGH`, `PT-102 HIGH`, `PT-103 high alarm` — gets ten bad
actors and no sign that they are one problem, so a rationalization meeting
works the list top-down and fixes the same thing three times. This groups the
same events by what they SAY instead of by who said it.

Clustering is **exact equality of a normalized string, not similarity**: case,
punctuation and embedded numbers are removed, and what remains must match
exactly. That is deliberately dumber than it could be, and it is why the
result needs no model and can be checked — two messages land together only
when they are literally the same sentence with the identifiers taken out.
Every cluster carries the distinct wordings and sources it merged, so you can
see what was combined. It does **not** claim two differently-worded alarms
mean the same thing; a person decides that.

Events carrying no message text are counted separately and excluded from the
shares, rather than being lumped together as one type.

Args:
    events: [{source?, message|description|text|condition|type, ...}].
    top_n: Clusters returned, largest first (default 20, capped at 100).
    min_count: Only report clusters with at least this many events (default 1 —
        a one-off is still reported, not tidied away).

Returns dict: {events_supplied, events_clustered, events_without_text,
    cluster_count, collapsed_count, clusters:[{signature, count, share_pct,
    distinct_wordings, distinct_sources, variants:[{text, count}],
    sources:[{source, count}]}], note}.

Example: alarm_event_clusters(events=[{"source":"PT-101","message":"pressure HIGH"},
    {"source":"PT-102","message":"Pressure high!"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
top_nNo
eventsYes
min_countNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the operation read-only and non-destructive, but the description adds substantial behavioral detail: exact equality after normalization of case, punctuation, and embedded numbers; events without message text are excluded from shares; and each cluster retains distinct wordings and sources. It also explicitly states what the tool does NOT claim, preventing over-interpretation of cluster meanings.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every sentence earns its place: it opens with a one-line summary and risk marker, explains motivation and algorithm, details all three parameters, and lists the return structure. The contrast with alarm_bad_actors is front-loaded, and the example grounds the explanation without bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given there is no output schema, the description compensates by fully specifying the return dict fields, including clusters, signatures, counts, shares, distinct wordings, and sources. It also addresses edge cases like events without text and one-off clusters. Combined with the sibling context and annotations, an agent has everything needed to select and invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully carries the burden. It explains the events parameter with accepted message field aliases, top_n with default and cap, and min_count with default and behavior. It even provides a concrete example call showing expected parameter shapes.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The first line states a specific action and resource: 'Collapse ten phrasings of one fault into one row.' The description then explicitly contrasts this with alarm_bad_actors, clarifying that this tool answers 'which fault is noisiest' rather than 'which instrument is noisiest.' This clearly differentiates it from the closest sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete when-to-use context: when multiple wordings of the same underlying fault inflate a bad-actor list. It names the alternative alarm_bad_actors and explains the distinction in terms of SOURCE versus message content. It also cautions that clustering is exact-equality based, not semantic similarity, so a human must decide whether different wordings mean the same thing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

alarm_flood_analysisA
Read-only

[READ][risk=low] ISA-18.2 deep alarm-flood analysis: episodes + chattering + stale + advice.

Deepens alarm_bad_actors: detects flood *episodes* (start/end/count/peak rate/
top contributors + each episode's first-out annunciation, per ISA-18.2's >=10
alarms per 10 min per operator), alarms chattering ACTIVE↔CLEARED, standing/
stale alarms, and percent-time-in-flood vs the ISA-18.2 targets (~1-2 alarms/
10 min steady state, <1% time in flood). Also returns an ISA-18.2 'load_profile'
(per-bucket rate band + peak period + trend) and per-source 'suppression_advice'
(deadband/on-off-delay for chatter, time-limited shelve for standing alarms).
The suppression advice is ADVISORY ONLY — starting values for a human to review
and approve via your ISA-18.2 / management-of-change process; this tool never
applies suppression, shelving, deadband, or delay changes. Pass 'events' for
pure analysis, or an endpoint to collect live via the same OPC-UA active-
condition scan the RCA copilot uses (polled over duration_s; other protocols
contribute no alarms). Output is bounded; 'truncated' flags say when caps bit.

Args:
    endpoint: Endpoint name from config (used only when events is omitted).
    duration_s: Live collection window in seconds (1..300, default 60).
    window_s: Flood analysis window in seconds (ISA-18.2 default 600).
    threshold: Annunciations per window that start a flood (default 10).
    events: Injected alarm events — {source, timestamp (ISO-8601), state?
        (ACTIVE/RTN/CLEARED)}; skips live collection entirely.
    stale_after_s: Continuously-active age that marks a standing alarm (default 24h).
    max_episodes: Cap on returned flood episodes (default 20).
    max_rows: Cap on chattering / stale / suppression-advice / worksheet rows (default 50).
    load_bucket_s: Load-profile bucket width in seconds (ISA-18.2 default 600 = 10 min).

Returns dict: {event_count, summary:{insufficient_data, percent_time_in_flood,
    avg_alarms_per_10min, peak_alarms_per_10min, isa_18_2_targets, ...},
    load_profile:{overall_band, peak_bucket, band_distribution, trend,
    busiest_buckets:[...], ...}, flood_episodes:[{start, end, ..., top_contributors,
    first_out:{source, ts}}], chattering:[{source, cycles, cycles_per_hour, ...}],
    stale_standing:[{source, active_since, active_for_s}], suppression_advice:[{source,
    kind, technique, suggested_on_delay_s, suggested_off_delay_s, suggested_shelve_max_s,
    basis, advisory}], worksheet_preview:[...], advisory_note, truncated:{...}, collected?}.

Example: alarm_flood_analysis(events=[{"source":"FIC101",
    "timestamp":"2026-06-28T10:00:00Z","state":"ACTIVE"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
max_rowsNo
window_sNo
thresholdNo
duration_sNo
max_episodesNo
load_bucket_sNo
stale_after_sNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description starts with '[READ][risk=low]' aligning with readOnlyHint=true annotations, explicitly states the tool never applies suppression (non-destructive), and describes output bounds and 'truncated' flags, adding behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a front-loaded summary, detailed body, bulleted 'Args', return dict, and example. While lengthy, every sentence adds value due to the tool's complexity. Structure is excellent but slightly verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description thoroughly explains the return dict, ISA-18.2 context, relationship with alarm_bad_actors, and edge cases like truncated flags. It is fully complete for a complex tool with 9 parameters.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description fully explains each parameter in the 'Args:' section, including purpose, defaults, constraints (e.g., duration_s 1..300), and the events format, providing meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs ISA-18.2 deep alarm-flood analysis covering episodes, chattering, stale alarms, and suppression advice. It distinguishes from sibling 'alarm_bad_actors' by stating 'Deepens alarm_bad_actors', providing a specific verb and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use 'events' for pure analysis vs an endpoint for live collection, and warns that suppression advice is advisory only and never applied. It also notes that other protocols contribute no alarms, giving clear application context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

alarm_rationalization_worksheetA
Read-only

[READ][risk=low] ISA-18.2 alarm-rationalization worksheet (CSV or inline rows).

One row per alarm source, count-descending: count, % of total annunciations,
chattering?, flood contributor?, and a recommendation stub — the starting
document for an ISA-18.2 rationalization review. Pass 'events' for pure
analysis, or an endpoint to collect live via the same OPC-UA active-condition
scan the RCA copilot uses. With out_path the full worksheet is written as CSV
and the path returned; otherwise bounded inline rows (truncation noted).

Args:
    endpoint: Endpoint name from config (used only when events is omitted).
    duration_s: Live collection window in seconds (1..300, default 60).
    events: Injected alarm events — {source, timestamp (ISO-8601), state?}.
    window_s: Flood analysis window in seconds (ISA-18.2 default 600).
    threshold: Annunciations per window that start a flood (default 10).
    out_path: Optional CSV destination; parent directory must exist.

Returns dict: {row_count, columns:[alarm_id, count, pct_of_total, chattering,
    in_flood, recommendation], csv_path? , rows?:[...], truncated (bool)}.

Example: alarm_rationalization_worksheet(events=[...], out_path="worksheet.csv").
ParametersJSON Schema
NameRequiredDescriptionDefault
eventsNo
endpointNo
out_pathNo
window_sNo
thresholdNo
duration_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses behavioral details: the tool is read-only ([READ][risk=low]), outputs inline rows with truncation, writes CSV when out_path is provided, and returns a structured dict. It also references the same OPC-UA scan as the RCA copilot. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured, starting with a one-line summary and a [READ][risk=low] tag, then detailing parameters and return format. It is slightly verbose for a single tool but remains focused and front-loaded. Every sentence adds value, though some redundancy could be trimmed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 6 optional parameters, no output schema, and the presence of annotations, the description covers all important aspects: parameter roles, defaults, return dict fields (row_count, columns, csv_path, rows, truncated), and an example call. It references the ISA-18.2 standard and explains truncation behavior, leaving no major gaps for a rationalization worksheet tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining each parameter: endpoint (optional, for live collection), duration_s (1-300 default 60), events (injected alarm events), window_s (flood analysis window, default 600), threshold (10), and out_path (optional CSV destination). It provides defaults, constraints, and usage context, making the parameter meaning clear.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool generates an ISA-18.2 alarm-rationalization worksheet with one row per alarm source. It specifies the output includes count, percentage, chattering, flood contribution, and recommendations. This distinguishes it from sibling alarm tools like alarm_flood_analysis or alarm_cascade, making the purpose highly specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains two usage modes: pass 'events' for pure analysis or an endpoint for live collection via OPC-UA. It implies use when a rationalization worksheet is needed but does not explicitly contrast with alternatives or specify when not to use. The guidance is clear but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

anomaly_scanA
Read-only

[DEPRECATED → opcua_anomaly_scan][READ][risk=low] Statistical outlier scan.

Samples a node over a bounded window and flags statistical outliers.
Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev.
Simple statistics only — no ML, no persisted model.

Args:
    node_id: The OPC-UA node id to scan.
    endpoint: Endpoint name from config.
    samples: Max samples (capped server-side).
    interval_ms: Delay between samples in milliseconds.
    sigma: Outlier band width in standard deviations.
ParametersJSON Schema
NameRequiredDescriptionDefault
sigmaNo
node_idYes
samplesNo
endpointNo
interval_msNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=true) align with description's [READ] tag. Discloses algorithm: mean/stddev/min/max, flags outliers outside sigma*stddev. Adds behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with deprecation, tags, brief summary, then bullet-like args. Slightly verbose but clear and front-loaded with key info.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 params and no output schema, description covers algorithm, parameters, and deprecation adequately. Agent can decide to use or switch to opcua_anomaly_scan.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but description documents all 5 parameters with brief explanations (e.g., 'sigma: Outlier band width in standard deviations'). Adds meaning beyond schema defaults/titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly describes statistical outlier scan for OPC-UA nodes. Distinguishes from sibling via deprecation notice pointing to opcua_anomaly_scan, but no explicit functional comparison.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly deprecated with alternative named. States 'Simple statistics only — no ML, no persisted model', guiding when to use. Doesn't provide when-not-to-use beyond deprecation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

asset_inventoryA
Read-only

[READ][risk=low] Actively fingerprint endpoints into an asset register.

Connects to each target with our own protocol client and reads its identity
call (S7 CPU info, EtherNet/IP controller info, OPC-UA server build info,
Modbus device identification FC43, Mitsubishi CPU type, MTConnect device
model), aggregating vendor/model/firmware/serial per device.

Honest scope: ACTIVE fingerprinting (we connect to each device), NOT passive
SPAN/tap discovery. Only finds devices we are configured to reach.

Args:
    endpoints: Endpoint names to fingerprint; omit to fingerprint ALL
        configured endpoints.

Returns dict: {asset_count, reachable_count, unreachable_count, method:
    'active_fingerprint', assets:[{endpoint, protocol, address, vendor, model,
    firmware, serial, reachable, last_seen, error}]}.

Example: asset_inventory(endpoints=["press1","cell5"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointsNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it connects to each target, reads identity calls, aggregates vendor/model/firmware/serial. No contradictions. It could mention rate limits or permissions, but current info is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a quick summary, then details about the method, scope, arguments, return value, and an example. Every sentence adds value and is efficiently written.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with one parameter, clear annotations, and no output schema, the description is very complete. It explains the return format in detail and provides an example, leaving little ambiguity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'endpoints' is clearly explained: it expects endpoint names, and omitting it fingerprints all configured endpoints. Schema description coverage is 0%, so the description fully compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'actively fingerprint endpoints into an asset register,' which is a specific verb-resource combination. This distinguishes it from protocol-specific siblings like profinet_asset_inventory, modbus_*, etc.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the scope as active fingerprinting only, not passive discovery, and that it only finds devices it can reach. It provides an example usage and indicates when to omit endpoints. However, it does not explicitly compare with sibling tools, though the context helps.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_checkA
Read-only

[READ][risk=low] Check recent local samples against the learned baseline.

Reads the last window_s seconds from ~/.iaiops/data.db (no device I/O) and
judges them against the stored band. Conservative by design: a violation is
reported ONLY when values are beyond p1/p99 by more than 3×MAD AND sustained
for >=3 consecutive samples — a single spike is never flagged. Every
violation cites the baseline window (from/to ts, n samples), the band
values, and the offending samples' timestamps/values. No stored baseline →
an explicit no_baseline answer (never a guess). Bounded output (<=10
violations, <=20 cited samples each).

Args:
    tag: Tag name to check, e.g. 'line1.temp'.
    endpoint: Only samples from this endpoint label.
    window_s: Recent window to check, seconds (60..604800; default 3600).

Returns dict: {status: 'ok'|'violation'|'no_baseline', tag, checked_samples,
    thresholds, baseline_citation, violations:[{direction, from_ts, to_ts,
    consecutive_samples, samples:[{ts,value}], baseline}], note}.

Example: baseline_check(tag="line1.temp", window_s=7200).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
endpointNo
window_sNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the detection algorithm (p1/p99, 3×MAD, consecutive samples), data source, bounded output, and no_baseline behavior. This adds significant context beyond annotations (readOnlyHint, destructiveHint), which are consistent (no contradiction).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a headline, behavioral paragraph, Args section, Returns dict, and example. It is front-loaded with purpose and every sentence is informative without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description details the return dict structure and handles edge cases (no baseline, bounded violations). Given the tool's complexity and existing annotations, the description is complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully explains each parameter: tag (example), endpoint (filtering), window_s (range and default). This adds meaning beyond the schema types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks recent local samples against a learned baseline, and distinguishes it from sibling baseline tools (e.g., baseline_learn, baseline_record_change) by focusing on checking. The verb 'check' and resource 'baseline' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the context (reads local data, no device I/O) and the conservative detection logic, but does not explicitly state when not to use or compare with alternatives. It implies usage for baseline checking but lacks exclusionary guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_check_in_contextA
Read-only

[READ][risk=low] Check readings against the band for ONE declared context.

A reading whose context was never learned comes back `unknown_context` and
stops there. It is **not** compared against the global band or the nearest
one, and that refusal is the entire point of the tool: borrowing a band turns
"we have never seen this regime" into "this regime is normal" — a silent
pass, in the direction nobody reports. The response lists the contexts that
do have bands so the gap is actionable.

Otherwise the usual conservative rules apply: a violation needs values beyond
the band by more than `margin_mad` × MAD AND sustained over `sustain_n`
consecutive samples, and every flag cites the baseline it was judged against.

Args:
    samples: [{ts, value, ...}] readings to check.
    contextual: A `baseline_learn_contextual` result.
    context: Which declared context these readings belong to.
    margin_mad: MAD margin beyond the band before flagging (default 3.0).
    sustain_n: Consecutive samples required (default 3 — no single-spike flags).

Returns dict (known context): the `baseline_check` shape plus {context,
    context_key}. (unknown): {status:"unknown_context", tag, context,
    known_contexts, checked_samples, reason, note}.

Example: baseline_check_in_context(samples=[...], contextual={...}, context="recipe-B").
ParametersJSON Schema
NameRequiredDescriptionDefault
contextYes
samplesYes
sustain_nNo
contextualYes
margin_madNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already flag read-only, but the description adds the crucial unknown_context refusal, the no-borrowing rule, margin_mad × MAD and sustain_n requirements, and the fact that flags cite their baseline. It also explains why the response lists known_contexts, making the tool's behavior genuinely predictable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every section earns its place: purpose, critical refusal behavior, rule thresholds, Args, return shapes, and an example. The risk tag and core action are front-loaded, and the structure is easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description fully specifies both known-context and unknown_context return shapes, plus example usage. An agent has enough to decide whether and how to invoke the tool correctly, including what happens for unlearned contexts.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description carries full responsibility and does so thoroughly: every parameter is explained, including the relationship between contextual and baseline_learn_contextual, the shape of samples, and the meaning/defaults of margin_mad and sustain_n. This far exceeds the bare schema titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb/resource and scope: 'Check readings against the band for ONE declared context.' It also draws an explicit contrast with uncontextual or nearest-band behavior, so an agent can distinguish it from baseline_check and other siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes clear this tool is for checking samples against one declared contextual band and expects a baseline_learn_contextual result, but it never names an alternative tool to use for global or non-contextual checks. That gives clear context without explicit exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_learnA
Read-only

[READ][risk=low] Learn a conservative per-tag normal band from local history.

Source is ~/.iaiops/data.db — the local store written by
historian_push(sink="sqlite") — NOT a live device read. Learns robust
percentiles (p1/p99 + median/MAD, no ML) from the tag's own samples,
segmented at the latest change recorded via baseline_record_change (the band
reflects only the post-change regime). REFUSES with an explicit
insufficient_data verdict (listing exactly what is missing) below 100 usable
samples or under 24h of span — it never invents a band from thin data. On
success the band is persisted to ~/.iaiops/baselines.json (owner-only local
metadata, not an OT write).

Args:
    tag: Tag name to learn, e.g. 'line1.temp'.
    endpoint: Only samples from this endpoint label.
    since: Only samples at/after this ISO-8601 time.

Returns dict: {status: 'ok'|'insufficient_data', tag, band:{p1,p99,median,mad},
    n_samples, window:{from_ts,to_ts,span_s}, segment, missing?:[...], note}.

Example: baseline_learn(tag="line1.temp", since="2026-06-01T00:00:00").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
sinceNo
endpointNo

TDQS

A3.9/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations set readOnlyHint=true, but description states the tool writes to ~/.iaiops/baselines.json. This is a direct contradiction, forcing a score of 1 per rubric. The description itself is transparent about the write side effect, but the inconsistency with annotations is serious.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections (risk, source, method, args, returns, example) and front-loads the READ tag. While slightly verbose, every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, but the description provides a detailed Returns dict with fields and refusal conditions. It also explains the data source, persistence, and relationship to baseline_record_change, making the tool's operational context complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description bears full burden. It explains all three parameters (tag, endpoint, since) with examples and semantics, adding significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Learn a conservative per-tag normal band from local history', using specific verb and resource. It distinguishes from siblings by noting the data source (~/.iaiops/data.db) and relationship to baseline_record_change, and clarifies it is not a live device read.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies when to use (learning a band) and explicitly states refusal conditions (<100 samples or <24h span). It does not mention alternatives to this tool but implies context via sibling relationships.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_learn_contextualA
Read-only

[READ][risk=low] Learn one conservative band per declared context, not one per tag.

One band per tag is wrong the moment a tag has more than one normal. A dryer
running recipe A at 180 °C and recipe B at 240 °C gets a band spanning both,
after which neither regime can go wrong — the band is too wide to catch a
real excursion and too mixed to mean anything. OT normal ranges move with
shift, product/recipe, and start-up versus steady state.

**The context is declared, never inferred** (D16). Each sample carries a
label under `context_key`; nothing here guesses which shift a timestamp falls
in or clusters values into regimes it then treats as real. Each context is
handed to the same learner as a global baseline, so it refuses on the same
terms — a thin context is left without a band rather than borrowing another
context's samples. Samples with no label are counted and named, not pooled
into a default bucket, because a default bucket is that same fallback.

Pass samples in (as with `spc_check` / `tag_health`). The local store's
`samples` table has no context column, so there is deliberately no
`iaiops baseline learn --context` yet; wiring one is a schema change and is
not done.

Args:
    samples: [{ts, value, quality?, tag?, <context_key>}] rows.
    tag: The tag being learned.
    context_key: Field that declares the context (default "context").
    min_samples: Per-context minimum before a band is learned (default 100).
    min_span_s: Per-context minimum history span in seconds (default 86400).

Returns dict: {tag, context_key, contexts:{label: learn_baseline result},
    learned_contexts, refused_contexts, uncontexted_samples, note}.

Example: baseline_learn_contextual(samples=[{"ts":"...","value":181.0,
    "context":"recipe-A"}], tag="dryer.temp").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
samplesYes
min_span_sNo
context_keyNocontext
min_samplesNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the readOnly/destructive annotations by explaining refusal behavior for thin contexts, counting rather than pooling uncontexted samples, and deliberately avoiding a default fallback bucket. It even discloses why there is no `--context` CLI wiring due to the local store schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is longer than typical but every paragraph carries meaningful design rationale or invocation detail, and it is well structured with Args, Returns, and an Example. The dryer example earns its place by clarifying the failure mode the tool avoids.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only learning tool with no output schema, the description provides the full return dict shape, parameter semantics, example call, and behavioral edge cases such as refused and uncontexted contexts. Nothing important is missing for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by documenting the sample row shape, `tag`, `context_key` as the declared-context field, `min_samples` as a per-context minimum, and `min_span_s` as a per-context history span with defaults. This gives the agent everything it needs beyond the raw JSON schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a precise verb and resource: 'Learn one conservative band per declared context, not one per tag.' The dryer example and contrast with per-tag learning make it clearly distinguishable from siblings like `baseline_learn`.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clearly describes when contextual baselines are needed: when a tag has multiple normal regimes due to shift, product/recipe, or start-up vs steady state. It also explains that contexts must be declared, not inferred, and shows how to pass samples, but it does not explicitly name the sibling alternative to use instead or provide an explicit when-not-to-use statement.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_record_changeA
Read-only

[READ][risk=low] Record an operator change-log entry for a tag (local only).

Writes ONLY local metadata (~/.iaiops/baselines.json, owner-only) — never an
OT device write, hence risk=low. A recorded change (setpoint moved, valve
replaced, probe swapped) marks a regime boundary: the next baseline_learn
uses only samples AFTER the latest change, so the band never mixes
pre-change and post-change behavior. This operator change log — not a
black-box score — is what makes the baseline trustworthy.

Args:
    tag: Tag whose process changed, e.g. 'line1.temp'.
    note: What changed (required), e.g. 'setpoint 60→70C'.

Returns dict: {tag, change:{ts, note}, changes_recorded}.

Example: baseline_record_change(tag="line1.temp", note="setpoint 60→70C").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
noteYes

TDQS

A4/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description states 'Writes ONLY local metadata', indicating a write side effect, but the annotations declare readOnlyHint=true, which contradicts this. The description adds useful behavioral context (local write, effect on baseline), but the contradiction forces a low score per guidelines.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a concise summary, behavioral explanation, structured Args/Returns/Example sections, and no wasted words. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (2 required params, no output schema), the description covers purpose, usage, parameters, return format, example, and impact on baseline learning. It is fully complete for an agent to select and invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully compensates by explaining both parameters in the Args section with examples. It defines tag as 'Tag whose process changed' and note as 'What changed', adding meaning beyond the schema's type and title.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool records an operator change-log entry for a tag, specifying the verb 'record' and the resource 'change-log entry'. It distinguishes itself from sibling tools like baseline_learn by explaining how recorded changes affect baseline learning.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool: to mark a regime boundary for baseline learning. It provides context that the next baseline_learn will only use samples after the latest change. While it does not explicitly state when not to use it, the example and explanation give clear guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

baseline_statusA
Read-only

[READ][risk=low] Baseline status for one tag, or a bounded listing of all.

Read from the local store only (no history scan, no device I/O) and never
guesses: 'no_baseline' (nothing learned, no refused attempt), 'learning'
(last learn refused — still accumulating history), 'ok' (band learned, last
check clean), 'violation' (last check flagged a sustained excursion). With
no tag, lists every tracked tag (bounded to 100 entries).

Args:
    tag: Optional tag name; omit to list all tracked tags.

Returns dict: {tag, status, band?, baseline_window?, changes_recorded?, ...}
    for one tag, or {tracked_tags, listed, truncated, tags:[...]} for all.

Example: baseline_status(tag="line1.temp").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds significant context beyond annotations: explains it reads from local store only, never guesses, and defines statuses. Contradicts no annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with summary, details, args, returns, and example. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a simple tool with one optional parameter and no output schema. Explains return structure and includes an example.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% coverage, but description fully explains the 'tag' parameter: optional, omit to list all tracked tags. Adds meaning beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it reads baseline status for one tag or lists all tracked tags. Specific verb 'Read' and resource 'baseline status'. Distinguishes from sibling tools like baseline_learn and baseline_check.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes when to use: for reading baseline status from local store only, no history or device I/O. Explains status values. Could be more explicit about when to choose this over other read tools but is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

changeover_analysisA
Read-only

[READ][risk=low] Changeover / SMED durations between products.

Breaks out what OEE availability only aggregates: each changeover is the gap
between the last good part of one product and the first good part of the next
— the setup/adjustment time SMED shrinks. Measures every changeover, ranks the
longest, and totals the lost time, worst-first, each duration cited by its two
bounding timestamps. Pure analysis over readings you pass in (a good-part
completion stream from the MES / PLC counters); read-only, advisory.

Args:
    good_parts: [{timestamp (ISO-8601), product}] — one per good part, any
        order (sorted by time). A changeover is recorded at each product change.

Returns dict: {good_parts, ignored, changeover_count, changeovers:[{from, to,
    start, end, durationS}], longest, avgDurationS, totalChangeoverS, note}.

Example: changeover_analysis(good_parts=[{"timestamp":"2026-07-12T08:00:00Z","product":"A"},
    {"timestamp":"2026-07-12T08:45:00Z","product":"B"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
good_partsYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it as readOnlyHint=true, and the description reinforces that it is 'read-only, advisory' and 'Pure analysis.' It explains the data requirement (good parts stream) and output structure. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

While well-structured with summary, args, returns, and example, the description is verbose. It includes repetitive phrases ('worst-first, each duration cited by its two bounding timestamps') that could be tightened. A 3 reflects adequate but not optimal conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one required parameter and no output schema, the description covers all necessary context: input format, output dict structure with example, and clarifying notes. It is fully sufficient for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description provides a detailed parameter description: 'good_parts: [{timestamp (ISO-8601), product}]' with ordering notes and an example. This fully compensates, making the parameter's semantics crystal clear.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it analyzes changeover/SMED durations between products. It explains what it measures (gap between last good part and first good part of next product) and how it relates to OEE. This distinct purpose makes it clear among sibling tools like oee_compute and downtime_events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description specifies it works on a 'good-part completion stream' and labels it 'read-only, advisory.' It contrasts with OEE availability aggregations. However, it does not explicitly state when not to use it or list alternatives, so it falls just short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compliance_dengbao_levelsA
Read-only

[READ][risk=low] 等保 2.0 二级 vs 三级 per-pillar deltas + honest iaiops posture.

等保 2.0 (GB/T 22239) is graded — the same control tightens as the level rises.
Per governance pillar this shows the 二级 baseline, what 三级 additionally requires,
and how far iaiops moves you toward it (with the honest per-control status/gap).
An onboarding/self-assessment aid, NOT a certification.

Args:
    level: Focus on one level — 'l2'/'l3', '二级'/'三级', or '2'/'3'. Omit for both.

Returns dict: {framework, levels:[{id,name,note}], selected_level, pillar_count,
    deltas:[{pillar, l2_requires?, l3_adds?, iaiops, iaiops_status, gap}], note}.

Example: compliance_dengbao_levels(level="三级").
ParametersJSON Schema
NameRequiredDescriptionDefault
levelNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive behavior. The description adds that it returns honest per-control status/gap, warns it is not a certification, and outlines the return dict structure. This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is verbose but well-structured: a concise heading, explanatory paragraph, parameter details, return dict, and example. Every sentence adds value, though could be slightly tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (compliance framework with pillars) and lack of output schema, the description provides a complete return dict structure, parameter options, and usage context. It covers all necessary information for an AI agent to use it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description fully explains the parameter 'level': accepted values ('l2'/'l3', '二级'/'三级', '2'/'3'), default behavior (omit for both), and an example. This adds complete meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it shows per-pillar deltas between 等保 2.0 level 2 and level 3, with honest iaiops posture. It distinguishes itself from sibling tools like compliance_frameworks or compliance_report by focusing on level comparison and self-assessment. The verb is implicit but clear.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates it is an onboarding/self-assessment aid, not a certification, suggesting use during compliance preparation. It does not explicitly list exclusions or alternatives but provides enough context to inform usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compliance_evidence_bundleA
Read-only

[READ][risk=low] Export the audit-evidence bundle (zip) for an auditor.

Packages the governance evidence trail into one deterministic zip:
audit_rows.jsonl (secrets already redacted upstream), chain_verification.json
(SHA-256 hash-chain walk result), rules.yaml (if present), doctor_summary.json
(non-probing config/secret-store facts), and manifest.json. Path is validated
(no '..' traversal; parent created 0700).

Args:
    out_path: Destination zip path (must end in .zip).
    since: Optional ISO-8601 floor on the audit row timestamp (inclusive).
    until: Optional ISO-8601 ceiling on the audit row timestamp (inclusive).

Returns dict: {path, row_count, chain{ok, checked, unhashed, ...}, files[],
    since, until}.

Example: compliance_evidence_bundle(out_path="/tmp/evidence.zip",
    since="2026-06-01T00:00:00+00:00").
ParametersJSON Schema
NameRequiredDescriptionDefault
sinceNo
untilNo
out_pathYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false. The description elaborates on behavior: non-destructive, deterministic zip creation, path validation (no '..' traversal), parent directory creation with 0700 permissions, and redacted secrets. This adds useful context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is structured with a clear purpose, a bullet-like list of package contents, parameter details, and an example. It is slightly verbose but front-loaded with the main action. Could be tightened slightly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description includes the return dict structure (path, row_count, chain, files, etc.). It covers all aspects needed for correct invocation: inputs, outputs, side effects (file creation), and an example. Comprehensive for a 3-parameter tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description fully compensates by defining each parameter: out_path must end in .zip, since and until are optional ISO-8601 timestamps. An example further clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool exports an audit-evidence bundle (zip) for auditors, listing included files and deterministic nature. It distinguishes itself from sibling tools like compliance_report or export_data by specifying the bundle's content and purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions it is for auditors with a READ risk level, indicating a safe read operation. While it doesn't explicitly state when not to use it or name alternatives, the context and sibling tools list imply it for compliance evidence gathering.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compliance_frameworksA
Read-only

[READ][risk=low] 跨框架对照: 防护指南 ↔ 等保 2.0 (GB/T 22239) ↔ IEC 62443.

One row per governance pillar, showing the matching 《工控系统网络安全防护指南》
requirement, 等保 2.0 control class, IEC 62443 foundational requirement, and the
current iaiops status. Companion to compliance_mapping (which carries the honest
per-control gap); use this to answer "which 等保 / 62443 clause does this satisfy".

Returns dict: {frameworks:[{id,name,region,kind}], framework_count, pillar_count,
    crosswalk:[{pillar, gjzn, dengbao, iec62443, iaiops_status}], note}.

Example: compliance_frameworks().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds value by specifying it is a read operation with [READ][risk=low] and detailing the return structure, including the dict format and the crosswalk array. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficient, with a clear opening line, second paragraph explaining usage, and an example. It could be slightly more concise but every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no parameters and no output schema, the description explains the return structure in detail, mentions companion tools, and gives an example. It is complete for a zero-parameter read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are no parameters, so schema coverage is 100%. The description adds value by providing an example call and explanation of the return value, meeting the baseline of 4 for zero-parameter tools.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is a cross-framework comparison tool for 防护指南, 等保 2.0, and IEC 62443. It distinguishes itself from sibling compliance_mapping by noting that compliance_mapping carries per-control gaps while this tool provides the crosswalk.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly tells when to use this tool: 'to answer which 等保 / 62443 clause does this satisfy' and frames it as a companion to compliance_mapping. It lacks an explicit 'when not to use' but provides sufficient context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compliance_mappingA
Read-only

[READ][risk=low] 《工控系统网络安全防护指南》 ↔ iaiops governance mapping.

An honest onboarding/sales self-assessment across the pillars 分区隔离 / 可审计 /
双向认证 / 最小权限 / 数据保护 / 自主可控. Each control names how iaiops addresses
it, an honest status (addressed / partial / 待核实), and the remaining gap.

Returns dict: {framework, frameworks[], pillars[], control_count, status_summary
    {addressed, partial, 待核实}, controls:[{pillar, requirement, iaiops, status,
    gap, crosswalk{dengbao, iec62443}}]}. See compliance_frameworks for the full
    cross-framework 对照.

Example: compliance_mapping().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false, so the safety profile is clear. The description adds value by detailing the return structure (dict with keys and example) and the pillars covered, without contradicting the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively concise, starting with a helpful risk label and including only necessary information. Some jargon (Chinese characters) may add clutter, but the structure is clear and example is provided, earning a 4.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description sufficiently explains the return format and provides an example. It references a sibling for more details. For a parameterless read-only tool, this is adequately complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so the description is not required to explain parameter semantics. According to guidelines, a baseline of 4 is appropriate, and the description does not introduce any misleading parameter information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool maps a specific Chinese industrial cybersecurity guide to iaiops governance, using a specific verb ('mapping') and resource. It distinguishes itself from sibling tools like compliance_frameworks by referencing that tool for full cross-framework comparisons, and the example call helps clarify its standalone usage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context for when to use this tool ('An honest onboarding/sales self-assessment') and references an alternative (compliance_frameworks) for broader framework views. However, it does not explicitly state when not to use it or provide exclusions for specific scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compliance_reportA
Read-only

[READ][risk=low] Render the 等保 2.0 / IEC 62443 compliance report (Markdown).

Turns the compliance crosswalk into a deliverable document a CISO can read:
title-page metadata (site / date / iaiops version), per-pillar 等保 L2/L3 status
table, IEC 62443 FR1–6 crosswalk, honest gap list, and a governance-controls
appendix (audit hash chain / approval tokens / dry-run+undo / mTLS). An
onboarding/self-assessment aid, NOT a certification.

Args:
    level: 等保 2.0 target level — 'l2'/'l3', '二级'/'三级', '2'/'3'. Omit for both.
    site: Site / plant name stamped on the title page.
    out_path: Optional file to write the markdown to (.md). Required when the
        report exceeds the inline bound (~400 lines): without it the inline
        markdown is truncated with a note.

Returns dict: {format, level, line_count, path?} plus either the full inline
    {markdown} (when within bounds and no out_path) or {markdown (truncated),
    truncated: true} with a hint to pass out_path.

Example: compliance_report(level="三级", site="示例水厂",
    out_path="/tmp/compliance-report.md").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
levelNo
out_pathNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

[READ] tag and annotations (readOnlyHint=true) consistently indicate read-only. Description further details truncation behavior, inline vs file output, and return format, providing full transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections for purpose, args, returns, and example. Slightly long but every sentence adds value; no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description covers return dict and behavior. With strong annotations and parameter details, the tool is fully understandable for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema coverage, description adds full parameter semantics: accepted values for level, purpose of site, and condition for out_path. Example clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description explicitly states it renders compliance reports for 等保 2.0 / IEC 62443 in Markdown, with clear verb+resource. Distinguishes from siblings by specifying it produces a deliverable document, unlike compliance_frameworks or compliance_mapping.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Describes use as an onboarding/self-assessment aid (NOT certification) and explains out_path requirement for large reports. Lacks explicit mention of alternative tools, but context is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

cross_protocol_asset_modelA
Read-only

[READ][risk=low] Fuse per-protocol tag feeds into ONE unified asset model.

Unifies the two per-protocol tag models (OPC-UA address-space discovery +
Modbus register templates) into one cross-protocol asset/tag/alias model. Tags
are re-classified with the SAME semantic classifier the OPC-UA layer uses,
grouped into assets ACROSS protocols (a ``Line1`` OPC-UA folder + a ``Line1``
Modbus block become one asset), and each gets a canonical alias
``<site>.<asset>.<class_or_name>``. Advisory only — aliases are SUGGESTIONS,
never a server-side rename (OT-dangerous).

Args:
    feeds: List of per-protocol feeds, each
        ``{protocol, source, asset?, tags:[...]}``. ``tags`` may be OPC-UA
        discovery descriptors (from opcua_discover_tags), Modbus template tags
        (from modbus_apply_template), or already-normalized tags. A feed-level
        ``asset`` is applied to its tags that don't carry their own.
    site: Site prefix for canonical aliases (default 'site').

Returns dict: {site, protocols, tag_count, asset_count, assets:[{asset,
    protocols, tag_count, classes, tags:[{protocol, source, name, ref, asset,
    unit, klass, canonical_alias, suggested_alias}]}], naming_quality:
    {alias_collisions, cross_protocol_overlaps, cryptic_names, verdict}}.

Example: cross_protocol_asset_model(feeds=[
    {"protocol":"opcua","source":"line1","tags":[...]},
    {"protocol":"modbus","source":"meter1","asset":"Line1","tags":[...]}],
    site="plant").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false. Description adds that it's advisory only, aliases are suggestions, and never performs server-side rename (OT-dangerous). This provides good context beyond annotations, but lacks details on error handling or rate limits.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections (Args, Returns, Example) and a front-loaded summary. It is slightly verbose but each sentence is informative and necessary for clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description details the return dict structure completely. It covers purpose, parameters, output, and an example, making it contextually complete for a tool with 2 parameters and complex behavior.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description thoroughly explains both parameters: 'feeds' with detailed object structure and 'site' with default. It adds significant meaning that is absent from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it fuses per-protocol tag feeds into a single cross-protocol asset model, distinguishing it from per-protocol tools like opcua_discover_tags and modbus_apply_template. It specifies actions like reclassification, grouping, and alias assignment.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when unifying multiple protocol feeds into a single asset model. It provides an example but does not explicitly state when not to use or list alternatives. However, the sibling tools context suggests per-protocol alternatives exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

data_quality_fleet_rollupA
Read-only

[READ][risk=low] Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality.

Builds on data_quality_scorecard to give a fleet-wide view: endpoints ranked by
their single worst tag, bad-quality tag counts aggregated across every endpoint,
and a first-class liveness rollup (dead-heartbeat / flatline). Staleness and gap
budgets are configurable per tag (staleness_s / gap_threshold_s) and per feed,
so a slow daily counter is not judged like a 1Hz sensor. Pure analysis.

Args:
    feeds: Per-endpoint feeds — {endpoint, staleness_s?, tags:[{ref, label?,
        samples:[scalars or {value, good|quality, timestamp?}], expected_update_s?,
        staleness_s?, gap_threshold_s?, flatline_after_s?, heartbeat?}]}.
    default_staleness_s: Fallback max sample-age (seconds) before 'stale' when a
        tag/feed sets no staleness_s/expected_update_s (default 300).
    now: ISO-8601 reference time for staleness (deterministic); omit for now-UTC.
    top_n: How many endpoints / bad-quality rows to return (default 10).

Returns dict: {evaluated_endpoints, evaluated_tags, fleet_score (0-100),
    fleet_status, endpoints_ranked_by_worst_tag:[...], bad_quality_rollup:
    {total_bad_quality_tags, endpoints_affected, by_endpoint:[{endpoint,
    bad_quality_tags, fully_bad, partial_bad}]}, liveness_rollup:
    {dead_heartbeat_count, flatline_count, dead_heartbeats[], flatlines[]},
    issue_breakdown{}}.

Example: data_quality_fleet_rollup(feeds=[{"endpoint":"line1","tags":[{"ref":"t",
    "samples":[{"value":None,"good":false}]}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
feedsYes
top_nNo
default_staleness_sNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false. The description adds that this is 'Pure analysis' and explains the deterministic behavior of the 'now' parameter. It also describes configurable thresholds, providing context beyond what annotations offer.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a one-line summary, Args section, Returns section, and Example. While it is relatively long, every part adds value. The Args section could be slightly more concise, but overall it is efficiently organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (nested parameters, no output schema), the description is complete. It details the return dictionary with all key fields (evaluated_endpoints, fleet_score, endpoints_ranked_by_worst_tag, bad_quality_rollup, liveness_rollup, issue_breakdown). It covers configuration and provides an example, ensuring the agent can understand and use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description compensates fully. Each parameter (feeds, default_staleness_s, now, top_n) is explained in detail in the Args section, including the nested structure of feeds and default behaviors. An example further clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear summary: 'Cross-endpoint fleet rollup of data-TRUST: worst tags + bad quality.' It specifies the verb (rollup), resource (fleet-level data quality), and scope (worst tags, bad quality). It also distinguishes itself from sibling tools like data_quality_scorecard, indicating it builds on that tool for a fleet-wide view.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains that it gives a fleet-wide view and builds on data_quality_scorecard. It mentions configurable staleness and gap budgets, indicating when to adjust parameters. However, it doesn't explicitly state when not to use this tool or list alternatives, missing some guidance for selecting between siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

data_quality_scorecardA
Read-only

[READ][risk=low] Fleet data-TRUST scorecard across endpoints' tag feeds.

Scores each tag 0-100 on whether its data can be BELIEVED — staleness, dead
heartbeat, bad-quality, flatline, gaps, anomaly — then rolls up per endpoint
and across the fleet. NOT process health (it does not score whether a value is
alarming, only whether it is trustworthy). Pure analysis over provided feeds.

Args:
    feeds: Per-endpoint feeds — {endpoint, tags:[{ref, label?, samples:[scalars
        or {value, good|quality, timestamp?}], expected_update_s?, heartbeat?}]}.
    default_staleness_s: Max sample-age before 'stale' when a tag sets no
        expected_update_s (default 300).
    now: ISO-8601 reference time for staleness (deterministic); omit for now-UTC.

Returns dict: {evaluated_endpoints, evaluated_tags, fleet_score (0-100),
    fleet_status, issue_breakdown{}, worst_endpoints[], worst_tags[],
    endpoints:[{endpoint, score, status, status_counts, worst_tag}]}.

Example: data_quality_scorecard(feeds=[{"endpoint":"line1","tags":[{"ref":"hb",
    "heartbeat":true,"samples":[5,5,5,5]}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
feedsYes
default_staleness_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive. The description adds details about the analysis nature, deterministic now, and the scoring factors (staleness, dead heartbeat, etc.). No contradiction with annotations; it enhances transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: first sentence states purpose, then details, then parameter definitions, return description, and an example. Every sentence adds value, and it is front-loaded with key information. No redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and absence of an output schema, the description adequately covers input parameters and return structure (dict with fields). An example is provided. It could be slightly more explicit about the return types, but it is sufficient for an agent to understand usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description's Args section fully explains all three parameters: feeds structure (endpoint/tags/samples), default_staleness_s meaning and default, and now as ISO-8601 reference time. This compensates comprehensively.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool evaluates data trustworthiness for each tag (0-100) and rolls up per endpoint and fleet. It explicitly contrasts with process health, providing a specific verb-resource pair and distinguishing from siblings like alarm tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use: for assessing data trustworthiness, not process health. It provides context but does not explicitly name alternative tools like tag_health or heartbeat_health. However, the clear purpose implicitly guides usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

device_advisory_checkA
Read-only

[READ][risk=low] Which scanned devices fall inside a mounted advisory's stated range.

`iaiops scan` already reads vendor / model / firmware / serial and then does
nothing with them. This closes that loop — and deliberately stops short of
where a vulnerability scanner would go.

**It reports that a device falls inside an advisory's stated range. Nothing
more.** Not "vulnerable", not "exploitable", no severity score. Whether a
published issue is reachable on a particular machine depends on
configuration, network position and compensating controls that a read-only
scan cannot see — and in OT most advisories against a protocol stack are not
findings at all, because the stack is not reachable from anywhere that
matters. A report full of red text that ignores that gets switched off by the
site, and then the real one is missed too.

**No database ships with this.** A bundled CVE feed is a maintenance
commitment this repo has not made, and a stale one that looks current is
worse than none — so the library is a file the site controls, which also
makes it work air-gapped. Every entry must carry a source, and one bad entry
refuses the whole file rather than half-mounting it.

Four verdicts, and the middle two are the point: `in_affected_range`,
`version_unknown` (model matches, no firmware read — neither a hit nor a
pass), `version_unparsed` (a firmware string it will not invent an ordering
for), `not_affected`. A device no advisory mentions is **absent** from the
findings, not reported clean: "nothing known" is not "nothing there".

Args:
    devices: [{ip?, vendor, model, firmware?}] — e.g. the `hosts` of a scan.
    library_path: Path to the advisory file (YAML or JSON) this site mounted;
        entries are {id, vendor, model, source, affected_below|affected_from|
        affected_versions, title?}.

Returns dict: {devices_checked, advisories_mounted, devices_with_findings,
    summary:{in_affected_range, version_unparsed, version_unknown,
    not_affected}, findings:[{ip, vendor, model, firmware, advisory_id, title,
    source, status, detail}], truncated, advisory_note, note}.

Example: device_advisory_check(devices=[{"ip":"10.0.0.5","vendor":"Siemens",
    "model":"S7-1500","firmware":"2.8.1"}], library_path="~/advisories.yaml").
ParametersJSON Schema
NameRequiredDescriptionDefault
devicesYes
library_pathYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, and the description aligns with them without contradicting them. It adds substantial behavior beyond annotations: four verdicts, the 'absent means nothing known' semantics, the strict library-file validation ('one bad entry refuses the whole file'), and the explicit refusal to infer vulnerability or severity.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long and includes a somewhat discursive OT-site anecdote, but the extra length is all relevant: it prevents misuse by over-eager agents. The structure is front-loaded with purpose, then warnings, verdicts, parameters, returns, and example, so an agent can stop after the first section if needed.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no output schema and 0% schema coverage, the description is unusually complete. It documents the exact return dict fields, the verdict semantics, the advisory library format, the absent-device behavior, the read-only safety profile, and usage prerequisites. No critical call-time information is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the full burden, and it delivers. It explains the shapes of `devices` and `library_path`, lists the advisory entry fields, enumerates the affected-range field options, and includes a concrete example call. Without this, the schema's minimal types would leave agents guessing.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line names a specific verb and resource: 'Which scanned devices fall inside a mounted advisory's stated range.' It also distinguishes itself from a vulnerability scanner by insisting it reports range membership only, not 'vulnerable' or 'exploitable'. This is clear and unique among the siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives clear usage context: it closes the loop after `iaiops scan` has read vendor/model/firmware/serial, and it deliberately stops short of vulnerability scanning. It does not name an explicit alternative sibling tool, but it provides enough context to know when this tool is appropriate and what it will not do.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diagnose_dataflowA
Read-only

[READ][risk=low] Localize a 'no data' break across an endpoint's reachable hops.

Probes connect → read(ref) → freshness → variance and returns a verdict with
per-hop detail and a recommended action. The #1 OT triage: distinguishes
"cannot connect" (network/PLC down) from "comms OK but value stale"
(upstream/field/source) from "good status but flatline" (sensor stuck).

Args:
    endpoint: Endpoint name from config (any protocol).
    ref: Tag/node/address/device to read (OPC-UA node id, Modbus address,
        S7 address string, MELSEC device). Omit to test connectivity only.
    freshness_threshold_s: Max value-age (seconds) before 'stale' (default 60).
    series: Optional injected samples (scalars or {value,timestamp}) for
        flatline/variance reasoning when a live historian is out of reach.
    flatline_eps: Spread at/below which a series counts as flatline.

Returns dict: {verdict ('cannot_connect'|'comms_ok_value_unreadable'|
    'comms_ok_bad_quality'|'comms_ok_value_stale'|'comms_ok_flatline'|
    'healthy'), diagnosis, recommended_action, hops:[{hop, ok, detail}]}.

Example: diagnose_dataflow(endpoint="line1", ref="ns=2;i=5", freshness_threshold_s=30).
ParametersJSON Schema
NameRequiredDescriptionDefault
refNo
seriesNo
endpointNo
flatline_epsNo
freshness_threshold_sNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint, destructiveHint false; description adds '[READ][risk=low]' and details the probing steps (connect, read, freshness, variance). Discloses verdict categories and recommended action, going well beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections, uses formatting, includes an example, and every sentence adds value. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no output schema, and no nested objects, the description covers all aspects: purpose, parameters, return value (including verdict enum and hop details), and an example. Complete and actionable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description explains every parameter in detail (e.g., ref can be various address types, series for injected samples, flatline_eps definition). Also provides an example call, fully compensating for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb and resource: 'Localize a 'no data' break across an endpoint's reachable hops.' It distinguishes between different failure modes and clearly differentiates from sibling tools by focusing on data flow triage.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says it's the '#1 OT triage' for no-data issues and explains when to use it (e.g., omit ref to test connectivity only). Provides clear context for selection among many diagnostic siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

diff_alias_mapA
Read-only

[READ][risk=low] Diff a fresh discovery run against the adopted baseline.

Loads the site's previously adopted alias map, re-runs the cross-protocol
asset model over ``feeds``, and reports how the address space moved: tags
added / removed / renamed (same ref, new alias) / reclassified (same ref+alias,
new semantic class), plus a stable|changed verdict. Adopt a baseline first
with ``adopt_alias_map``.

Args:
    feeds: Fresh per-protocol tag feeds (same shape as adopt_alias_map).
    site: Site label whose baseline to diff against. Default 'site'.

Returns dict: {site, verdict, counts:{added,removed,renamed,reclassified},
    added:[...], removed:[...], renamed:[...], reclassified:[...]}.

Example: diff_alias_map(feeds=[{"protocol":"opcua","source":"l1","tags":[...]}],
    site="plant").
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo
feedsYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, destructiveHint=false, aligning with the description's '[READ][risk=low]' tag. The description adds process details ('loads previous map, re-runs model, reports changes'), which goes beyond the annotations and provides useful behavioral context without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (overview, Args, Returns, Example), front-loaded with the core purpose. Every sentence adds value; no redundancy. It is appropriately sized for the complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description documents the return dict with keys and example values. It covers all necessary context: purpose, parameters, return format, prerequisite, and example usage. Complete for a read-only diff tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining both parameters: 'feeds' as per-protocol tag feeds with shape reference, and 'site' including its default value. This adds significant meaning beyond the minimally typed schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs ('diff', 'loads', 're-runs', 'reports') and clearly identifies the resource ('fresh discovery run against the adopted baseline'). It distinguishes itself from the sibling tool 'adopt_alias_map' by stating that adoption is a prerequisite.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly mentions the prerequisite ('Adopt a baseline first with adopt_alias_map') and provides an example. It implicitly tells when to use (after adoption) but does not explicitly state when not to use, though the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_attributionA
Read-only

[READ][risk=low] Which stoppage started it, and which ones were downstream of it.

RCA weights evidence by TIME alone — a signal before onset counts, one after
counts less. That is the honest half of the axis. Run `downtime_root_cause`
per asset after one upstream stop and every downstream machine comes back
with its own confident local root cause: each internally consistent, each
citing real signals, and all but one about a machine that stopped because it
was starved. The distinguishing fact is not in the evidence — it is the
line's topology.

Two rules decide an attribution and both must hold: the candidate must be
**declared upstream** of the asset, and it must have **stopped first**. An
upstream asset that stopped later cannot have caused an earlier stop, however
upstream it is.

Topology is declared, never inferred (D25). Co-occurrence on a production
line is guaranteed — everything stops together — so mining it for edges would
manufacture the causality this exists to remove. With no relations declared
every row comes back `not_evaluable` and the reason names the command that
fixes it. Assets the topology does not connect are left `unattributed` rather
than folded into the origin's column.

This ranks the stoppages; it does not diagnose the origin. Run
`downtime_root_cause` on the origin asset for that.

Args:
    stoppages: [{asset, start, end?}] for one incident window (ISO-8601).
    site: Which declared line topology to use (default "default").
    max_lead_s: A downstream stop is attributed only if it began within this
        many seconds of the upstream one (default 900).

Returns dict: {site, stoppages_evaluated, relations_declared, max_lead_s,
    verdict ('origin'|'multiple_origins'|'unattributed'|'not_evaluable'),
    origins, consequence_count, attributions:[{asset, start, status,
    origin_asset?, hops_upstream?, lead_s?, explains?, detail}], advisory}.

Example: downtime_attribution(stoppages=[{"asset":"filler","start":"2026-01-05T06:00:00Z"},
    {"asset":"capper","start":"2026-01-05T06:01:00Z"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNodefault
stoppagesYes
max_lead_sNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it readOnly and non-destructive, and the description adds substantial behavioral detail beyond that: evidence is weighted by time alone, topology is declared never inferred, co-occurrence is deliberately not mined, unconnected assets are left unattributed, and the tool ranks rather than diagnoses. No contradiction exists between description and annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but earns its length: the motivating RCA example explains why topology matters, the two rules are crisp, and the Args/Returns/Example block is cleanly organized and front-loaded with purpose and risk. No sentence is redundant; the vivid explanatory paragraph clarifies behavior rather than padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description thoroughly documents the return dict, edge-case statuses like not_evaluable and unattributed, and the exact effect of missing topology declarations. It also gives an example call. This is complete enough for an agent to select and invoke the tool correctly without additional context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description fully compensates: it defines stoppages as [{asset, start, end?}] for one ISO-8601 incident window, explains site as the declared line topology with default 'default', and specifies max_lead_s as the downstream attribution window with default 900. It also documents the return dictionary structure and provides a concrete example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a clear question that defines the tool's role — identifying which stoppage started an incident and which were downstream — and later states 'This ranks the stoppages; it does not diagnose the origin,' drawing a crisp boundary against downtime_root_cause. It names the specific resource (stoppages) and action (attribution/ranking), making it easy for an agent to distinguish from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly routes between this tool and downtime_root_cause: 'Run downtime_root_cause on the origin asset for that' and explains the failure mode when no relations are declared, including that the reason names the fixing command. It also states both rules that must hold, so an agent knows exactly when a candidate qualifies.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_eventsA
Read-only

[READ][risk=low] Detect running→stopped transitions and categorize stoppages.

Args:
    series: Timestamped samples — {timestamp (ISO-8601), state} where state is
        a string (RUNNING/IDLE/FAULT…), a bool, or a number.
    category_map: Optional {state_label: category} override (else keyword
        heuristics map to changeover/material/mechanical/quality/break/unknown).
    min_duration_s: Ignore stoppages shorter than this (seconds).

Returns dict: {samples, event_count, total_downtime_s, by_category:{cat:
    {count, downtime_s}}, events:[{start, end, duration_s, state, category}]}.

Example: downtime_events(series=[{"timestamp":"2026-06-28T08:00:00Z","state":"RUNNING"},
    {"timestamp":"2026-06-28T08:05:00Z","state":"FAULT"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
category_mapNo
min_duration_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant behavioral context beyond annotations: it declares risk level ([READ][risk=low]), explains categorization heuristics, the min_duration_s filtering, and the full return structure. No contradictions with annotations (readOnlyHint, openWorldHint, destructiveHint).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with summary, args, returns, and an example. It is slightly verbose, particularly the example, but every sentence is informative. It could be more front-loaded, but overall effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of the tool (3 parameters, no output schema), the description covers all necessary aspects: input format, optional overrides, threshold behavior, and the complete return structure. It provides enough detail for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description fully compensates by explaining each parameter in detail: series format, category_map override logic, and min_duration_s purpose. This adds substantial meaning beyond the schema structure.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool detects 'running→stopped transitions' and categorizes stoppages, using a specific verb and resource. It distinguishes itself from sibling tools like 'downtime_root_cause' or 'downtime_triage' by focusing on the detection and categorization step.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for use via the Args section, detailing the required series input. However, it does not explicitly state when not to use this tool or name alternative tools for different purposes (e.g., root cause analysis).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_root_causeA
Read-only

[READ][risk=low] AI downtime root-cause copilot — cited verdict, ADVISORY only.

Correlates whatever evidence you supply around a downtime/incident window —
alarm events, tag samples, a diagnose_dataflow verdict, a machine-state series —
ranks candidate root causes, and cites the REAL signals behind each. Read-first:
it proposes a human-approved, undoable (MOC-gated) action but executes nothing.
Anti-hallucination: only signals present in the input are cited; thin evidence
downgrades to 'insufficient_evidence' with a 'recommended_next_data' list rather
than a confident guess. Confidence combines independent, time-correlated evidence
(signals BEFORE onset outweigh signals during it).

Args:
    window: {start (ISO-8601), end? (ISO-8601), asset?, category?}. If 'end' is
        omitted but state_series is given, the first running→stopped span bounds it.
    alarms: Alarm/condition events — {source, timestamp, message?, priority?, state?}.
    tags: Per-tag samples — {ref, samples:[scalars or {value, good|quality}],
        warn_high?, alarm_high?, ...} (scored via tag_health).
    dataflow: A diagnose_dataflow result dict (its 'verdict' localizes comms vs field).
    state_series: {timestamp, state} samples to bound the window if 'end' is absent.
    lead_window_s: How far before onset a signal may sit and still count as a cause
        (default 300s); signals after onset are treated as consequences.
    cause_weights: Optional per-site {cause: multiplier} override (e.g. from
        learn_cause_weights) — scales each cause's evidence (1.0 = neutral
        default) before the noisy-OR. Unknown causes / non-numeric weights are
        rejected; values are clamped. Omit for the shipped default weighting.
    include_graph: When true, also return a 'graph' block — the SAME verdict
        re-projected as a causal graph {nodes, edges, mermaid, meta} (signal →
        cause → downtime) for a frontend/Grafana. Pure re-shape: signal→cause
        edge weights are the evidence contribution scores, cause→symptom edge
        weights are the hypothesis confidences — no new reasoning. Omit for the
        flat verdict only (default).

When a per-site 'historian:' block is configured (~/.iaiops/config.yaml, A7),
the 2h pre-incident window is additionally pulled from that reader and scored
as historian trend evidence — cited with its source ('historian:<name>'),
window, and sample count. Without the config, behaviour is unchanged.

Returns dict: {window, verdict ('root_cause_identified'|'multiple_candidates'|
    'insufficient_evidence'), primary_cause, hypotheses:[{cause, confidence (0..1),
    confidence_band, evidence:[{signal, ref, at?, lead_time_s?, detail, weight}],
    recommended_action}], evidence_summary, recommended_next_data?,
    anti_hallucination, graph? (when include_graph): {nodes:[{id, kind
    (signal|cause|symptom), label, score, ...}], edges:[{from, to, weight,
    relation (supports|attributed_to)}], mermaid, meta}}.

Example: downtime_root_cause(window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
    alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:50Z",
             "message":"motor overload trip"}], dataflow={"verdict":"healthy"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNo
alarmsNo
windowYes
dataflowNo
state_seriesNo
cause_weightsNo
include_graphNo
lead_window_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description goes beyond by detailing anti-hallucination behavior, confidence combining, the advisory nature, and the historian config integration. It also mentions that actions are 'human-approved, undoable (MOC-gated)'. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured, with clear sections and a bold opening statement. It uses formatting to separate parameter details and return value. While some redundancy exists (e.g., repeating keywords), the complexity of the tool justifies the length. Minor improvements could improve conciseness without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 8 parameters, 6 optional inputs, nested objects, no output schema, and a large sibling context, the description covers all aspects comprehensively. It explains return value in detail, includes an example, and describes edge cases (historian config, cause_weights validation, include_graph behavior). The anti-hallucination and confidence logic are also detailed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full burden for parameter semantics. It provides extensive explanations for each parameter, including window format, alarms, tags, dataflow, state_series, lead_window_s, cause_weights, and include_graph. The example further clarifies usage. This far exceeds minimal schema information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is an AI downtime root-cause copilot, read-only and advisory. It specifies it correlates evidence, ranks candidates, and cites real signals. The '[READ][risk=low]' prefix and 'ADVISORY only' make the purpose unambiguous, and it distinguishes from siblings like 'downtime_root_cause_live' by focusing on historical evidence analysis.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when you have evidence around a downtime window and need a cited verdict. It mentions it is read-only and advisory, but does not explicitly contrast with similar sibling tools like 'downtime_triage' or 'downtime_root_cause_live'. However, the detailed parameter descriptions and example provide enough context for appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_root_cause_liveA
Read-only

[READ][risk=low] AI downtime RCA copilot that GATHERS its own live evidence.

Same advisory, read-only, evidence-cited contract as downtime_root_cause — but
instead of hand-injecting evidence you give an endpoint + incident window and it
pulls the evidence itself: a cross-protocol diagnose_dataflow probe, a short
sampled series per ref (so flatline/bad-quality/anomaly surface via tag_health),
and active OPC-UA conditions. Light read load; non-destructive; nothing executed.
The gathered bundle is echoed under 'collected_evidence' (no hidden inputs).

Args:
    endpoint: Endpoint name from config (any protocol). Omit for the default.
    window: {start (ISO-8601), end?, asset?, category?, freshness_threshold_s?}.
    refs: Tags/nodes/addresses to sample for this incident (first is also the
        diagnose_dataflow target). Capped at 20.
    sample_count: Reads per ref to build its series (1..60, default 8).
    interval_ms: Delay between reads (>=50ms, default 200).
    include_alarms: Surface active OPC-UA conditions as alarm evidence (OPC-UA only).
    lead_window_s: Causal lead window before onset (default 300s).
    include_graph: When true, also return the 'graph' block (same {nodes, edges,
        mermaid, meta} causal-graph re-projection as downtime_root_cause). Pure
        re-shape of the verdict; no new reasoning. Omit for the flat verdict.

Returns dict: same shape as downtime_root_cause plus 'collected_evidence'
    {endpoint, protocol, refs_sampled, alarms_found, dataflow_verdict}.

Example: downtime_root_cause_live(endpoint="line1",
    window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
    refs=["ns=2;i=5","ns=2;i=6"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
refsNo
windowNo
endpointNo
interval_msNo
sample_countNo
include_graphNo
lead_window_sNo
include_alarmsNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds significant detail: 'Light read load; non-destructive; nothing executed', 'gathered bundle echoed under collected_evidence (no hidden inputs)', and explains the probe types. This far exceeds the annotation baseline and provides complete behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a header, explanatory paragraph, bulleted list, return shape, and example. While slightly lengthy, every sentence adds value and the key information is front-loaded. Minor redundancy could be trimmed, but overall effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (8 params, no output schema), the description covers the return dict shape, parameter roles, and an example. It lacks full details on window subfields and error handling, but provides enough for correct invocation. The contrast with sibling and safety notes add completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description fully compensates by detailing all 8 parameters with types, defaults, and constraints (e.g., refs capped at 20, interval_ms >=50ms). Each parameter has clear meaning and purpose, making the schema's lack of descriptions irrelevant.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool is an 'AI downtime RCA copilot that GATHERS its own live evidence', with a specific verb (gathers) and resource (root cause analysis). It explicitly contrasts with the sibling tool downtime_root_cause by noting the evidence-gathering method, making its purpose distinct.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear guidance: use this tool when you have an endpoint and want automatic evidence gathering, as opposed to hand-injecting evidence. It names the alternative downtime_root_cause. However, it does not explicitly state when not to use it, leaving some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

downtime_triageA
Read-only

[READ][risk=low] One-call downtime triage: first-look alarm + RCA cause + precursors.

Answers the operator's three simultaneous questions on a stopped line — which
alarm to look at first, the likely cause, and whether anything warned us —
then cross-checks whether the first-out alarm agrees with the RCA verdict.
Composes alarm_cascade + downtime_root_cause + pdm_forecast over ONE incident;
every field traces to a sub-report echoed under 'cascade'/'rca'/
'precursor_forecasts'. Read-first and advisory: it proposes but executes
nothing. Thin evidence downgrades honestly rather than guessing.

Args:
    window: {start (ISO-8601), end?, asset?, category?}. If 'end' is omitted
        but state_series is given, the first running→stopped span bounds it.
    alarms: Alarm/condition events — {source, timestamp, message?, priority?,
        state?}. Feeds BOTH the first-out cascade and the RCA.
    tags: Per-tag samples — {ref, samples:[...], warn_high?, ...} (via tag_health).
    dataflow: A diagnose_dataflow result dict (localizes comms vs field).
    state_series: {timestamp, state} samples to bound the window if 'end' is absent.
    precursors: Signals to check for a pre-incident trend — [{signal, series:
        [scalars or {value, timestamp}], warn_high?, alarm_high?, warn_low?,
        alarm_low?}]; each is run through pdm_forecast and kept only when it was
        degrading/imminent before the trip.
    cascade_window_s: Quiet gap (s) separating alarm cascades (default 60).
    lead_window_s: Causal lead window before onset (default 300s).
    cause_weights: Optional per-site {cause: multiplier} RCA override.
    imminent_within_s: ETA horizon that marks a precursor 'imminent' (default 24h).
    include_graph: When true, the echoed 'rca' sub-report also carries a 'graph'
        block — the SAME verdict re-projected as a causal graph {nodes, edges,
        mermaid, meta} (signal → cause → downtime) for a frontend. Pure re-shape;
        no new reasoning. Omit to keep the flat rca summary (default).

Returns dict: {window, triage:{first_look:{source, ts, cascade_size, basis},
    likely_cause:{cause, verdict, confidence, confidence_band,
    recommended_action}, cross_check:{status ('corroborated'|'diverging'|
    'no_alarm_root'|'no_rca_primary'), detail}, precursors_missed:[{signal,
    status, direction, eta_to_limit, unit, limit}], recommended_next_data},
    cascade:{...}, rca:{verdict, primary_cause, top_hypotheses, graph?},
    precursor_forecasts:[...], anti_hallucination}.

Example: downtime_triage(window={"start":"2026-06-28T10:00:00Z","asset":"line1"},
    alarms=[{"source":"M1_DRIVE","timestamp":"2026-06-28T09:59:50Z",
             "message":"motor overload trip"}],
    precursors=[{"signal":"M1_temp","series":[...],"warn_high":80}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsNo
alarmsNo
windowYes
dataflowNo
precursorsNo
state_seriesNo
cause_weightsNo
include_graphNo
lead_window_sNo
cascade_window_sNo
imminent_within_sNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false, and the description reinforces this by stating it 'proposes but executes nothing.' It adds context about evidence handling (downgrading on thin evidence) and cross-checking (first-out vs RCA). No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured: summary, parameter details, return format, example. It is front-loaded with the core purpose. While every section is informative, some minor redundancy exists (e.g., repeating 'Read-first' in both summary and args). Still efficient for a complex tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 11 parameters, no output schema, and nested objects, the description comprehensively covers inputs, outputs (return dict structure with sub-reports), and example usage. It addresses edge cases like missing 'end' window and optional graph output. This fully equips the agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full burden. The 'Args' section explains each parameter's structure, purpose, and defaults in detail (e.g., window bounds, alarms events, precursor signals). This adds significant semantic meaning beyond the bare schema types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs 'One-call downtime triage: first-look alarm + RCA cause + precursors' and explains it composes alarm_cascade, downtime_root_cause, and pdm_forecast. This distinguishes it from sibling tools like alarm_cascade or downtime_root_cause individually.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says 'Read-first and advisory: it proposes but executes nothing' and 'Thin evidence downgrades honestly rather than guessing.' It implies usage for initial triage, but lacks explicit when-to-use vs alternatives. However, the context of sibling tools and the tool's purpose makes it reasonably clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eip_controller_infoA
Read-only

[READ][risk=low] Controller identity (proves the CIP link).

Args:
    endpoint: Endpoint name from config (protocol 'ethernetip'/'eip'); omit for default.
    plctype: Driver selector override — 'logix' (default), 'slc' (PLC-5/SLC-500/
        MicroLogix, PCCC), or 'micro800'. Omit to use the endpoint's configured plctype.

Returns dict: {endpoint, host, slot, plctype, controller, info_error}. For
    logix/micro800 controller carries {vendor, product_type, revision, serial,
    product_name, name, ...}; for slc it carries {processor_type}.

Example: eip_controller_info(endpoint="slc05", plctype="slc").
ParametersJSON Schema
NameRequiredDescriptionDefault
plctypeNo
endpointNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral context beyond annotations by detailing return structure for different plctypes, the presence of info_error, and risk level. It fully discloses what the tool does and its outputs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a header, arguments, returns, and an example. Every sentence adds value, and it is appropriately sized without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of output schema and 0% schema coverage, the description is complete: it explains all parameters, return fields for different plctypes, and provides an example.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates by fully explaining both parameters: endpoint (from config, default option) and plctype (override with possible values and default). This adds essential meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool retrieves controller identity to prove the CIP link. It distinguishes itself from sibling tools like eip_read_tag or eip_list_tags by focusing on identity rather than tag operations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading controller identity but does not explicitly state when to use this tool versus alternatives. No direct comparison or exclusion criteria are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eip_list_tagsA
Read-only

[READ][risk=low] Discover the controller's tags (Logix) or PCCC data files (SLC).

Logix/Micro800: enumerate the controller's symbol table without prior
knowledge (program-scoped tags appear as 'Program:<prog>.<tag>'). SLC/PCCC has
no symbol table, so the data-file directory (N7/B3/F8/... with element counts)
is returned instead.

Args:
    endpoint: Endpoint name from config.
    plctype: Driver selector override — 'logix' (default), 'slc', or 'micro800'.

Returns dict: logix → {endpoint, plctype, tag_count, tags:[{name, data_type,
    tag_type, structure, dimensions}]}; slc → {endpoint, plctype, file_count,
    files:[{file, elements, length}], directory_error, note}.

Example: eip_list_tags(endpoint="cell5"); eip_list_tags(endpoint="slc05", plctype="slc").
ParametersJSON Schema
NameRequiredDescriptionDefault
plctypeNo
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description details divergent behaviors for Logix (symbol table) and SLC (data-file directory), mentions program-scoped tag notation, and outlines return structure, adding significant context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized, starting with a clear one-liner, then explaining PLC-specific behavior, parameter docs, return format, and examples, without unnecessary verbosity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite lacking an output schema, the description provides detailed return structures for both PLC types and example calls, covering most relevant aspects for a list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema coverage at 0%, the description compensates by explaining endpoint and plctype parameters, including defaults and allowed values (logix, slc, micro800), adding meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists tags or PCCC data files, distinguishes between Logix/Micro800 and SLC/PCCC behaviors, and differentiates from sibling tools like eip_read_tag and eip_read_many.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly indicates use for discovery, but does not explicitly state when to use vs alternatives or provide exclusions. It lacks direct guidance on selecting this tool over others.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eip_read_manyA
Read-only

[READ][risk=low] Batch-read many tags/addresses in one request.

Args:
    tags: Logix tag names (["Speed", "Temp", "Array[0]"]) OR SLC/PCCC
        data-table addresses (["N7:0", "F8:0", "B3:0/0"]).
    endpoint: Endpoint name from config.
    plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.

Returns dict: {endpoint, plctype, count, items:[{tag, value, type, error, good}]}.

Example: eip_read_many(tags=["Speed","Temp"], endpoint="cell5");
    eip_read_many(tags=["N7:0","F8:0"], endpoint="slc05", plctype="slc").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsYes
plctypeNo
endpointNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description includes '[READ][risk=low]' upfront, aligning with annotations (readOnlyHint=true, destructiveHint=false). It details the return format (dict with endpoint, plctype, count, items) and explains the meaning of each parameter. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, using a clear docstring structure. It front-loads key information (READ, risk low) and provides an example. Every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (3 parameters, no output schema), the description is complete: it explains parameters, return format, and usage examples. It sufficiently covers what the agent needs to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully explains all three parameters: tags (with examples of Logix and PCCC formats), plctype (driver selector with enumerated values), and endpoint (name from config). This adds essential meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool is for batch-reading many tags/addresses in one request, specifying both Logix and SLC/PCCC address types. It includes a structured format with Args, Returns, and Example, making the purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for batch reads with 'Batch-read many tags/addresses in one request,' but does not explicitly state when to use this tool versus single-read alternatives like eip_read_tag. The example provides practical guidance, and sibling context partly fills the gap.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eip_read_tagA
Read-only

[READ][risk=low] Read one tag/address with its type.

Args:
    tag: Logix tag ('Conveyor.Speed', 'Array[3]', 'Program:Main.X') OR an
        SLC/PCCC data-table address ('N7:0' int, 'B3:0/0' bit, 'F8:0' float,
        'T4:0.ACC', 'N7:0{10}' slice).
    endpoint: Endpoint name from config.
    plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.

Returns dict: {endpoint, plctype, tag, value, type, error, good}.

Example: eip_read_tag(tag="Conveyor.Speed", endpoint="cell5");
    eip_read_tag(tag="N7:0", endpoint="slc05", plctype="slc").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
plctypeNo
endpointNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations (readOnlyHint=true, destructiveHint=false) align with the description. The description adds detail on the tag format, endpoint, driver override, and return dict structure, fully disclosing behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with header, Args, Returns, and Example. Each sentence is informative and concise, with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description explains the return dict and provides examples, making the tool's usage complete and understandable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All three parameters (tag, endpoint, plctype) are clearly explained with examples and allowed values, even though schema coverage is 0%. Tag format includes Logix and SLC variants.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Read one tag/address with its type', specifying the action and resource. It distinguishes from sibling tools like eip_write_tag and eip_read_many.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies single-tag/address reading but does not explicitly state when to prefer this over other read tools (e.g., modbus_read_holding) or which protocols it supports beyond Logix/SLC/Micro800.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

eip_write_tagA
Destructive

[WRITE][risk=HIGH][MOC] Write ONE value to a tag/data-table address (off by default).

OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE
value (read-back) and records an undo descriptor so the change is reversible.
Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.

Args:
    tag: Logix tag name OR SLC/PCCC data-table address ('N7:0', 'F8:0', 'B3:0/0').
    value: Value to write (pycomm3 coerces to the tag's CIP/PCCC type).
    endpoint: Endpoint name from config.
    plctype: Driver selector override — 'logix' (default), 'slc' (PCCC), or 'micro800'.
    dry_run: When True (default) returns a preview without writing.

Returns dict: dry-run → {tag, plctype, dry_run:true, before, would_write, note};
    applied → {tag, plctype, dry_run:false, before, written, applied:true, _undo_id}.

Example (preview): eip_write_tag(tag="Setpoint", value=42, endpoint="cell5").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
valueYes
dry_runNo
plctypeNo
endpointNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=false, destructiveHint=true), the description reveals: the tool is destructive by default unless dry_run is used; it captures the BEFORE value and creates an undo descriptor; it requires an approver for actual writes. This adds critical behavioral context that is not present in annotations alone, especially for a high-risk operation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with Args, Returns, and Example sections, and it is front-loaded with a compact header. While it is long, every sentence serves a purpose—safety warnings, parameter details, return schemas. Minor suggestion: the Chinese line could be omitted without loss of clarity for English readers, but it does not detract significantly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (industrial write with high risk, no output schema, 5 parameters), the description covers purpose, safety, parameter semantics, return behavior (dry-run vs applied), and an example. It addresses all likely questions an AI agent would need to use the tool correctly and safely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates fully: it explains each parameter (tag: format examples, value: pycomm3 coercion, endpoint, plctype: valid values 'logix'/'slc'/'micro800', dry_run: behavior). This provides all necessary semantic information that the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear verb-resource pair: 'Write ONE value to a tag/data-table address.' It specifies the scope (one value) and resource type, and the header '[WRITE][risk=HIGH][MOC]' immediately conveys the action and risk. The tool's name 'eip_write_tag' aligns perfectly with the description, and it is distinct from siblings like 'eip_read_tag' and 'eip_read_many'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states that by default dry_run=True (no writing), and that to actually write, one must set dry_run=False and record an approver. It includes a Chinese safety warning and 'OT-DANGEROUS' label. While it does not compare to alternative tools, the guidance on when to apply (and the safety precautions) is clear and sufficient for safe usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_master_stateA
Read-only

[READ][risk=low] Open the master on the configured NIC; report bus state.

Needs Linux + root/CAP_NET_RAW + a dedicated NIC + real slaves (pysoem extra).
Degrades to a teaching error dict if pysoem/permission/NIC/bus is missing.

Args:
    endpoint: Endpoint name from config (protocol 'ethercat'); omit for default.

Returns dict: {endpoint, nic, master_state (INIT/PREOP/SAFEOP/OP/...),
    expected_working_counter, slaves_found, slaves_expected, slave_count_ok}.

Example: ethercat_master_state(endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. The description adds context about resource requirements and failure modes, which annotations do not cover. There is no contradiction; 'Open' refers to establishing a connection, not modifying data.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured, starting with a bold summary, then requirements, parameter info, return format, and an example. Every sentence provides necessary information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one optional parameter and no output schema, the description covers purpose, prerequisites, behavior, parameter, return value, and an example. It is fully self-contained.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description compensates by explaining the parameter 'endpoint' as 'Endpoint name from config (protocol 'ethercat'); omit for default.' This adds meaning beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action: 'Open the master on the configured NIC; report bus state.' It specifies a verb ('Open','report') and resource ('master on configured NIC'), and distinguishes from sibling tools like 'ethercat_slaves' by focusing on master state.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit prerequisites: 'Needs Linux + root/CAP_NET_RAW + a dedicated NIC + real slaves (pysoem extra).' It also describes degradation behavior: 'Degrades to a teaching error dict if pysoem/permission/NIC/bus is missing.' It does not explicitly contrast with alternatives but gives clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_read_pdoA
Read-only

[READ][risk=low] One cyclic snapshot of a slave's input process-data image.

Does a single send/receive cycle (never loops) and returns the input image.

Args:
    slave: Zero-based slave index.
    endpoint: Endpoint name from config.

Returns dict: {endpoint, slave, working_counter, input_byte_length, input_hex,
    output_byte_length}.

Example: ethercat_read_pdo(slave=0, endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
slaveYes
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it does a single cycle (never loops), which is informative beyond annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise with clear sections: header, functionality, args, returns, and example. No unnecessary words, well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, behavior (single cycle), arguments, and return fields despite no output schema. Lacks error handling but overall sufficient for a read-only tool with good annotations.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description explains each parameter: slave as zero-based index and endpoint from config. This adds meaning beyond type info, though it omits default values or constraints.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it reads one cyclic snapshot of a slave's input process-data image with a single send/receive cycle. This distinguishes it from siblings like ethercat_read_sdo (SDO) or ethercat_slave_info (general info).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides an example usage but does not explicitly state when to use this tool versus alternatives like ethercat_read_sdo or when not to use it. Context is clear but lacks exclusion guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_read_sdoA
Read-only

[READ][risk=low] CoE SDO upload: read one object-dictionary entry (acyclic).

Args:
    slave: Zero-based slave index.
    index: CoE object index (decimal, e.g. 0x1018 → 4120).
    subindex: Sub-index (default 0).
    size: Expected byte size (0 = let SOEM size it).
    endpoint: Endpoint name from config.

Returns dict: {endpoint, slave, index, subindex, byte_length, hex, as_uint}.

Example: ethercat_read_sdo(slave=0, index=0x1018, subindex=1, endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
sizeNo
indexYes
slaveYes
endpointNo
subindexNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false; the description adds value by noting 'risk=low', acyclic nature, and specifying the return dictionary format (endpoint, slave, index, subindex, byte_length, hex, as_uint), without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with only 6 lines, front-loaded with a [READ] tag and risk level, and includes an example. No redundant sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an acyclic read tool with 5 parameters and no output schema, the description covers purpose, parameters, and return value structure. It is sufficient to use the tool correctly without needing additional context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%; the description explains all 5 parameters in the Args section with details such as slave index being zero-based, index being decimal (e.g., 0x1018 → 4120), and size default behavior (0 = let SOEM size it), which the schema does not provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states '[READ] CoE SDO upload: read one object-dictionary entry (acyclic)', specifying the verb (read) and resource (object-dictionary entry), and distinguishes from siblings like ethercat_write_sdo and ethercat_read_pdo.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for acyclic reads via CoE SDO, but does not explicitly state when to use this tool versus alternatives like ethercat_read_pdo or ethercat_write_sdo, or provide exclusion criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_set_stateA
Destructive

[WRITE][risk=HIGH][MOC] Request an AL-state transition (off by default).

OT-DANGEROUS: moving to/from OP can START or STOP machine motion. Defaults to
dry_run=True. ``slave`` < 0 applies to the master (all slaves). Captures the
CURRENT state for undo. Set dry_run=False AND record an approver to apply.
未经授权勿对生产控制系统写入.

Args:
    state: Target AL-state: INIT | PREOP | SAFEOP | OP (or a numeric code).
    slave: Zero-based slave index, or -1 (default) for the whole master.
    endpoint: Endpoint name from config.
    dry_run: When True (default) returns a preview without changing state.

Returns dict: dry-run → {scope, dry_run:true, before, would_request, note};
    applied → {scope, dry_run:false, before, requested, reached, applied:true}.

Example (preview): ethercat_set_state(state="OP", slave=0, endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
slaveNo
stateYes
dry_runNo
endpointNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses write nature, high risk, destructive hint, dry-run behavior, scope option, and current state capture. Complements annotations (readOnlyHint=false, destructiveHint=true) with additional context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with sections for warning, behavior, args, returns, and example. No redundant sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description fully explains return dict for dry-run and applied cases. Covers edge cases like slave=-1 and default dry_run=True. Complete for a high-risk tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All four parameters are described with meaning and acceptable values (state: target AL-state; slave: zero-based or -1; endpoint: from config; dry_run: preview vs apply). Schema coverage 0% but description fully compensates.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it requests an AL-state transition for EtherCAT, specific states listed, and distinguishes from sibling tools like ethercat_slaves or ethercat_read_sdo by being a write operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly warns about risk of starting/stopping machine motion, defaults to dry_run, instructs to set dry_run=false and record approver for apply. Does not mention alternative tools for same operation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_slave_infoA
Read-only

[READ][risk=low] Detail one slave: identity, SM/FMMU config, OD summary.

Args:
    slave: Zero-based slave index (from ethercat_slaves).
    endpoint: Endpoint name from config.

Returns dict: {endpoint, index, name, vendor_id, product_code, revision,
    config_addr, state, input_bytes, output_bytes, sync_managers[], fmmus[],
    object_dictionary:[{index, name, entry_count}]}.

Example: ethercat_slave_info(slave=0, endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
slaveYes
endpointNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true. The description adds a return format and risk tag, but does not elaborate on behavioral traits like side effects, authorization needs, or rate limits. The openWorldHint is not explained.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise: a one-line summary, followed by arg descriptions, return dictionary, and an example. Every sentence adds value, and the summary is front-loaded with the risk tag and purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and medium complexity, the description provides a detailed return structure covering endpoint, slave identity, config, sync managers, FMMUs, and OD summary. It lacks explanations of SM/FMMU semantics but provides an example, making it reasonably complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description compensates by explaining 'slave' as a zero-based index from ethercat_slaves and 'endpoint' as an endpoint name from config. This adds meaningful context beyond the schema's type and default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it details one slave's identity, SM/FMMU config, and OD summary. It uses a specific verb 'Detail' and resource 'one slave', distinguishing it from sibling tools like ethercat_slaves (list slaves) and ethercat_read_sdo (read SDO).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage after obtaining a slave list from ethercat_slaves, as it mentions 'from ethercat_slaves'. However, it does not explicitly state when to use this tool versus alternatives like ethercat_read_sdo or ethercat_read_pdo, nor does it provide when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_slavesA
Read-only

[READ][risk=low] Bus scan: enumerate every slave on the segment.

Args:
    endpoint: Endpoint name from config (protocol 'ethercat').

Returns dict: {endpoint, slave_count, slaves:[{index, name, vendor_id,
    product_code, revision, config_addr, state}]}.

Example: ethercat_slaves(endpoint="bus1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false. Description adds '[READ][risk=low]' and details return dict structure, example call. It does not contradict annotations and provides useful behavioral context beyond them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is extremely concise: two-sentence intro, then clear Args/Returns/Example sections. No wasted words, front-loaded with key info.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, parameter, return structure (with fields), and example. For a simple enumeration tool with no output schema, this is sufficient. Lacks details on possible slave states but acceptable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage, so description must compensate. It defines 'endpoint: Endpoint name from config (protocol "ethercat").' This adds meaning beyond schema (just 'string' with default null), clarifying the parameter's source and protocol constraint.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description starts with '[READ][risk=low] Bus scan: enumerate every slave on the segment.' This clearly states a read operation to enumerate all slaves, with specific verb 'enumerate' and resource 'slaves'. It distinguishes from sibling tools like 'ethercat_slave_info' (specific slave) and 'ethercat_master_state' (master state).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description implies usage as a general bus scan but does not explicitly state when to use this tool versus alternatives like 'ethercat_slave_info' or 'ethercat_master_state'. No guidance on when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ethercat_write_sdoA
Destructive

[WRITE][risk=HIGH][MOC] CoE SDO download: write one OD entry (off by default).

OT-DANGEROUS. Defaults to dry_run=True (nothing written). ``value`` is a hex
string of the raw little-endian bytes (e.g. 'e803' = 1000 as uint16). Captures
the BEFORE value (SDO read-back) and records an undo descriptor. Set
dry_run=False AND record an approver to apply. 未经授权勿对生产控制系统写入.

Args:
    slave: Zero-based slave index.
    index: CoE object index (decimal, e.g. 0x607A → 24698).
    value: Hex string of raw little-endian bytes to write.
    subindex: Sub-index (default 0).
    endpoint: Endpoint name from config.
    dry_run: When True (default) returns a preview without writing.

Returns dict: dry-run → {slave, index, dry_run:true, before, would_write, note};
    applied → {slave, index, dry_run:false, before, written, applied:true}.

Example (preview): ethercat_write_sdo(slave=0, index=0x607A, value="e8030000").
ParametersJSON Schema
NameRequiredDescriptionDefault
indexYes
slaveYes
valueYes
dry_runNo
endpointNo
subindexNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate destructiveHint=true and readOnlyHint=false. The description confirms with 'OT-DANGEROUS' and explains the dry-run mechanism, capture of BEFORE value, and undo descriptor. No contradictions. It adds context about the high risk and safety features beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively long but well-structured with a header, warning, parameter list, and return format. It is front-loaded with risk and purpose. Some redundancy (e.g., repeating 'dry_run') but justified for safety-critical tool. Could be slightly tighter.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but the description explains the return dict for both dry-run and applied cases. Includes an example. Provides complete context for a complex write operation with safety implications. Leaves no major gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description explains all key parameters: slave (zero-based), index (decimal with example), value (hex string little-endian with example), dry_run (default true, behavior), subindex (default), endpoint (from config). It fully compensates for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool does a 'CoE SDO download: write one OD entry'. The prefix '[WRITE][risk=HIGH][MOC]' and the verb 'write' clarify the action. It distinguishes from siblings like ethercat_read_sdo.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says 'Defaults to dry_run=True (nothing written)' and 'Set dry_run=False AND record an approver to apply.' This gives clear when-to-use guidance. It also includes a Chinese warning about unauthorized writes. It could explicitly mention when not to use, but the safety precautions are strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

export_dataA
Read-only

[READ][risk=low] Export collected samples from the LOCAL SQLite sink to a file.

Source is ~/.iaiops/data.db — the local queryable store written by
historian_push(sink="sqlite") — NOT a live device read. Writes csv (Excel),
sqlite (SQL browser / Power BI) or parquet (pandas/Spark; needs
pip install 'iaiops[export]'), and returns the file path + row count with a
bounded inline preview (first 200 rows max) so the response never floods.

Args:
    fmt: 'csv' | 'sqlite' | 'parquet'.
    since/until: Optional ISO-8601 time bounds (inclusive).
    endpoint: Only samples from this endpoint label.
    tag: Only samples for this tag.
    limit: Max rows exported (1..100000; default 10000).
    out_path: Output file; default ~/.iaiops/exports/iaiops-export-<ts>.<ext>.

Returns dict: {format, path, rows, preview_rows:[{ts, endpoint, protocol, tag,
    value, quality, unit}] (≤200), preview_truncated}.

Example: export_data(fmt="csv", tag="line1.temp", since="2026-07-01T00:00:00").
ParametersJSON Schema
NameRequiredDescriptionDefault
fmtYes
tagNo
limitNo
sinceNo
untilNo
endpointNo
out_pathNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses behavioral traits beyond the annotations: it writes files (not destructive but creates files), returns file path and row count with a bounded preview, has a pip install dependency for parquet, and includes limits and defaults. This adds significant context that annotations alone (readOnlyHint, destructiveHint) do not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear summary, source explanation, output details, parameter list, and example. While informative, it could be slightly more concise (e.g., the pip install detail might be secondary), but overall it efficiently communicates essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, no output schema but described return dict) and the rich annotations, the description is complete—it covers source, behavior, constraints, parameter defaults, output structure with preview, and an example. No critical gaps remain for successful invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining each parameter: fmt with format options, since/until as optional ISO-8601 time bounds, endpoint/tag for filtering, limit with range and default, and out_path with default path. It also includes an example usage, making the parameters highly actionable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool exports collected samples from a local SQLite sink to a file, specifying the source and output formats. It distinguishes from sibling tools like historian_query (which returns data inline) and historian_push (which writes to sink) by explicitly noting the local store and file output.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description effectively explains when to use the tool: for exporting data from the local SQLite store to a file, not for live reads. It provides parameter details and an example, but lacks explicit exclusion criteria or direct comparisons to alternatives, such as noting that for real-time data, other tools like historian_query should be used.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_cpu_infoA
Read-only

[READ][risk=low] Omron CPU model/version via FINS 0501 (proves the link).

Args:
    endpoint: Endpoint name from config (protocol must be 'fins'); omit for default.

Returns dict: {endpoint, model, version}.

Example: fins_cpu_info(endpoint="line2").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Description adds context beyond annotations: specifies the FINS 0501 command, the 'proves the link' purpose, and the return dict structure. Annotations already declare readOnlyHint=true and destructiveHint=false; description adds concrete behavioral details without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two-line summary followed by Args, Returns, and Example. Every sentence is informative. No waste. Front-loaded with purpose and risk level.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one optional parameter and annotations present, the description covers purpose, usage, parameter details, return shape, and example. No gaps given the low complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter with 0% schema coverage. Description adds meaning: endpoint name from config, protocol must be 'fins', and omit for default. This compensates for the lack of schema description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description explicitly states it reads Omron CPU model/version via FINS 0501 and proves the link. The verb 'reads' and specific resource 'CPU model/version' are clear. Distinguishes from siblings like s7_cpu_info by specifying protocol FINS.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear that it is a read operation with low risk, and the usage context is implied by protocol FINS and the 'proves the link' phrase. However, no explicit when-to-use vs alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_cpu_statusA
Read-only

[READ][risk=low] Omron controller status via FINS 0601 (run/stop, mode, errors).

Args:
    endpoint: Endpoint name from config (protocol must be 'fins').

Returns dict: {endpoint, status, mode, fatal_error_data, non_fatal_error_data}.

Example: fins_cpu_status(endpoint="line2").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds that it reads via FINS 0601 and returns specific dictionary keys (status, mode, error data), which enriches understanding beyond the annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: a one-line header, then Args and Returns sections, plus an example. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one parameter, no output schema, and rich annotations, the description fully covers what the tool does, the input, and the output format. It is complete for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must explain the parameter. It does: 'endpoint: Endpoint name from config (protocol must be fins).' This adds significant meaning about valid values, compensating for missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads Omron controller status via FINS 0601, covering run/stop, mode, and errors. It distinguishes from sibling tools like fins_cpu_info or fins_read_words by specifying the specific command and resource.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions the endpoint must be from config with protocol 'fins' and provides an example, but does not explicitly state when to use this tool over alternatives like fins_cpu_info or fins_read_words. No when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_read_bitsA
Read-only

[READ][risk=low] Read bits from an Omron memory area (FINS 0101, bit codes).

Args:
    area: Bit-capable area: "CIO", "W", "H", "A", or "DM".
    address: Word address the first bit lives in, e.g. 0 for CIO 0.00.
    bit: Bit number within the word (0..15).
    endpoint: Endpoint name from config.
    count: Number of consecutive bits (1..256).

Returns dict: {endpoint, area, address, bit, count, bits:[bool,...]}.

Example: fins_read_bits(area="CIO", address=0, bit=0, count=16).
ParametersJSON Schema
NameRequiredDescriptionDefault
bitNo
areaNoCIO
countNo
addressNo
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds the FINS command code 0101 and 'risk=low', and details return format, providing behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a title line, args list, return description, and example. Every sentence adds value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters and no output schema, the description explains parameters, return dict, and provides an example. It lacks only an explicit note on openWorldHint (external state dependency) but is otherwise thorough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description provides clear, detailed explanations for all five parameters (area, address, bit, endpoint, count), including valid values and example. This fully compensates for missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Read' and the resource 'bits from an Omron memory area (FINS 0101, bit codes)'. It distinguishes from sibling tools like fins_read_words and fins_read_many by specifying bit-level reading.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for bit reads but does not explicitly state when to use this tool versus alternatives like fins_read_words or fins_read_many. Sibling differentiation is implied but not direct.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_read_manyA
Read-only

[READ][risk=low] Batched word reads over one FINS session (bounded).

Args:
    endpoint: Endpoint name from config.
    items: Read specs, each {"area": "DM", "address": 100, "count": 2}
        (max 20 items, count capped at 500 each).

Returns dict: {endpoint, reads:[{area, address, count, words:[int,...]}]}.

Example: fins_read_many(items=[{"area":"DM","address":100,"count":2},
    {"area":"CIO","address":0,"count":1}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
itemsNo
endpointNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it's bounded and risk low, providing context beyond annotations. It does not cover error behavior but is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with Args, Returns, and an example, making it easy to parse. It is slightly verbose but still efficient for its content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description provides the return format. It covers input and output but omits error handling. Given the tool's simplicity and annotations, it is mostly complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description fully explains both parameters: endpoint as a config name and items with a detailed structure including constraints (max 20 items, count capped at 500). This compensates fully.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs 'Batched word reads over one FINS session (bounded)', includes a READ tag, and distinguishes it from single-read siblings like fins_read_words and fins_read_bits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates it's for batched reads with explicit limits (max 20 items, count capped at 500), implying when to use it. It does not explicitly list alternatives, but the context is clear enough for selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_read_wordsA
Read-only

[READ][risk=low] Read 16-bit words from an Omron memory area (FINS 0101).

Args:
    area: Memory area: "DM", "CIO", "W", "H", "A", or "EM" (current bank).
    address: Word address to start at, e.g. 100 for DM100.
    endpoint: Endpoint name from config.
    count: Number of consecutive words (1..500, capped server-side).

Returns dict: {endpoint, area, address, count, words:[int,...]} (unsigned 16-bit).

Example: fins_read_words(area="DM", address=100, count=8).
ParametersJSON Schema
NameRequiredDescriptionDefault
areaNoDM
countNo
addressNo
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and safe operation. The description adds behavioral detail: server-side capping of count (1..500) and the specific FINS command. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Structured layout with Args, Returns, Example. Every sentence adds value, no redundancy. Front-loaded with purpose and risk level.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers essential information: return format, parameter constraints, server-side cap. Lacks error conditions or handling of invalid inputs, but annotation openWorldHint suggests some flexibility. Sufficient for a read-only tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully explains all four parameters: area (with allowed values), address (example format), endpoint (from config), and count (range). Example reinforces usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear action verb 'Read' and specifies the resource '16-bit words from an Omron memory area', explicitly referencing the FINS 0101 command. This distinguishes it from sibling tools like fins_read_bits and fins_read_many.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives such as fins_read_bits or fins_read_many. The description implies usage for word-sized data, but lacks when-not or alternative recommendations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fins_write_wordsA
Destructive

[WRITE][risk=HIGH][MOC] Write 16-bit words to an Omron area (off by default).

OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back
of the same range) and records an undo descriptor. Set dry_run=False AND
record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.

Args:
    area: Memory area to write: "DM", "CIO", "W", "H", "A", or "EM".
    address: Word address to start at, e.g. 100 for DM100.
    values: List of 16-bit word values to write (length 1..500).
    endpoint: Endpoint name from config.
    dry_run: When True (default) returns a preview without writing.

Returns dict: dry-run → {area, address, dry_run:true, before, would_write, note};
    applied → {area, address, dry_run:false, before, written, applied:true, _undo_id}.

Example (preview): fins_write_words(area="DM", address=100, values=[1,2,3]).
ParametersJSON Schema
NameRequiredDescriptionDefault
areaYes
valuesYes
addressYes
dry_runNo
endpointNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond annotations by detailing the dry_run safety mechanism, BEFORE value capture, undo descriptor recording, and requirement for an approver to apply writes. Annotations have destructiveHint=true, but the description enriches this with actionable safety behaviors. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a tag line, safety warnings, parameter details, return format, and example. Every sentence adds value; no fluff. The Chinese warning is context-specific but not excessive. Front-loaded with purpose and risk.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description thoroughly explains return values for both dry-run and applied modes, including undo descriptor. It covers safety protocol, parameter semantics, and provides an example. It is comprehensive for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining each parameter's meaning: area lists valid options, address gives an example, values specifies length bounds, dry_run explains default and effect, and endpoint indicates source. This is essential for correct usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool writes 16-bit words to an Omron area, with a specific verb ('Write'), resource ('16-bit words'), and scope ('Omron area'). It differentiates from siblings like fins_read_words and mc_write_words by specifying the protocol and data type. The [WRITE] tag reinforces the action.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides strong usage context: it's a dangerous operation defaulting to dry_run, requiring an approver to apply, and offering undo capability. However, it does not explicitly compare to sibling tools like fins_read_words or mc_write_words, leaving the agent to infer when to use this over alternatives. The 'OT-DANGEROUS' label and safety instructions give clear context but lack exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fleet_incidentsA
Read-only

[READ][risk=low] Roll up active RCA incidents across sites → fleet-wide top causes.

Aggregates the incidents each site reports into a fleet picture: how many incidents, which sites
are affected, and the most common root causes across the whole fleet. Read-only; no device I/O.

Args:
    sites: Per-site reports carrying incidents: [{site, incidents:[{cause|primary_cause,
        confidence?}]}].

Returns dict: {total_incidents, sites_with_incidents, affected_sites[], top_causes[]}.

Example: fleet_incidents(sites=[{"site":"plant-sh","incidents":[{"cause":"network"}]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
sitesYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds value by explicitly stating 'Read-only; no device I/O' and describing the aggregation behavior and return structure. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a summary tag and then provides structured sections (Args, Returns, Example). It is comprehensive without excessive wordiness. Each sentence contributes useful information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (single parameter, no output schema), the description fully covers the purpose, parameter structure, return format, and provides an example. No gaps remain for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, so the description must carry the full burden. It explains the 'sites' parameter as an array of objects with 'site' and 'incidents' fields, detailing the incident structure. This adds meaning beyond the bare schema. A slight deduction for informal formatting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Roll up' and the resource 'active RCA incidents across sites' to produce 'fleet-wide top causes'. It explains the aggregation purpose well. However, it does not explicitly distinguish this tool from similar sibling tools like 'fleet_status' or 'downtime_root_cause', so a perfect score is not warranted.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description indicates when to use the tool (to get a fleet overview of RCA incidents) and notes it is read-only with no device I/O. However, it does not mention when not to use it or suggest alternative tools for specific scenarios, leaving some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

fleet_statusA
Read-only

[READ][risk=low] Roll up per-site status reports into one fleet health view.

The tier above data_quality_fleet_rollup (per-endpoint within one site): this aggregates across
many edge SITES for central management. A site is 'offline' if its last_seen is older than
stale_after_s; fleet_status is the worst site status present. Read-only, pure; no device I/O.

Args:
    sites: Per-site reports, each
        [{site, location?, profile?, status?, score?, issues?, last_seen?}]; status ∈
        ok|degraded|critical|offline (else derived from score); score 0..1.
    stale_after_s: A site with no report newer than this is 'offline' (default 300).
    now: Optional ISO-8601 'now' for deterministic staleness (default: current UTC).

Returns dict: {site_count, fleet_status, fleet_score, by_status, worst_sites[], sites[]}.

Example: fleet_status(sites=[{"site":"sh","score":0.9},{"site":"bj","status":"critical"}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
nowNo
sitesYes
stale_after_sNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. Description adds 'Read-only, pure; no device I/O', aligns with annotations, and explains staleness logic and status derivation, adding value beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is well-structured with sections (Args, Returns, Example) and front-loaded with key tags [READ][risk=low]. Slightly verbose but every sentence adds value; could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description details the return dict structure. All parameters are explained, an example is provided, and annotations cover safety. Completeness is high for a tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but description fully covers all three parameters: sites (structure, valid fields, derived status), stale_after_s (default 300), now (optional ISO-8601). Provides meaning, defaults, and constraints that the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description explicitly states it rolls up per-site status reports into fleet health view, distinguishing from sibling data_quality_fleet_rollup (per-endpoint within one site) by specifying aggregation across sites.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description clarifies it is the tier above data_quality_fleet_rollup, providing context for when to use this tool over alternatives, though it does not explicitly state when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

health_summaryA
Read-only

[DEPRECATED → opcua_health_summary][READ][risk=low] Classify OPC-UA tags.

Classifies tag node-ids against warn/alarm thresholds. Returns
ok/warn/alarm/unknown counts plus the offending tags. Thresholds
come from config tags, or per-ref overrides in ``thresholds``.

Args:
    endpoint: Endpoint name from config.
    node_ids: Tag node ids to evaluate; omit to use configured tags.
    thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
node_idsNo
thresholdsNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, making the tool's safety profile clear. The description adds that it returns ok/warn/alarm/unknown counts and offending tags, and mentions that thresholds come from config or overrides, which enriches transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with deprecation and purpose, then provides a structured Args section. It is comprehensive but slightly verbose; however, the deprecation note and parameter details are all necessary. Well-organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 3 parameters and no output schema, the description adequately explains the return values (counts and offending tags) and how thresholds are set. It covers what the agent needs to know to use it correctly, given the absence of output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Since schema description coverage is 0%, the description carries the full burden for parameter semantics. It provides clear explanations for all three parameters: endpoint (from config), node_ids (omit for configured), and thresholds (optional with specific structure). This adds substantial meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: classify OPC-UA tags against thresholds and return counts. The resource is specified as tag node-ids, and it distinguishes from siblings via the deprecation note pointing to opcua_health_summary.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The deprecation note explicitly tells the agent to use opcua_health_summary instead, providing clear alternative guidance. The context for use is implied by the classification function, but there is no explicit when-not-to-use statement, though the deprecation covers it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

heartbeat_healthA
Read-only

[READ][risk=low] Is a heartbeat/watchdog tag still alive? (liveness check).

A heartbeat must keep CHANGING; a flatlined one means the upstream is dead even
when comms/quality look fine. With timestamped samples + max_interval_s, also
flags the longest stall.

Args:
    series: Heartbeat samples — scalars or {value, timestamp?} (a counter/toggle).
    max_interval_s: Max allowed gap between changes; exceeding it = not alive.

Returns dict: {alive (bool), samples, distinct_transitions, spread,
    longest_stall_s, reason}.

Example: heartbeat_health(series=[1,2,3,4,5], max_interval_s=10).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
max_interval_sNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral context: it is a read operation with low risk, explains the flatlining concept, and that it also flags longest stall. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for summary, args, returns, and example. It is slightly lengthy but each sentence adds value. Could be trimmed slightly, but overall efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's simplicity (2 params, no output schema), the description covers input, output, behavior, and example comprehensively. It explains the concept of heartbeat liveness, making it complete for an agent to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining both parameters: series (heartbeat samples as scalars or with timestamps) and max_interval_s (max allowed gap). It also provides an example, adding significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool checks if a heartbeat/watchdog tag is alive (liveness check). It explains the need for change to indicate liveness, distinguishing it from general health checks, but does not explicitly differentiate from similar sibling tools like tag_health.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for heartbeat tags that must change, but it does not provide explicit guidance on when to use this tool versus alternatives or when not to use it. Usage context is clear but lacks exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historian_coverageA
Read-only

[READ][risk=low] Per-tag history coverage — what history do we actually have.

Answers the question every RCA starts with: which tags have stored history,
how many rows, and over what time span — per tag {rows, first_ts, last_ts}
from the same store historian_push writes. Read-only, bounded (tag list is
capped with a truncation flag); no device I/O.

Args:
    reader: 'sqlite' | 'tdengine' | 'iotdb'. Omit to use the per-site
        'historian:' block in ~/.iaiops/config.yaml, else the local sqlite
        store. TSDB readers need their extra: pip install iaiops[tdengine|iotdb].
    limit: Max tags returned (1..2000; default 500).

Returns dict: {reader, source, tag_count, tags:[{tag, rows, first_ts,
    last_ts}], truncated} plus the standard return envelope
    (items_returned, items_total, items_total_is_exact, is_truncated,
    truncation_note).

Example: historian_coverage().
ParametersJSON Schema
NameRequiredDescriptionDefault
limitNo
readerNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses behavioral traits beyond annotations: '[READ][risk=low]', bounded with truncation flag, no device I/O, and details on default reader configuration. Matches readOnlyHint=true without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with purpose, args, returns, example. Slightly longer due to thoroughness but every sentence adds value. Front-loaded with purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete for a read-only tool with 2 params and no output schema: covers purpose, arguments, return format, truncation behavior, and gives example.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Adds full meaning beyond schema: describes reader options (sqlite/tdengine/iotdb) with config fallback and pip install notes, and limit range (1-2000) with default. Compensates for 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states purpose: 'Per-tag history coverage — what history do we actually have.' Specifies verb 'Answers the question' and resource 'tags with stored history, rows, time spans.' Distinguishes from siblings like historian_push (write) and historian_query (query).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides usage context: 'Answers the question every RCA starts with' and notes it's read-only, bounded, no device I/O. Implicitly distinguishes from alternatives but lacks explicit when-not or alternatives list.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historian_healthA
Read-only

[READ][risk=low] Bad-tag / flatline / gap detection over a provided series.

Pure analysis over an injected sample series — no live historian needed.

Args:
    series: Samples — scalars or {value, timestamp (ISO-8601), quality|good}.
    gap_threshold_s: Time gap (seconds) between consecutive samples that counts
        as a data gap (default 60).
    flatline_eps: Spread at/below which the series counts as flatline.

Returns dict: {samples, numeric_samples, bad_quality_count, flatline (bool),
    gap_count, gaps:[{after, gap_seconds}], stdev,
    verdict ('ok'|'degraded'|'gappy'|'flatline'|'bad_tag')}.

Example: historian_health(series=[{"value":10,"timestamp":"2026-06-28T10:00:00Z"}, ...]).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
flatline_epsNo
gap_threshold_sNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that the tool is a pure analysis (read-only) with low risk and no destructive actions. It explains that it operates over an injected series and details the return dictionary structure. This adds significant context beyond the annotations ('readOnlyHint': true, 'destructiveHint': false).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear header, purpose statement, parameter details, return value explanation, and an example. It is concise but comprehensive, with every sentence adding value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of an output schema, the description fully explains the return dictionary structure. All three parameters are described with details. The context signals (3 params, 1 required, 0% schema coverage) are compensated by the thorough description.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description includes an 'Args' section that explains the meaning of each parameter, including defaults, format (ISO-8601 timestamps), and the 'quality' key in series elements. This goes well beyond the input schema, which only provides titles and types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool performs bad-tag, flatline, and gap detection over a provided series. It specifies a specific verb+resource combination and distinguishes itself from sibling tools like historian_query and tag_health by focusing on analysis over an injected sample series without requiring a live historian.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'no live historian needed,' indicating when this tool is appropriate for pure analysis. However, it does not provide explicit when-not-to-use or alternative recommendations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historian_pushA

[WRITE][risk=low][→historian] Push collected telemetry to a national TSDB.

Writes already-collected points to a domestic historian (信创) — TDengine or
IoTDB — instead of binding InfluxDB. Data egress to the operator's OWN database,
NOT a control-system write. Non-numeric points are skipped (numeric value column).

Args:
    points: Collected points — {ref|metric, value|present_value, timestamp?, ...}
        (e.g. the output of interrogate / integrity_poll / read_points / monitor).
    sink: 'tdengine' or 'iotdb'.
    host/port/user/password: TSDB connection params (sensible defaults per sink
        when blank/0).
    database: Target database (TDengine db / IoTDB storage group, e.g. 'root.iaiops').

Returns dict: {sink, received, written, skipped_non_numeric, database}.

Example: historian_push(points=[{"ref":"line1.temp","value":21.5}], sink="tdengine",
    host="10.0.0.20", database="iaiops").
ParametersJSON Schema
NameRequiredDescriptionDefault
hostNolocalhost
portNo
sinkYes
userNo
pointsYes
databaseNo
passwordNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=false (write), openWorldHint=true (flexible input), and destructiveHint=false. The description adds important behavior: non-numeric points are skipped and data goes to the operator's own database. It does not cover error handling or limits, but the added context is valuable.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with headings and bullet points. It is front-loaded with the purpose and provides an example. Minor redundancy exists (e.g., [WRITE] prefix repeated), but overall it is efficient and clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 params, write operation) and no output schema, the description covers the essential aspects: purpose, parameter behavior, and return format. It could include more on error handling or authentication, but the provided example and Returns section are adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description's Args section explains all 7 parameters, including points, sink, connection details, and database. It also provides an example. This fully compensates for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'push' and the resource 'telemetry to a national TSDB'. It distinguishes itself from sibling tools like historian_query by specifying it writes collected points to TDengine or IoTDB, and explicitly mentions it is not a control-system write.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides context for when to use the tool: after collecting points to push to a domestic historian. It states what it does not do (not InfluxDB, not control-system write) and that non-numeric points are skipped. However, it does not explicitly mention when not to use or list alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

historian_queryA
Read-only

[READ][risk=low] Query a tag's historical samples from a historian.

Reads history back OUT of the store the sinks write — the local SQLite
store (~/.iaiops/data.db), TDengine, or IoTDB — so the RCA copilot / an
agent can see real pre-incident windows instead of only short live samples.
Read-only over the operator's OWN historian; no device I/O. Bounded: rows
are capped and a truncation flag is set when more history exists.

Args:
    tag: Tag/metric name as stored by historian_push (e.g. 'line1.temp').
    since/until: Optional ISO-8601 time bounds (inclusive).
    endpoint: Only samples from this endpoint label (sqlite reader only —
        the TSDB layout stores no endpoint label).
    reader: 'sqlite' | 'tdengine' | 'iotdb'. Omit to use the per-site
        'historian:' block in ~/.iaiops/config.yaml, else the local sqlite
        store. TSDB readers need their extra: pip install iaiops[tdengine|iotdb].
    limit: Max rows returned (1..10000; default 1000).

Returns dict: {reader, source, tag, since, until, rows,
    samples:[{ts, endpoint, protocol, tag, value, quality, unit}], truncated}
    plus the standard return envelope (items_returned, items_total,
    items_total_is_exact, is_truncated, truncation_note). Trust
    `is_truncated`: an empty `samples` with is_truncated=false means the
    history really is empty, NOT that the result was cut short.

Example: historian_query(tag="line1.temp", since="2026-07-02T06:00:00Z",
    until="2026-07-02T08:00:00Z").
ParametersJSON Schema
NameRequiredDescriptionDefault
tagYes
limitNo
sinceNo
untilNo
readerNo
endpointNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds beyond annotations: 'Read-only over the operator's OWN historian; no device I/O', 'rows are capped and a truncation flag is set', and explains empty samples with is_truncated=false meaning truly empty. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized: purpose, args, returns, example. Each section adds value without redundancy. It uses clear formatting and avoids unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description provides a detailed return format including the standard envelope and trust expectations. It covers all parameters, behavior, and an example, making it complete for a 6-parameter complex tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description provides detailed explanations for all 6 parameters: tag (example), since/until (ISO-8601 inclusive), endpoint (sqlite only), reader (values and default behavior), limit (range and default). It adds constraints and examples, fully compensating for missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Query' and the resource 'a tag's historical samples from a historian'. It specifies the storage backends (SQLite, TDengine, IoTDB) and use case (pre-incident windows), distinguishing it from sibling tools like historian_push (write) and opcua_read_history (different source).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use this tool (historical analysis, read-only, no device I/O) and mentions bounding and truncation. It notes extra install requirements for TSDB readers. However, it does not explicitly list alternative tools for when not to use this one, such as live sampling tools or other history readers.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ignition_alarm_statusA
Read-only

[READ][risk=low] Active/acknowledged alarm list (normalized).

Args:
    base_url: Gateway HTTP base URL.
    flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
    secret_name: Secret-store key holding the API token (omit if none).
    verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
        is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.

Returns dict: {flavor, base_url, alarm_count,
    alarms:[{name, source, priority, state, label, timestamp}]}.

Example: ignition_alarm_status(base_url="https://gw:8043", flavor="webdev").
ParametersJSON Schema
NameRequiredDescriptionDefault
flavorNowebdev
base_urlYes
verify_tlsNo
secret_nameNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds valuable behavioral context beyond annotations: marks as READ with low risk, describes return structure, and documents security constraints for verify_tls and secret_name. No contradictions with annotations (readOnlyHint, openWorldHint, destructiveHint).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Efficiently structured: READ tag, risk, purpose, then Args, Returns, Example. No redundant sentences; every line adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 4 parameters (1 required), annotations present, and no output schema, the description provides complete context: parameter explanations, return format, and an example call. Sufficient for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Each parameter is explained in the Args section with clear semantics (e.g., flavor choices, verify_tls default and override condition). Despite 0% schema description coverage, the tool description fully compensates by detailing all 4 parameters.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description explicitly states action ('list'), resource ('alarms'), and scope ('active/acknowledged', 'normalized'). Clearly distinguishes from sibling tools like alarm_bad_actors or alarm_flood_analysis which perform different analyses.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Description implies usage for retrieving alarm status but does not specify when to use this tool over related alarm tools (e.g., alarm_flood_analysis, alarm_cascade). No direct guidance on exclusions or context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ignition_gateway_statusA
Read-only

[READ][risk=low] Gateway/module health + reachability (the Gateway doctor step).

Talks to the vendor SCADA/MES platform's Gateway HTTP web API (not OPC-UA —
that stays on the opcua connector). The API token is resolved from the
encrypted secret store by key name, never passed inline. Token-egress guard:
with a secret set, base_url must point at an internal host (private IP /
single-label / .local-style name) or a host the operator allowlisted via
IAIOPS_TOKEN_EGRESS_HOSTS — public hosts are refused before any request
(prevents stored-token exfiltration).

Args:
    base_url: Gateway HTTP base URL, e.g. 'https://gw-host:8043'.
    flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
    secret_name: Secret-store key holding the API token (omit if none).
    verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
        is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.

Returns dict: {flavor, base_url, reachable, gateway:{name, version, state},
    module_count, modules:[{name, state, version}]}.

Example: ignition_gateway_status(base_url="https://gw:8043", flavor="webdev").
ParametersJSON Schema
NameRequiredDescriptionDefault
flavorNowebdev
base_urlYes
verify_tlsNo
secret_nameNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses significant behavioral traits beyond annotations: it is a read operation (consistent with readOnlyHint), explains token egress guard, refusal of public hosts, and TLS verification constraints. It adds context about authentication and security that annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed and well-structured with a READ header, bullet list of args, and return format. While it is lengthy, every sentence adds value and the most important information is front-loaded. It earns a 4 because it is slightly verbose but still efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 4 parameters with 0% schema coverage and no output schema, the description provides comprehensive information: parameter explanations, return dict structure, and security context. It leaves no obvious gaps for an agent to misuse the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully compensates. It explains each parameter's purpose: base_url with example, flavor as API dialect with possible values, secret_name as secret-store key, and verify_tls with default and conditions for insecure. This adds critical meaning beyond the schema titles.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it checks gateway/module health and reachability, calling it the 'Gateway doctor step'. It specifies it talks to the vendor SCADA/MES platform's Gateway HTTP web API, distinguishing it from OPC-UA tools. The verb+resource is specific and unique among siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool (gateway health check) and explicitly contrasts it with the opcua connector. It also details token resolution and egress constraints, though it does not explicitly list when not to use it. The differentiation from sibling tools is adequate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ignition_tag_browseA
Read-only

[READ][risk=low] Browse the tag tree under a provider/path.

Args:
    base_url: Gateway HTTP base URL.
    provider: Tag provider name (e.g. 'default').
    path: Folder path under the provider to browse (blank = root).
    flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
    secret_name: Secret-store key holding the API token (omit if none).
    verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
        is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.

Returns dict: {flavor, base_url, provider, path, node_count,
    nodes:[{name, path, type, has_children}]}.

Example: ignition_tag_browse(base_url="https://gw:8043", provider="default",
    path="Line1").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathNo
flavorNowebdev
base_urlYes
providerYes
verify_tlsNo
secret_nameNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false, and the description confirms [READ][risk=low]. It adds valuable context about verify_tls behavior (requires IAIOPS_ALLOW_INSECURE_TLS=1 to disable), which is beyond annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Purpose is front-loaded. Structure with Args/Returns and example is clear. Every sentence adds value, but could be slightly more concise (e.g., 'Returns dict' could be shortened without loss). Overall well-organized.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 6 parameters, no output schema, and high parameter complexity, the description covers return format (dict with fields), parameter details, and an example. Lacks edge case handling (e.g., invalid path, network errors) but sufficient for typical use. Annotations are rich, reducing burden.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so description carries full burden. It explains each parameter meaningfully: base_url as 'Gateway HTTP base URL', provider as 'Tag provider name (e.g. default)', path as 'Folder path under the provider (blank = root)', flavor as 'Gateway API deployment dialect — webdev or gateway', secret_name as 'Secret-store key holding the API token (omit if none)', verify_tls with TLS certificate verification and env var override. Adds significant value beyond schema types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it 'Browse the tag tree under a provider/path.' with READ and risk=low annotations. It specifically distinguishes from siblings like ignition_tag_read and ignition_tag_history by focusing on browsing the tree structure rather than reading values or history.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool versus alternatives like opcua_browse or uns_browse. Does not specify prerequisites, limitations, or when not to use it. The description only explains what it does, not why choose it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ignition_tag_historyA
Read-only

[READ][risk=low] Historian query for one tag over a time window (aggregated).

Args:
    base_url: Gateway HTTP base URL.
    provider: Tag provider name (e.g. 'default').
    tag_path: Tag path whose history to query.
    start: Window start (ISO-8601 or the gateway's accepted time string).
    end: Window end (ISO-8601 or the gateway's accepted time string).
    count: Max samples to return (1..5000, capped server-side).
    flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
    secret_name: Secret-store key holding the API token (omit if none).
    verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
        is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.

Returns dict: {flavor, base_url, provider, tag_path, start, end,
    sample_count, samples:[{timestamp, value, quality}]}.

Example: ignition_tag_history(base_url="https://gw:8043", provider="default",
    tag_path="Line1/OvenTemp", start="2026-07-13T00:00:00Z",
    end="2026-07-13T06:00:00Z", count=200).
ParametersJSON Schema
NameRequiredDescriptionDefault
endYes
countNo
startYes
flavorNowebdev
base_urlYes
providerYes
tag_pathYes
verify_tlsNo
secret_nameNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, openWorldHint=true, destructiveHint=false. Description adds security caveat about verify_tls and server-side cap on count, providing extra behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is structured with Args, Returns, Example sections. Front-loaded with type and risk. Slightly lengthy but efficient for a 9-parameter tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 9 parameters (5 required), no output schema, and security caveat, the description covers all necessary information including return format and edge case for TLS verification.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but description fully documents each parameter with purpose, defaults, and constraints. Includes an example illustrating typical usage. Adds significant meaning beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Historian query for one tag over a time window (aggregated)', specifying verb, resource, and scope. Distinguishes from siblings like real-time read or multiple-tag queries.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool vs. alternatives like 'historian_query' or 'ignition_tag_read'. Usage context is implied but not explicitly stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ignition_tag_readA
Read-only

[READ][risk=low] Current value(s)/quality/timestamp for tag path(s).

Args:
    base_url: Gateway HTTP base URL.
    provider: Tag provider name (e.g. 'default').
    tag_paths: Tag paths to read (from ignition_tag_browse).
    flavor: Gateway API deployment dialect — 'webdev' or 'gateway'.
    secret_name: Secret-store key holding the API token (omit if none).
    verify_tls: Verify the Gateway's TLS certificate (default True). Passing False
        is refused unless the operator set IAIOPS_ALLOW_INSECURE_TLS=1.

Returns dict: {flavor, base_url, provider, tag_count,
    tags:[{path, value, quality, timestamp}]}.

Example: ignition_tag_read(base_url="https://gw:8043", provider="default",
    tag_paths=["Line1/OvenTemp"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
flavorNowebdev
base_urlYes
providerYes
tag_pathsYes
verify_tlsNo
secret_nameNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context: it explains the security constraint on verify_tls (requiring IAIOPS_ALLOW_INSECURE_TLS=1 to disable), the return dict structure, and the risk level. This goes beyond annotations and provides useful behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a one-line summary with risk tag, followed by Args, Returns, and Example sections. Every sentence adds value. It is front-loaded with the core purpose and uses clear formatting. There is no redundant or extraneous text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers input parameters, return structure (including nested tags array), an example call, and a security constraint. It lacks information on error handling or edge cases (e.g., what happens if a tag path is invalid). For a read-only tool with good annotations (readOnlyHint, openWorldHint), this is fairly complete but not fully exhaustive.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It explicitly explains all 6 parameters in the Args section: base_url, provider, tag_paths (with origin mention), flavor (with dialect options), secret_name (optional), and verify_tls (with default and special condition). This adds significant meaning and context beyond the schema's type/name information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with '[READ][risk=low] Current value(s)/quality/timestamp for tag path(s).' This clearly states the tool's purpose: reading live tag data. The verb 'read' and noun 'current value(s)/quality/timestamp' specify the action and resource. The example further clarifies usage. It distinguishes itself from siblings like 'ignition_tag_browse' (listed in siblings) by focusing on reading current values rather than browsing tags.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions 'tag_paths: Tag paths to read (from ignition_tag_browse),' which implies a sequential use: browse first, then read. However, it does not explicitly state when to use this tool versus alternatives (e.g., 'ignition_tag_history' for historical data) or provide exclusions. The guidance is implicit but not comprehensive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

investigation_listA
Read-only

[READ][risk=low] List saved investigations, newest first.

ParametersJSON Schema
NameRequiredDescriptionDefault
siteNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds value by stating the ordering behavior ('newest first') and that only saved investigations are returned, which are not visible in annotations or schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is one short, front-loaded sentence with a useful READ tag prefix. Every word contributes meaning, and there is no redundant boilerplate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only list tool, the description covers the core action and ordering. However, the undocumented 'site' parameter is a real gap, and with no output schema or parameter guidance, the description is only minimally complete rather than fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description does not mention the 'site' parameter at all. An agent cannot determine whether 'site' filters results, groups them, or is required for certain contexts, so the description fails to compensate for the bare input schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a clear verb and resource: 'List saved investigations' plus an ordering detail ('newest first'). It distinguishes itself from siblings like investigation_show and investigation_open by focusing on listing rather than viewing or opening a specific investigation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description makes it clear that this tool is for listing saved investigations, which gives an agent a reasonable context for when to call it. It does not explicitly name alternatives or state when not to use it, but the action is straightforward enough that no exclusion is strictly required.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

investigation_openA
Read-only

[READ][risk=low] Open an investigation over one past window and walk what can be walked.

Contacts no device — the window is already past, and its evidence is whatever
was collected at the time. Each of the eight steps records its own outcome:
`done` (it ran, here is what it found), `refused` (it could not run HERE —
no samples, no alarm source; a site fact) or `not_possible` (this product
cannot do it at all).

The investigation is persisted, so it can be re-read and advanced later.
ParametersJSON Schema
NameRequiredDescriptionDefault
endYes
siteNodefault
assetNo
startYes
endpointYes

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The annotations already indicate readOnly/openWorld/non-destructive, and the description adds important non-obvious behavior: no device contact, evidence collected at the time, per-step outcomes, and persistence. These details go well beyond the structured fields and materially help an agent understand side effects and failure modes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with [READ][risk=low]. Each sentence contributes a distinct fact: past window, no device contact, outcome semantics, and persistence. There is no filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description is behaviorally rich and partially compensates for the absent output schema by enumerating outcome states. However, with no output schema and 0% parameter documentation, it leaves endpoint/site/asset semantics and the identity of the eight steps unclear, so an agent has incomplete invocation detail.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% and the description gives no direct parameter guidance. 'Past window' loosely implies start/end define the time range, but endpoint, site, and asset are left unexplained, and no formats or value constraints are provided. With five parameters, this is a substantial gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and object: 'Open an investigation over one past window and walk what can be walked.' It clearly distinguishes itself from sibling investigation tools by emphasizing the window is past and that no device is contacted. The outcome taxonomy (done/refused/not_possible) further clarifies what the tool produces.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear usage context: use it for a past window, it does not contact a device, and it persists the investigation for later re-reading and advancement. However, it does not explicitly name alternative tools or state when not to use this tool, so it falls just short of full routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

investigation_readinessA
Read-only

[READ][risk=low] How far into an investigation this site could get, and what each gap needs.

`readiness` answers "which scenarios can this site run"; this answers the
next question down — if something stopped tomorrow, how many of the eight
evidence steps could actually be walked, and for each one that could not,
what is missing.

Contacts nothing: no device, no network, no historian. It is derived from
the config and the local store, which is what makes it usable on a site
nobody has been authorised to probe yet.

Each gap says whether it is *unmet* (you have not supplied it — the fix names
the command) or *not yet expressible* (this product offers no way to supply
it at all). Those two send a person to very different places.
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNodefault

TDQS

A4.1/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint and destructiveHint annotations, the description discloses that the tool contacts no device, network, or historian and is derived from config and local store, explaining why it is safe on unauthorized sites. It also explains the two possible gap outcomes, unmet vs not yet expressible, giving the agent a clear picture of result semantics. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a READ/risk tag and a one-line summary, then uses short paragraphs to cover scope, safety, and gap semantics. Each paragraph earns its place, though the first two sentences are slightly repetitive in expressing the 'how far can this site go' idea.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers core behavior, safety, and output distinction between unmet and not-yet-expressible gaps well. However, with only one input parameter, omitting parameter guidance entirely is a meaningful gap, and there is no output schema to fill that in. The eight evidence steps are also left unnamed, though that may be acceptable product-domain knowledge.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema contains one `site` parameter with a default, but the description never mentions it or explains how to populate it. With 0% schema description coverage, the description needed to compensate and did not. The parameter name and default are somewhat self-evident, but the description adds no meaning about valid values, site identity, or how the default affects the analysis.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that investigation_readiness evaluates how far into an evidence-gathering investigation a site can currently get, and identifies what each missing gap needs. It explicitly contrasts itself with `readiness` (site_readiness), saying readiness answers which scenarios a site can run while this tool answers the next question down. This makes the tool's purpose specific and distinguishable from its sibling.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives a clear when-to-use condition: 'usable on a site nobody has been authorised to probe yet' because the tool contacts nothing and derives data from config and local store. It also distinguishes from the site_readiness sibling by describing the relationship between the two tools. However, it does not explicitly name alternatives for cases where live device, network, or historian probing is desired, so exclusion guidance is mostly implicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

investigation_showA
Read-only

[READ][risk=low] Re-read a saved investigation — the state it was left in.

ParametersJSON Schema
NameRequiredDescriptionDefault
investigation_idYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's '[READ][risk=low]' mostly repeats that. It adds some behavioral context with 'the state it was left in,' indicating the tool returns the previously saved snapshot, but it does not disclose details like error behavior or what happens for missing/invalid investigation IDs.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One concise sentence with no wasted words, and the read/risk profile is front-loaded. It conveys the core purpose and key distinguishing detail efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a simple one-ID read tool with annotations covering safety, so the bar is lower. However, with no output schema, the description only vaguely indicates the return ('the state it was left in') and does not explain what fields or format the saved investigation state will be returned in. It is minimally adequate but leaves a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description needs to compensate. It does not explicitly define investigation_id beyond the schema's 'Investigation Id' title, though the phrase 'a saved investigation' implies the ID refers to a previously saved investigation. The single parameter is self-explanatory enough, but the description adds little direct semantic detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('Re-read'), a clear resource ('a saved investigation'), and a distinctive semantic ('the state it was left in'). This differentiates it from siblings like investigation_open and investigation_list, which involve opening or listing rather than re-reading a saved investigation by ID.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The phrase 'a saved investigation' implies this is for resuming or inspecting an existing investigation, but the description does not explicitly say when to use it over investigation_open or investigation_list, nor does it mention when not to use it. Usage guidance is mostly implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

learn_cause_weightsA
Read-only

[READ][risk=low] Learn a per-site RCA {cause: weight} profile from history.

Derives a per-site cause-weight profile from a corpus of CONFIRMED past
incidents so downtime_root_cause adapts to what THIS site's evidence actually
predicts. Pure + explainable: each weight is the smoothed signal→cause
precision relative to chance (>1 = evidence for that cause is reliable here,
<1 = often misleading) — no black box. Anti-overfit: Laplace smoothing + a
per-cause min-sample guard, and a fall-back to the shipped defaults when the
corpus is too thin. Feed the returned 'cause_weights' to downtime_root_cause's
cause_weights argument. Advisory: it tunes ranking, never executes anything.

Args:
    history: Confirmed incidents — [{cause, signals:[...]}] where 'cause' is the
        known root cause and 'signals' are the cause labels the evidence pointed
        at (both from the copilot taxonomy: mechanical_fault, comms_loss,
        sensor_fault, material_starvation, quality_reject, changeover, utility_fault).
    min_samples: Minimum confirmed incidents before adapting at all (default 8);
        below it the defaults are kept.
    smoothing: Laplace pseudo-count pulling each estimate toward chance (default 1.0).

Returns dict: {cause_weights:{cause: multiplier}, n_incidents, per_cause:{cause:
    {support, hits, precision, weight, note}}, rationale}.

Example: learn_cause_weights(history=[{"cause":"mechanical_fault",
    "signals":["mechanical_fault"]}, {"cause":"comms_loss","signals":["comms_loss"]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
historyYes
smoothingNo
min_samplesNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false. The description adds detailed behavioral context: pure + explainable, no black box, anti-overfit with Laplace smoothing, and that it never executes anything. This exceeds what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is moderately long but well-structured with a headline, sections, and clear formatting. It is informative without being overly verbose, though it could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and lack of output schema, the description fully explains the return value (dict with cause_weights, n_incidents, per_cause details, rationale) and provides an example. It is complete for effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so description compensates well. It lists arguments with defaults and explains history format: [{cause, signals:[...]}]. It doesn't describe each property in detail but gives sufficient context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool learns a per-site RCA cause-weight profile from history. It specifies the verb 'Learn', the resource 'per-site RCA cause-weight profile', and distinguishes itself by providing a statistical profile to adapt downtime_root_cause.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance: 'Feed the returned cause_weights to downtime_root_cause's cause_weights argument.' and advises it only tunes ranking, never executes. It mentions fall-back when corpus is thin but does not explicitly compare with sibling tools like rca_corpus_from_maintenance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

line_relation_declareB
Read-only

[READ][risk=low] Record that one asset feeds another — the second RCA axis.

`[READ]` follows this repo's convention, where the tag is about PLANT state:
it touches no device, exactly like `baseline_record_change` and
`adopt_alias_map`, which are the same shape. It does write — a declaration
about the line, into the site knowledge base.

With time alone, an upstream stoppage produces a string of equally-confident
downstream false causes, because on a line downstream co-occurrence is
guaranteed whatever the cause. That guarantee is exactly why this is a
declaration and not something inferred (D25): a person stating the line
order needs no inference at all.

``by`` is required — a person is the evidence, and an edge with no author is
indistinguishable from a guess a year later. Self-loops and cycles are
refused here, where somebody can still fix them.
ParametersJSON Schema
NameRequiredDescriptionDefault
byYes
siteNodefault
upstreamYes
downstreamYes

TDQS

B3.2/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description explicitly says 'It does write — a declaration about the line, into the site knowledge base,' while annotations carry readOnlyHint: true. This is a direct contradiction and forces an agent to guess whether side effects occur. The added details about `by` and cycle rejection are useful but cannot offset the contradictory read/write signal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The summary is front-loaded in one sentence, followed by organized paragraphs on convention, rationale, and constraints. It is longer than strictly necessary due to the root-cause reasoning, but each paragraph earns its place and the structure helps an agent parse the key points.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a four-parameter write-like tool with no output schema and no parameter descriptions, the description covers purpose, direction, author requirement, and cycle restriction. But it omits what the call returns, the role/default of `site`, and how asset identifiers are expressed, and the read/write contradiction leaves a core uncertainty.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must compensate. It gives direction meaning to upstream/downstream ('one asset feeds another'), explains why `by` is required, and notes cycles are refused. However, it never describes the `site` parameter or value formats, so not all parameters receive adequate semantic coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence 'Record that one asset feeds another' names a specific verb and resource, and the rest clarifies it is a person-authored declaration about line order rather than an inference. It is clear about the core operation, though it does not explicitly contrast itself with the sibling line_relations_list or other RCA tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives useful context: a person is the evidence, this is a declaration rather than something inferred, and self-loops/cycles are refused. However, it does not explicitly name alternative tools or state a when-not-to-use condition.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

line_relations_listB
Read-only

[READ][risk=low] The declared line order for a site, and what each asset feeds.

ParametersJSON Schema
NameRequiredDescriptionDefault
siteNodefault

TDQS

B3.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's [READ][risk=low] tag repeats that safety profile. It adds a little context by specifying that results are based on declared order and feed relationships, but it does not disclose open-world behavior, default-site handling, or what happens when no declarations exist. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One short sentence plus a safety tag, with no filler. The essential content—declared order and feed relationships—is front-loaded and every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a one-optional-parameter read-only list tool, this is a minimally viable description. It tells an agent what the tool returns, but with no output schema it omits the return shape, the effect of omitting site, and any relationship to line_relation_declare.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description should compensate for the undocumented site parameter, but it only repeats that the data is 'for a site.' It does not explain accepted site values, the meaning of the 'default' value, or how the parameter changes the response.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies a specific resource—the declared line order for a site—and adds that each asset's feed relationship is included, so the purpose of returning line-relation data is clear. It does not explicitly contrast itself with sibling line_relation_declare, but the read-only wording and the tool name make the distinction reasonably inferable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The word 'declared' implies this tool reads previously declared line relations, and the sibling name line_relation_declare hints at the complementary write operation. However, the description gives no explicit when-to-use guidance, prerequisites, or direct comparison with alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mc_cpu_statusA
Read-only

[READ][risk=low] MELSEC CPU type/code (proves the MC link is alive).

Args:
    endpoint: Endpoint name from config (protocol must be 'mc'); omit for default.

Returns dict: {endpoint, plctype, cpu_type, cpu_code}.

Example: mc_cpu_status(endpoint="cell3").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true. Description adds '[READ][risk=low]' and 'proves the MC link is alive', providing useful behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Concise: one-line purpose, compact parameter and return docs, example call. No filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, parameter, return dict, example. Missing error handling details, but for a simple read-only tool it's adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Single parameter 'endpoint' has 0% schema coverage. Description clarifies it must be from config with protocol 'mc', and defaults allowed—adds meaning the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it reads MELSEC CPU type/code and proves MC link is alive. It distinguishes from siblings like mc_read_words/data tools by focusing on status.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implies use for checking CPU status/connectivity. Doesn't explicitly list when not to use, but context from siblings (status vs data read/write) makes it clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mc_read_bitsA
Read-only

[READ][risk=low] Batch-read bit devices from a head device.

Args:
    headdevice: MELSEC bit device, e.g. "M0", "X10", "Y20", "B0".
    endpoint: Endpoint name from config.
    count: Number of consecutive bits (1..256).

Returns dict: {endpoint, headdevice, count, bits:[bool,...]}.

Example: mc_read_bits(headdevice="M0", count=16).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
endpointNo
headdeviceYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is clear. The description adds that it is low risk and returns a dict with bits, but does not elaborate on permissions, rate limits, or error handling.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single well-structured paragraph with a risk tag, argument list, return type, and example. Every sentence adds value without waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with 3 parameters, the description adequately covers input and output format, including an example. However, it does not discuss error conditions or behavior on missing devices, which is acceptable given the tool's straightforward nature.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description compensates well by explaining each parameter: headdevice with examples, endpoint as 'from config', and count with a valid range. Minor lack of detail on endpoint nullability or config source.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it batch-reads bit devices from a head device, with a [READ] tag and low risk. It implicitly distinguishes from sibling word-reading tools, but no explicit differentiation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides an example and lists arguments but offers no guidance on when to use this tool vs alternatives like modbus_read_coils or mc_read_words. No when-not-to-use or alternative recommendations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mc_read_manyA
Read-only

[READ][risk=low] Random-read scattered word + dword devices in one request.

Args:
    endpoint: Endpoint name from config.
    word_devices: Word device names, e.g. ["D100", "D200", "M0"].
    dword_devices: Double-word device names, e.g. ["D300", "D400"].

Returns dict: {endpoint, words:[{device, value}], dwords:[{device, value}]}.

Example: mc_read_many(word_devices=["D100","D101"], dword_devices=["D200"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
word_devicesNo
dword_devicesNo

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds '[READ][risk=low]' and return format, but no additional behavioral insights beyond what annotations provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise with a clear structure (summary, args, returns, example). Slightly redundant but efficient overall.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, parameters, and return format adequately. Lacks error/edge case details, but acceptable given low complexity and no output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but description fully explains each parameter (endpoint, word_devices, dword_devices) with examples, adding significant value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states it reads scattered word and dword devices in one request ('Random-read scattered word + dword devices'), distinguishing it from siblings like mc_read_words (contiguous reads) and mc_read_bits.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implied usage: use when needing to read scattered word/dword devices from a Mitsubishi controller. No explicit when-not-to-use or alternatives are mentioned among the many sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mc_read_wordsA
Read-only

[READ][risk=low] Batch-read 16-bit word devices from a head device.

Args:
    headdevice: MELSEC word device, e.g. "D100", "W10", "R0".
    endpoint: Endpoint name from config.
    count: Number of consecutive words (1..256, capped server-side).

Returns dict: {endpoint, headdevice, count, words:[int,...]} (signed 16-bit).

Example: mc_read_words(headdevice="D100", count=8).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
endpointNo
headdeviceYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint and destructiveHint annotations, the description adds that it returns signed 16-bit integers, the count is capped server-side, and the operation is a batch read. This provides useful behavioral context without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, front-loading the risk tag and purpose, then using a clear Args/Returns/Example structure. Every sentence serves a distinct purpose with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 3 parameters, no output schema, and 0% schema coverage, the description is complete. It explains all parameters, the return format, and even provides an example, matching the tool's moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has no descriptions (0% coverage), but the description fully explains all three parameters: headdevice (with examples like D100), endpoint (from config), and count (range 1-256, capped). An example invocation is also provided, leaving no ambiguity.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'batch-read' and identifies the resource '16-bit word devices from a head device'. It clearly distinguishes this tool from siblings by focusing on word device batch reading, unlike mc_read_bits for bits or mc_read_many for mixed types.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies the tool is for reading multiple consecutive words from a head device, listing parameters and an example. While it doesn't explicitly state when not to use it, the context of sibling tools (e.g., mc_read_bits, mc_read_many) makes the specific use case clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mc_write_wordsA
Destructive

[WRITE][risk=HIGH][MOC] Write 16-bit words from a head device (off by default).

OT-DANGEROUS. Defaults to dry_run=True. Captures the BEFORE values (read-back
of the same range) and records an undo descriptor. Set dry_run=False AND
record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.

Args:
    headdevice: MELSEC word device to start at, e.g. "D100".
    values: List of 16-bit word values to write (length 1..256).
    endpoint: Endpoint name from config.
    dry_run: When True (default) returns a preview without writing.

Returns dict: dry-run → {headdevice, dry_run:true, before, would_write, note};
    applied → {headdevice, dry_run:false, before, written, applied:true, _undo_id}.

Example (preview): mc_write_words(headdevice="D100", values=[1,2,3]).
ParametersJSON Schema
NameRequiredDescriptionDefault
valuesYes
dry_runNo
endpointNo
headdeviceYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint: true), the description details the safety mechanism (dry_run default, before values capture, undo descriptor) and the need for explicit approval, fully disclosing the tool's behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with header, warnings, args, returns, and example. The Chinese language adds some redundancy but the key information is front-loaded and clear.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers all necessary aspects: input parameters, behavior (dry-run vs apply), return value structure in both modes, and an example. No output schema but the description adequately describes the output.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description explains each parameter in the Args section (headdevice, values length range, endpoint, dry_run default) and provides an example, adding significant meaning beyond the schema which has 0% description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Write 16-bit words from a head device' and differentiates itself from siblings like mc_read_words by emphasizing the write action and high risk.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidelines: defaults to dry_run, requires dry_run=false and an approver to apply. However, no direct comparison to other write tools (e.g., fins_write_words) for when to choose this over alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mechanism_library_checkA
Read-only

[READ][risk=low] What a mounted fault-mechanism library says about one candidate cause.

Three answers, and the difference between the first two is the whole point:

* ``nothing_known`` — the library has never heard of this cause. **Not** "no
  objection": a knowledge base that knows nothing about something has not
  cleared it.
* ``known``, not excluded — mechanisms for it apply here, with what would
  confirm each.
* ``known``, excluded — every mechanism for it is inapplicable to this
  equipment, so the candidate can be ruled out. That is the strong move a
  ranker cannot make.

It never confirms. Raising a candidate to `confirmed` comes from outside the
ranking — a measurement, a reproduction, or a person (D29).
ParametersJSON Schema
NameRequiredDescriptionDefault
siteNodefault
causeYes
protocolNo

TDQS

A3.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint and openWorldHint annotations, the description explains the operational meaning of open-world semantics: nothing_known is not a clearance, and known/excluded is the only strong ruling-out move. It also states plainly that the tool never confirms a cause, which is critical behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary line, bullets, and no wasted words. The final D29 reference is cryptic but does not undermine the overall clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The three-answer semantics are explained thoroughly, which is essential because there is no output schema. Missing parameter guidance for site and protocol and the absence of explicit sibling routing leave operational gaps at low schema coverage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description must supply parameter meaning. It clarifies cause as a candidate cause but does not explain site or protocol, both of which appear in the schema with no descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool queries a mounted fault-mechanism library about one candidate cause and enumerates the three possible answers. This distinguishes it from sibling mechanism_library_list, though it uses a noun phrase rather than a direct action verb.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description establishes when this tool belongs in the workflow: during ranking it can mark a cause known or excluded, but it never confirms a cause. It gives an explicit when-not, though it does not name a specific alternative tool to use for confirmation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mechanism_library_listC
Read-only

[READ][risk=low] The fault mechanisms mounted for a site, and where each came from.

ParametersJSON Schema
NameRequiredDescriptionDefault
siteNodefault

TDQS

C2.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description's [READ][risk=low] tags simply repeat that. The 'where each came from' hint gives some output-context, but the description adds no behavioral detail beyond annotations such as pagination, filtering, or side-effect notes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The main sentence is compact and front-loaded with the core meaning. However, the '[READ][risk=low]' prefix is redundant with the annotations and adds noise, preventing a perfect score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read-only tool with one optional parameter, this is minimally usable: it communicates the subject and what output to expect at a high level. But without an output schema, it should more clearly describe the return structure and what 'where each came from' means in practice.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate for the undocumented 'site' parameter. It only weakly connects to the parameter with the phrase 'for a site', but gives no details about valid values, format, or behavior when omitted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the resource ('fault mechanisms mounted for a site') and adds the provenance scope ('where each came from'), which is specific enough to understand the tool's purpose. However, it does not explicitly differentiate itself from the sibling mechanism_library_check, so it loses the fifth point.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this tool versus alternatives such as mechanism_library_check. The phrase 'for a site' implies a contextual use, but no explicit conditions, exclusions, or alternative tools are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_apply_templateA
Read-only

[READ][risk=low] Read a register block and decode it into named tags via a template.

Args:
    template: Template name (see modbus_list_templates).
    endpoint: Endpoint name from config.
    address: Absolute address of the first register read (aligns to offsets).
    count: Registers to read; omit to use the template's span.
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
addressNo
endpointNo
templateYes

TDQS

A4.3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds a '[READ][risk=low]' label consistent with annotations, but does not disclose additional behavioral traits beyond the decoding process. No contradiction, but limited extra value.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single concise paragraph with a clear front-loaded purpose and bullet-like argument listing. Every sentence adds value, no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 4 parameters, no output schema, and annotations covering read-only/non-destructive, the description adequately covers purpose, parameters, and references a related tool. It does not detail return format, but that is acceptable given the template context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must fully explain parameters. It does: template (from list), endpoint (from config), address (absolute, aligns to offsets), count (optional, defaults to template span). This adds significant meaning beyond the bare schema types.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Read a register block and decode it into named tags via a template.' It distinguishes from sibling tools like modbus_read_holding by emphasizing the template-based decoding. References modbus_list_templates for template names, providing clear context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains each argument and notes that 'count' is optional (defaulting to template's span). It implicitly guides when to use this tool (when you want decoded tags via a template) versus raw reads. Could be more explicit about when not to use it, but the context is adequate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_detect_byte_orderA
Read-only

[READ][risk=low] Auto-detect the word/byte order of a raw Modbus register block.

Pure decode logic (no device): decodes the raw registers under every candidate
order for the numeric type and scores them against a known/expected value
and/or a plausible range. Solves the "right registers, wrong endianness" pain.

Args:
    registers: Raw 16-bit register values (e.g. from modbus_read_holding).
    value_type: uint16|int16|uint32|int32|float32.
    hint: A known/expected sample value to match against.
    value_min: Lower bound of a plausible value band.
    value_max: Upper bound of a plausible value band.
ParametersJSON Schema
NameRequiredDescriptionDefault
hintNo
registersYes
value_maxNo
value_minNo
value_typeNofloat32

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it is 'pure decode logic (no device)' and explains the scoring mechanism, providing useful behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a header, a brief paragraph, and a bulleted parameter list. No unnecessary fluff, though slightly more compact could be possible.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains what the tool does and its parameters, but does not explicitly document the return value (detected order and scores). With no output schema, this omission reduces completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description includes a detailed 'Args:' section explaining each of the 5 parameters (registers, value_type, hint, value_min, value_max), compensating for the 0% schema description coverage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Auto-detect the word/byte order of a raw Modbus register block.' with a specific verb (detect) and resource (raw register block), differentiating from siblings that read from devices.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains 'Pure decode logic (no device)' implying it should be used when register values are already obtained. It mentions the pain point it solves, but does not explicitly exclude use cases or list alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_health_summaryA
Read-only

[READ][risk=low] Classify Modbus registers against warn/alarm thresholds.

Mirrors the OPC-UA health_summary classifier. Returns ok/warn/alarm/unknown
counts plus offenders.

Args:
    endpoint: Endpoint name from config.
    addresses: Register addresses to evaluate; omit to use configured tags.
    thresholds: Optional {address_str: {warn_high, alarm_high, ...}}.
    register_type: holding|input.
    decode: uint16|int16 — how to interpret each register before
        threshold comparison (int16 for bipolar/signed tags).
ParametersJSON Schema
NameRequiredDescriptionDefault
decodeNouint16
endpointNo
addressesNo
thresholdsNo
register_typeNoholding

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only, safe, non-destructive behavior. The description adds that it is a read operation with low risk, explains the decode parameter for signed registers, and mentions the return of counts and offenders. This goes beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, starting with a clear tag and purpose, followed by a bullet-like list for arguments. Every sentence adds value, and no unnecessary words are present. It is well-structured for quick parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the lack of output schema and 0% schema coverage, the description adequately covers inputs and behavior. It explains what the tool returns (counts and offenders) but could benefit from more explicit output structure details. Nonetheless, it is sufficient for an agent to understand and invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining all 5 parameters in detail. It describes the endpoint, addresses (with note to omit for configured tags), thresholds (with format), register_type, and decode (including int16 for signed tags). This is comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it classifies Modbus registers against thresholds, specifying a verb and resource. It distinguishes itself from siblings like 'opcua_health_summary' by explicitly targeting Modbus. The return of counts and offenders is also specified.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for Modbus register classification and notes it mirrors the OPC-UA version, but lacks explicit guidance on when to use it versus alternatives like 'health_summary' or other protocol-specific tools. However, the provided details are sufficient for an agent to understand its context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_list_templatesA
Read-only

[READ][risk=low] List built-in vendor register-map templates (name / type / tags).

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false; the description adds 'risk=low' and clarifies it returns template metadata, which is consistent and slightly extends transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence that is entirely on point, with no unnecessary words or content.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter, read-only listing tool with annotations covering safety, the description suffices: it tells what the tool lists and confirms it is safe and low-risk.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so schema coverage is 100%. The description does not need to add parameter meaning beyond what the schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states 'List built-in vendor register-map templates' with specific fields (name / type / tags), clearly distinguishing it from siblings like modbus_apply_template which applies a template.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

While no explicit when-not-to-use or alternatives are stated, the name and description imply it is the tool to use when needing to see available templates before applying one, which is clear enough.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_read_coilsA
Read-only

[READ][risk=low] Read coils (FC01) — digital outputs, read-only here.

Args:
    address: Starting coil address.
    endpoint: Endpoint name from config.
    count: Number of coils.
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
addressYes
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds 'READ', 'risk=low', and 'read-only here', reinforcing safety with additional context. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: a one-line purpose and three brief parameter explanations. Every sentence adds value, with no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with no output schema, the description adequately covers what it does and the parameters. It could mention return format (e.g., list of booleans) but is sufficient for invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description fully explains all three parameters: address (starting coil address), endpoint (from config), and count (number of coils), adding clear meaning beyond the schema's bare types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description specifies 'Read coils (FC01) — digital outputs, read-only here', using a specific verb and resource. It distinguishes from siblings like modbus_read_discrete by clarifying that it reads digital outputs, not inputs.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives like modbus_read_discrete or modbus_read_holding. It implies usage from the name and 'digital outputs', but lacks explicit guidance on context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_read_discreteA
Read-only

[READ][risk=low] Read discrete inputs (FC02) — read-only digital inputs.

Args:
    address: Starting discrete-input address.
    endpoint: Endpoint name from config.
    count: Number of inputs.
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
addressYes
endpointNo

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds the risk level and confirms read-only, but these mostly replicate annotation info without deeper behavioral context like rate limits or connection requirements.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: a header with risk, one-line purpose, and compact parameter list. Every sentence is necessary and front-loaded, with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

While the description covers the basic function and parameters, it lacks details on return format, valid ranges for count, or error handling. Given the simple nature of this read tool and presence of annotations, it's adequate but not complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description includes an Args section with brief explanations for address, endpoint, and count, adding meaning beyond the raw JSON schema (e.g., 'Starting discrete-input address').

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Read discrete inputs (FC02) — read-only digital inputs,' specifying the verb (read), resource (discrete inputs), and function code, distinguishing it from sibling tools like modbus_read_coils or modbus_read_holding.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading discrete inputs via Modbus FC02 but provides no explicit when-to-use or when-not-to-use guidance, nor does it reference alternatives among the many sibling read tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_read_holdingA
Read-only

[READ][risk=low] Read holding registers (FC03) with a decode hint.

Args:
    address: Starting register address.
    endpoint: Endpoint name from config.
    count: Number of registers (capped server-side).
    decode: raw|uint16|int16|uint32|int32|float32.
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
decodeNouint16
addressYes
endpointNo

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, openWorldHint=true, and destructiveHint=false. The description adds useful behavioral context: count is 'capped server-side' and decode supports specific formats (raw, uint16, etc.), which is beyond what annotations provide. No contradictions detected.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise with a front-loaded '[READ][risk=low]' tag and a list of parameters. Every sentence adds value. Could be slightly more structured but is efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema exists, and the description does not mention return values or response format. For a tool reading Modbus holding registers, the agent would benefit from knowing what is returned (e.g., decoded values, list of registers). This omission reduces completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. The description lists parameters (address, endpoint, count, decode) with brief explanations and enumerates decode options. However, endpoint ('endpoint name from config') is vague, and address lacks detail on range or behavior. Adds some value but not comprehensive.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states 'Read holding registers (FC03) with a decode hint', specifying verb (read), resource (holding registers), and function code (FC03). This distinguishes it from sibling tools like modbus_read_input or modbus_read_coils, which read different register types.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not provide explicit guidance on when to use this tool versus alternatives such as modbus_read_input, modbus_read_coils, or modbus_read_discrete. No direct comparison or when-to-use/when-not-to-use information is present.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

modbus_read_inputA
Read-only

[READ][risk=low] Read input registers (FC04) with a decode hint.

Args:
    address: Starting register address.
    endpoint: Endpoint name from config.
    count: Number of registers (capped server-side).
    decode: raw|uint16|int16|uint32|int32|float32.
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
decodeNouint16
addressYes
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds that it's a read operation with risk=low, specifies the protocol (FC04), and mentions server-side capping of count, providing useful context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, front-loading the purpose with a clear tag, and uses a bullet-style list for parameters. Every sentence is informative and there is no wasted text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has no output schema, and the description does not explain what the tool returns (e.g., decoded values or raw data). While the annotations cover safety and parameters are well-described, the missing return value description leaves a gap for effective tool use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full burden. It explains all four parameters clearly: address (starting register address), endpoint (from config), count (capped server-side), and decode (with possible values). This adds significant meaning beyond the schema types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it reads input registers using Modbus FC04, with a decode hint. This distinguishes it from sibling tools like modbus_read_holding and modbus_read_coils.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives. While the name and protocol hint at intended use, no when-to-use or when-not-to-use guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

monitor_changesA
Read-only

[READ][risk=low] Capture only the value CHANGES of a point over a bounded window.

Polls ``ref`` and returns only the changes (with timestamps), not every
sample — the OT deadband-report pattern. Works across OPC-UA / Modbus / S7 /
Mitsubishi MC / EtherNet/IP. Hard-capped by duration_s and max_changes (never
an infinite loop).

Args:
    ref: Point to watch — OPC-UA node id, Modbus address, S7 address string,
        MELSEC device, or Logix tag (per the endpoint's protocol).
    endpoint: Endpoint name from config.
    duration_s: Wall-clock window in seconds (1..120, capped server-side).
    interval_ms: Poll interval in milliseconds (>=50).
    deadband: Numeric change must exceed this to count (0 = any change).
    max_changes: Stop after this many changes (1..500, capped server-side).

Returns dict: {endpoint, ref, duration_s, interval_ms, deadband, samples_polled,
    change_count, changes:[{value, previous, source_timestamp, wall_clock}]}.

Example: monitor_changes(ref="ns=2;i=5", endpoint="line1", duration_s=20, deadband=0.5).
ParametersJSON Schema
NameRequiredDescriptionDefault
refYes
deadbandNo
endpointNo
duration_sNo
interval_msNo
max_changesNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true and destructiveHint=false. The description adds value by detailing the polling mechanism, deadband integration, and hard caps on duration and max changes, which are not evident from annotations alone.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a purpose statement, behavior explanation, parameter list, return format, and example. It is concise but covers all essential aspects without waste.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and moderate complexity, the description explains the return dictionary structure and key behaviors (capping, deadband). Minor gaps like error handling or edge cases exist, but overall it is sufficiently complete for agent usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description provides a comprehensive Args section with explanations for each of the 6 parameters, including types, defaults, and protocol-specific address formats. This fully compensates for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Capture only the value CHANGES of a point over a bounded window.' It specifies supported protocols and contrasts with continuous reading, making the purpose unambiguous and distinct from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (deadband-report pattern) and mentions caps, but it does not explicitly state when not to use it or provide alternatives. Given the large sibling list, better exclusion guidance would help.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mqtt_publishA
Destructive

[WRITE][risk=HIGH][MOC] Publish/command to an MQTT topic (off by default).

OT-DANGEROUS. A command (e.g. Sparkplug NCMD/DCMD) can change a live control
system. Defaults to dry_run=True. Set dry_run=False AND record an approver
(OPCUA_AUDIT_APPROVED_BY) to send. 未经授权勿对生产控制系统下发指令.

Reversibility depends on retain: a transient (retain=False) command has NO
inverse — delivered is delivered. A RETAINED publish overwrites durable broker
state, so the prior retained payload is captured first (returned as `before`)
and an undo descriptor recorded, as the protocol write tools do.

Args:
    topic: MQTT topic to publish to.
    payload: Message payload (string; JSON is fine).
    endpoint: Endpoint name from config.
    qos: MQTT QoS 0..2.
    retain: Set the broker retain flag.
    dry_run: When True (default) returns a preview without publishing.

Returns dict: dry-run → {topic, dry_run:true, would_publish_bytes, note};
    applied → {topic, dry_run:false, published_bytes, applied:true}, plus
    before:{found, payload, binary} when retain=True (the captured prior
    retained payload; _undo_id is added when an inverse was recorded).

Example (preview): mqtt_publish(topic="factory/line1/cmd", payload='{"setpoint":50}').
ParametersJSON Schema
NameRequiredDescriptionDefault
qosNo
topicYes
retainNo
dry_runNo
payloadYes
endpointNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations (destructiveHint=true) by explaining OT-DANGEROUS, dry-run default, reversibility tied to retain, prior retained payload capture, and undo descriptor. This is exactly the kind of behavioral context annotations alone do not provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but well-structured with warning, Args, Returns, and Example sections. Every sentence adds value, especially the critical dry-run and approval information. It is longer than average, but warranted for a high-risk write operation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description documents return formats for both dry-run and applied cases, including the `before` field. It includes an example call and covers security, reversibility, and parameter semantics, making it effectively complete for an agent to invoke and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the full burden. The Args list explains all six parameters in plain language (topic, payload, endpoint, qos, retain, dry_run), including defaults and the preview behavior. This adequately compensates for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with '[WRITE] Publish/command to an MQTT topic' which is a specific verb+resource. It clarifies the tool publishes to MQTT and supports commands (e.g., Sparkplug NCMD/DCMD), distinguishing it from siblings like mqtt_read_topic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear usage context: 'Defaults to dry_run=True' and 'Set dry_run=False AND record an approver' tells the agent when it is safe to actually send. It implies the tool should be used for command writes, but does not explicitly name alternative tools for reading; however the safety gate is explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mqtt_read_topicA
Read-only

[READ][risk=low] Plain MQTT: collect a BOUNDED set of messages from a topic.

Subscribes, gathers up to ``count`` messages or until ``timeout_s``, then
disconnects — never an open-ended loop. Payloads are decoded as JSON/text;
binary (e.g. Sparkplug protobuf) is reported with a hex preview + hint.

Args:
    endpoint: Endpoint name from config (protocol must be 'mqtt').
    topic: Topic filter (default: the endpoint's configured topic or '#').
    count: Max messages (1..500, capped server-side).
    timeout_s: Max seconds to wait (1..60, capped server-side).

Returns dict: {endpoint, topic, message_count, messages:[{topic,
    payload:{encoding, json|text|hex_preview}}]}.

Example: mqtt_read_topic(topic="factory/+/temperature", count=10, timeout_s=5).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
topicNo
endpointNo
timeout_sNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive. Description adds value by detailing subscription, disconnection after count/timeout, payload decoding (JSON/text), and binary handling with hex preview. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Description is concise at ~150 words, well-structured with summary, behavior, args, returns, and example. Each sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description fully explains return format. It covers behavior, parameter ranges, and edge cases (binary). Missing output schema is compensated. Complete for a bounded read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates well by documenting all four parameters: endpoint, topic (with default), count (1-500 capped), timeout_s (1-60 capped). Defaults and ranges are specified.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states it collects a bounded set of MQTT messages from a topic, using 'READ' label and detailed behavior. It distinguishes from siblings like mqtt_publish and sparkplug_subscribe_sample by specifying 'Plain MQTT' and bounded nature.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clarifies it is not an open-ended loop, implying use for one-time data collection. It lacks explicit 'when not to use' or direct alternative names, but the bounded nature and mention of binary handling provide context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mtconnect_assetsB
Read-only

[READ][risk=low] Assets the agent knows (cutting tools, fixtures, programs).

Args:
    endpoint: Endpoint name from config.

Returns dict: {endpoint, asset_count, assets:[{asset_type, asset_id, timestamp}]}.

Example: mtconnect_assets(endpoint="vmc1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

B3/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds a [READ][risk=low] tag consistent with readOnly and specifies the return format (dict with endpoint, asset_count, assets). It does not disclose further behavioral traits such as rate limits, authentication needs, or the meaning of 'agent knows'. With annotations covering the core safety profile, the description provides moderate additional context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (3 sentences plus example) and front-loaded with heuristic tags. Every sentence adds value, defining purpose, parameters, return format, and an example. No redundant or wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one optional parameter and no output schema, the description covers the basics: purpose, parameters, return structure, and example. However, it lacks details like what asset types are possible, how the agent determines 'known' assets, or error conditions. The completeness is adequate but not thorough.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has one optional parameter 'endpoint' with no description (0% coverage). The description mentions the parameter in the args list and gives an example, but does not explain its meaning, possible values, or where to obtain valid endpoints. Given the low schema coverage, the description should compensate more.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states that the tool returns assets (cutting tools, fixtures, programs) known to the agent, and specifies the return structure. It distinguishes from siblings like mtconnect_current which return time-series data, but does not explicitly differentiate from other asset-related tools like asset_inventory.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It does not suggest when not to use it or mention other tools as alternatives. The user must infer usage from the read-only nature and asset focus.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mtconnect_currentA
Read-only

[READ][risk=low] Latest value of every data item (a snapshot of the machine now).

Args:
    endpoint: Endpoint name from config.

Returns dict: {endpoint, observation_count, next_sequence,
    observations:[{data_item_id, type, name, timestamp, sequence, value}]}.
    Pass next_sequence as from_sequence to mtconnect_sample to stream from 'now'.

Example: mtconnect_current(endpoint="vmc1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds value by detailing the return structure (dict with fields like endpoint, observation_count, observations) and an example, and explicitly tags it as a low-risk read operation. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a concise docstring with summary, Args, Returns, and Example sections. It is front-loaded with the purpose and includes essential details in a structured format. Slightly redundant formatting (e.g., 'Args:' line) but overall efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with one optional parameter, the description combined with annotations (readOnlyHint, destructiveHint) provides complete context: purpose, usage pattern, return format, and example. No output schema needed as return structure is described.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% (no description in schema for endpoint). The description adds meaning with 'Endpoint name from config', indicating where the value comes from. This partially compensates for the lack of schema documentation, but more detail on config format would improve.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Latest value of every data item (a snapshot of the machine now)', specifying the verb (retrieve), resource (data items), and scope (current snapshot). It distinguishes from sibling mtconnect_sample by noting the streaming use of next_sequence.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on using the output as input to mtconnect_sample for streaming ('Pass next_sequence as from_sequence to mtconnect_sample to stream from now'). It implies usage context but does not explicitly state when not to use or list alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mtconnect_oee_snapshotA
Read-only

[READ][risk=low] Availability / Execution / mode / program (OEE inputs).

Surfaces the live data items an availability/performance calc needs. Does NOT
compute a single OEE % (needs planned-time + ideal-cycle context MTConnect
doesn't expose).

Args:
    endpoint: Endpoint name from config.

Returns dict: {endpoint, availability, execution, controller_mode, program,
    available (bool), running (bool), verdict ('running'|'available_idle'|'down')}.

Example: mtconnect_oee_snapshot(endpoint="vmc1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare the tool as read-only and non-destructive. The description adds valuable behavioral context: it surfaces live data items, requires an endpoint from config, and returns a dict with specific keys (including boolean flags and a verdict). No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a header line with risk/scope, a brief explanation of what it does and does not, labeled Args/Returns/Example sections. Every sentence adds value without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple snapshot tool with one parameter and no output schema, the description is remarkably complete. It covers the input, the output structure with example, and the limitation (no OEE computation). The agent has all necessary information to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description compensates by explaining the single 'endpoint' parameter as 'Endpoint name from config.' This clarifies that the parameter is a config-based reference, adding meaning beyond the schema's string type and null default.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool surfaces live OEE input data (availability, execution, mode, program) and explicitly distinguishes itself by noting it does NOT compute a single OEE percentage. It also lists the returned fields and provides an example, making the purpose unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implicitly guides usage by explaining it provides raw data needed for availability/performance calculations and does not compute OEE. This helps the agent understand when to use this tool (for OEE inputs) versus a tool like oee_compute (for final OEE %). However, it does not explicitly state alternative tools or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mtconnect_probeA
Read-only

[READ][risk=low] The device model: devices → components → data items.

The MTConnect 'schema' — what the machine can report. Call this first to
discover dataItem ids/types before reading values.

Args:
    endpoint: Endpoint name from config (protocol must be 'mtconnect').

Returns dict: {endpoint, device_count, devices:[{name, uuid, component_count,
    components:[{component, id, name, data_items:[{id, type, category, name, units}]}]}]}.

Example: mtconnect_probe(endpoint="vmc1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare read-only, and description reinforces with [READ] tag and details return structure. It explains the behavioral purpose (discovery of schema) without contradicting annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Extremely concise: two sentences plus args/returns/example. Front-loads purpose and risk level. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description provides detailed return structure and hierarchy. Includes example and accounts for open-world hint. Covers all necessary context for a simple probe tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description adds essential meaning: 'endpoint from config (protocol must be mtconnect)'. This compensates fully for the single parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly identifies it as a read-only probe for MTConnect device model. It specifies discovering dataItem ids/types before reading values, distinguishing it from siblings like mtconnect_current and mtconnect_sample.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States 'Call this first to discover dataItem ids/types before reading values,' providing clear usage ordering. While it doesn't explicitly name alternatives, the context implies this is the prerequisite probe step.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mtconnect_sampleA
Read-only

[READ][risk=low] Recent observations — a bounded snapshot OR a bounded incremental long-poll stream. Both modes are read-only and can NEVER run unbounded.

Modes:
  - snapshot (default): one /sample page of up to `count` observations. Pass
    `from_sequence` for a single incremental page starting at that sequence.
  - stream: set `max_samples` and/or `duration_s` to poll the agent
    repeatedly, advancing by the header's nextSequence each round, until a
    bound is hit. Feed the returned `next_sequence` back as `from_sequence`
    to resume exactly where you stopped.

Args:
    endpoint: Endpoint name from config.
    count: Max observations per /sample page (1..500, capped server-side).
    from_sequence: Start sequence for an incremental pull (use next_sequence
        from mtconnect_current or a prior call). None = the most recent `count`.
    interval_ms: Poll spacing between rounds in stream mode (0..10000; 0 =
        back-to-back). Client-side spacing — NOT the agent's server-push interval.
    max_samples: Total observation budget across rounds; >0 selects stream mode
        (capped at 2000). 0 = snapshot.
    duration_s: Wall-clock budget in seconds; >0 selects stream mode (capped 120).

Returns dict (snapshot): {endpoint, mode:'snapshot', requested_count,
    from_sequence, next_sequence, first_sequence, last_sequence,
    observation_count, observations:[{data_item_id, type, name, timestamp,
    sequence, value}]}.
Returns dict (stream): {endpoint, mode:'stream', from_sequence, next_sequence,
    observation_count, poll_count, stopped_reason, interval_ms, max_samples,
    observations:[...]}.

Example (snapshot): mtconnect_sample(endpoint="vmc1", count=200).
Example (stream):   mtconnect_sample(endpoint="vmc1", from_sequence=1500,
    interval_ms=1000, max_samples=500, duration_s=30).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
endpointNo
duration_sNo
interval_msNo
max_samplesNo
from_sequenceNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint and non-destructive; the description reinforces read-only behavior and adds critical details: both modes are bounded, stream polls with client-side spacing, and returns include stopping reason and sequence advancement. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections, bullet points, and examples. It is somewhat lengthy but justified by the complexity of two modes and multiple parameters. A minor cut could enhance conciseness without losing key information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description covers return structures for both modes, including all fields and examples. It addresses all aspects: purpose, behavior, parameters, and usage context. The description is fully self-sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All six parameters are explained in detail, including defaults, caps, and mode selection logic. Since the input schema has 0% description coverage, the description fully compensates, making parameter semantics complete and actionable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: providing recent observations as a bounded snapshot or bounded incremental long-poll stream. It defines two modes (snapshot and stream) and distinguishes them, preventing confusion with sibling tools like mtconnect_current or mtconnect_probe. The verb 'sample' and resource 'observations' are specific and well-defined.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use each mode: snapshot for a single page, stream for continuous polling with bounds. It provides examples and mentions using from_sequence from mtconnect_current. However, it does not explicitly compare against other sibling tools for choosing between them, which slightly reduces clarity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

oee_computeA
Read-only

[READ][risk=low] OEE = Availability × Performance × Quality (+ loss/energy depth).

Args:
    planned_time_s: Planned production time (seconds).
    run_time_s: Actual running time (seconds) — planned minus downtime.
    ideal_cycle_time_s: Ideal/nameplate cycle time per part (seconds).
    total_count: Total parts produced.
    good_count: Good (non-reject) parts produced.
    breakdown_time_s: Optional — unplanned-stop seconds (splits availability loss).
    setup_time_s: Optional — changeover/setup seconds (splits availability loss).
    minor_stop_time_s: Optional — minor-stop seconds (splits performance loss;
        the remainder is speed loss).
    startup_reject_count: Optional — startup/warm-up rejects (splits quality
        loss; the remainder is production rejects).
    actual_kwh: Optional — measured energy for this run; enables the energy block.
    baseline_kwh: Optional — expected/baseline energy for the actual-vs-baseline
        deviation verdict.
    emission_factor_kg_per_kwh: Optional — carbon factor (kg CO2e/kWh). Default is
        a flagged placeholder (see the tool's carbon note); pass the grid's value.
    energy_tolerance: ± band (fraction) for the over/under/on-target verdict.

Returns dict: OEE factors + oee/oee_pct + inputs + losses, plus
    ``six_big_losses`` (breakdown/setup/minor-stops/speed/startup/production-reject
    time-ladder that sums with OEE to 100%) and, when ``actual_kwh`` is given,
    ``energy`` (kwh_per_unit, carbon, and baseline deviation).

Example: oee_compute(planned_time_s=28800, run_time_s=25200,
    ideal_cycle_time_s=2.0, total_count=12000, good_count=11800,
    setup_time_s=1800, actual_kwh=940, baseline_kwh=880).
ParametersJSON Schema
NameRequiredDescriptionDefault
actual_kwhNo
good_countYes
run_time_sYes
total_countYes
baseline_kwhNo
setup_time_sNo
planned_time_sYes
breakdown_time_sNo
energy_toleranceNo
minor_stop_time_sNo
ideal_cycle_time_sYes
startup_reject_countNo
emission_factor_kg_per_kwhNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds value beyond annotations by detailing the return structure (six_big_losses, energy block) and explaining how optional parameters split losses. It explicitly declares '[READ][risk=low]', which aligns with the readOnlyHint = true annotation. There is no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but well-organized: a formula header, labeled Args list, Returns section, and an example. Every sentence serves a purpose. Slightly long due to thoroughness, but not wasteful. The front-loaded formula quickly conveys the core calculation.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (13 parameters, no output schema), the description is remarkably complete. It explains all inputs, return keys, loss decomposition, and energy computation. The example demonstrates typical usage. No gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description fully compensates by explaining each parameter in detail (e.g., 'planned_time_s: Planned production time (seconds)'). It provides syntax, units, and behavior for all 13 parameters, including optional ones. This is excellent semantic help.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it computes OEE using the formula 'Availability × Performance × Quality' and lists inputs and outputs. It specifies the verb 'compute' and resource 'OEE', making the purpose very clear. However, it does not differentiate itself from sibling tools like 'oee_multidim', which might also compute OEE in a different dimension.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. It does not mention prerequisites, context, or limitations. The description only explains what the tool does, not when it should be invoked.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

oee_multidimA
Read-only

[READ][risk=low] Aggregate OEE (+ optional energy) across dimensions.

Args:
    records: Labelled records — {<dimension labels>, planned_time_s, run_time_s,
        ideal_cycle_time_s, total_count, good_count} plus optional actual_kwh /
        baseline_kwh to enable the energy rollup.
    dimensions: Dimension keys to group by (default ['machine','part','shift']);
        use ['shift'] for the classic by-shift energy comparison.
    emission_factor_kg_per_kwh: Optional carbon factor (kg CO2e/kWh); default is a
        flagged placeholder — pass the grid's published value.
    energy_tolerance: ± band (fraction) for the actual-vs-baseline verdict.

Returns dict: {dimensions, group_count, mean_oee, worst_performers:[...],
    matrix:[{dimensions, oee, oee_pct, availability, performance, quality,
    energy?}]}. When any record carries energy, adds an ``energy_baseline`` block
    that flags cross-group deviation anomalies (tolerance + robust-outlier rules).

Example: oee_multidim(records=[{"shift":"day","planned_time_s":28800,
    "run_time_s":25000,"ideal_cycle_time_s":2,"total_count":12000,
    "good_count":11800,"actual_kwh":940,"baseline_kwh":880}], dimensions=["shift"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
recordsYes
dimensionsNo
energy_toleranceNo
emission_factor_kg_per_kwhNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral details: it explicitly states the risk level ('risk=low'), describes the return structure, and explains the conditional energy block. This adds value beyond annotations without contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for Args, Returns, and an Example. It is fairly long but each part adds value. It could be slightly more concise, but it remains readable and informative.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 4 parameters, no output schema, and complex behavior, the description comprehensively covers inputs, outputs, and includes an example. It explains the return dict structure and the conditional energy block. It is sufficiently complete for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage for properties. The description fully compensates by explaining each parameter: what records must contain (fields like planned_time_s, run_time_s, etc.), the purpose of dimensions, the default for emission_factor_kg_per_kwh, and the role of energy_tolerance. This adds meaning well beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it aggregates OEE (plus optional energy) across dimensions. The verb 'Aggregate' and resource 'OEE' are specific. It distinguishes from siblings like 'oee_compute' by highlighting multi-dimension grouping and energy inclusion, but does not explicitly name alternatives.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides usage guidance: it explains the default dimensions and suggests using ['shift'] for classic by-shift energy comparison. It does not explicitly state when not to use this tool or name alternative tools, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_alarm_eventsA
Read-only

[READ][risk=low] Timestamped Alarms & Conditions via a bounded event subscription.

Subscribes to the Server object for Condition-type events, optionally calls
ConditionRefresh so currently-retained conditions are re-announced WITH their
original event Time, listens for at most duration_s seconds, unsubscribes.
The timed complement to opcua_read_alarms: each event carries the server's own
timestamp, so RCA can time-localize alarm evidence. Requires a server that
implements A&C event subscriptions (待核实 per server); an empty result can mean
no events in the window OR no A&C support — pair with opcua_read_alarms.

Args:
    endpoint: Endpoint name from config.
    duration_s: Listen window in seconds (0..60, default 5).
    refresh: Call ConditionRefresh to replay retained/active conditions (default true).
    max_events: Stop after this many events (1..200).

Returns dict: {endpoint, duration_s, condition_refresh, refresh_error, event_count,
    events:[{source, message, severity, state (ACTIVE|RTN|EVENT), timestamp}], note}.

Example: opcua_alarm_events(endpoint="line1", duration_s=5).
ParametersJSON Schema
NameRequiredDescriptionDefault
refreshNo
endpointNo
duration_sNo
max_eventsNo

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true, openWorldHint=true, destructiveHint=false. The description greatly expands beyond these by detailing the subscription lifecycle: subscribing to Server, optionally calling ConditionRefresh, listening for a bounded duration, and unsubscribing. It also explains the meaning of the returned timestamp field and potential reasons for empty results. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections (summary, usage notes, args, returns, example) and front-loaded with the core purpose. However, it is somewhat verbose, including a Chinese note (待核实 per server) and extra notes about RCA. Could be slightly more concise without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 4 parameters, no output schema, and moderate complexity, the description covers all necessary aspects: parameter semantics, return format, side effects (unsubscribes), potential edge cases (empty results), and an example. No gaps are evident.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must define all parameters. It does so comprehensively: endpoint (from config), duration_s (0-60, default 5), refresh (default true, calls ConditionRefresh), max_events (1-200, stop after). Defaults, ranges, and behaviors are all explained. This adds full meaning beyond the schema's basic type definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Timestamped Alarms & Conditions via a bounded event subscription.' It uses specific verbs like 'Subscribes', 'listens', 'unsubscribes', and explicitly distinguishes itself from the sibling tool 'opcua_read_alarms' by calling itself 'the timed complement'. The scope and resource ('Condition-type events on Server object') are unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use: it requires a server that implements A&C event subscriptions. It warns about empty results meaning either no events in window OR no A&C support, and recommends pairing with 'opcua_read_alarms' for disambiguation. This covers both when-to-use and when-not-to, and offers an alternative.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_anomaly_scanA
Read-only

[READ][risk=low] Sample a node over a bounded window and flag statistical outliers.

Computes mean/stddev/min/max and flags samples outside mean ± sigma*stddev.
Simple statistics only — no ML, no persisted model.

Args:
    node_id: The OPC-UA node id to scan.
    endpoint: Endpoint name from config.
    samples: Max samples (capped server-side).
    interval_ms: Delay between samples in milliseconds.
    sigma: Outlier band width in standard deviations.
ParametersJSON Schema
NameRequiredDescriptionDefault
sigmaNo
node_idYes
samplesNo
endpointNo
interval_msNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Description adds context about computation (mean/stddev/min/max, outlier flagging, no persistence) beyond annotations, which already declare readOnlyHint=true, destructiveHint=false, openWorldHint=true. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, with a header line, a brief statistics line, and a clear Args list. Every sentence adds value and there is no redundant information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the computation and parameters but does not describe the output format or return value. Given no output schema, this is a gap for a tool with moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% coverage, but the description explains all 5 parameters in the Args section, adding meaning like 'capped server-side' and 'delay between samples', which compensates for lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses specific verbs 'sample' and 'flag', and clearly identifies the resource as an OPC-UA node, distinguishing it from generic sibling tools like 'anomaly_scan'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States 'Simple statistics only — no ML, no persisted model', indicating when to use this tool over more complex alternatives. However, it does not explicitly mention when not to use it or name specific siblings in the guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_browseA
Read-only

[READ][risk=low] Browse the OPC-UA node tree from a node id (bounded depth).

Args:
    node_id: Root node id (default i=85, the Objects folder).
    endpoint: Endpoint name from config.
    depth: Bounded browse depth (capped server-side).
ParametersJSON Schema
NameRequiredDescriptionDefault
depthNo
node_idNoi=85
endpointNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, covering safety. The description adds '[READ][risk=low]' and notes that depth is capped server-side, which gives useful behavioral context beyond annotations. However, it does not specify behavior for invalid node_id or endpoint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: a one-line header with risk tag and a brief action, followed by three bullet-point parameter descriptions. Every sentence adds value with no redundancy or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simplicity of a browse tool and that annotations cover safety, the description adequately explains purpose and parameters. However, the lack of an output schema means the description should ideally describe what the tool returns (e.g., a tree of nodes). It does not, leaving a gap for the agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, so the description must compensate. It provides brief but meaningful explanations for all three parameters: node_id (with default and example), endpoint (from config), and depth (bounded). This adds sufficient semantic value for parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'browse', the resource 'OPC-UA node tree from a node id', and adds 'bounded depth'. This effectively distinguishes it from sibling tools like opcua_read_node which read values, and opcua_discover_tags which may have different scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives (e.g., opcua_read_node, opcua_subscribe_sample). It does not mention prerequisites, exclusions, or typical use cases.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_diagnose_connectionA
Read-only

[READ][risk=low] Diagnose why an OPC-UA endpoint won't connect — a classified verdict.

Attempts a connect (no writes, disconnects immediately) and classifies any
failure into the well-known OPC-UA buckets instead of returning a raw error,
each with a concrete next step:
certificate (server doesn't trust our client cert) · auth (user/password) ·
security_policy (policy/mode mismatch) · port_closed · dns · firewall_timeout ·
unreachable · config (bad endpoint_url / connector not installed) · ok.

Args:
    endpoint: Endpoint name from config; omit to use the default endpoint.

Returns dict: {endpoint, reachable (bool), class, diagnosis, remediation, detail}.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true and destructiveHint=false. The description adds significant behavioral context: it attempts a connect but no writes, disconnects immediately, and classifies failures into specific buckets. This goes beyond annotations and provides valuable transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary line, process explanation, failure categories, and Args section. It is informative without being overly verbose. A slight reduction could be possible, but every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description describes the return dict structure. It covers input, behavior, and output. Minor gaps: no explicit mention of what happens if endpoint is invalid or how the test is performed, but overall sufficient for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has one optional parameter with 0% description coverage. The description compensates fully by explaining the endpoint parameter: 'Endpoint name from config; omit to use the default endpoint.' This adds meaning beyond the schema's type/title.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool diagnoses why an OPC-UA endpoint won't connect, with a specific verb 'Diagnose' and resource 'OPC-UA endpoint connection'. It distinguishes well from sibling OPC-UA tools like opcua_browse or opcua_read_node by focusing on connection diagnosis.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use: to diagnose connection failures. It implies alternatives (e.g., other OPC-UA tools for different tasks) but does not explicitly exclude them or provide direct contrast. The failure classification and next steps give clear context for appropriate use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_discover_tagsA
Read-only

[READ][risk=low] Auto-discover OPC-UA tags and build a semantic asset model.

Walks the address space, collects every Variable node, and enriches each with
datatype / value / engineering-unit / a heuristic semantic class (temperature,
pressure, flow, setpoint, alarm, state, …) and a suggested clean alias. Tags
are grouped into assets by their browse path, and a naming-quality report
flags alias collisions + cryptic names. Aliases are ADVISORY — nothing is
written back to the server (a server-side rename would be OT-dangerous).

Args:
    endpoint: Endpoint name from config; omit to use the default endpoint.
    root: Root node id to discover from (default i=85, the Objects folder).
    max_depth: Bounded recursion depth (capped server-side at 8).
    include_standard: Include OPC-UA namespace-0 server infrastructure
        (default False — only real process tags in vendor namespaces).

Returns dict: {endpoint, root, tag_count, asset_count,
    assets:[{asset, tag_count, classes, tags:[{node_id, browse_name,
    browse_path, datatype, value, unit, writable, class, suggested_alias}]}],
    naming_quality:{alias_collisions, cryptic_names, verdict}}.
ParametersJSON Schema
NameRequiredDescriptionDefault
rootNoi=85
endpointNo
max_depthNo
include_standardNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds valuable context: aliases are 'ADVISORY — nothing is written back', server-side rename is 'OT-dangerous', max_depth is 'capped server-side at 8', and it describes the exact actions taken (walk address space, collect nodes, enrich). This goes well beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a clear header, narrative paragraph, Args list, and Returns block. It is informative without being overly verbose, though the Args section could be slightly more compact. Every sentence adds value; no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With 4 parameters, no output schema, and a complex return structure, the description provides a detailed Returns dict including endpoint, root, tag_count, asset_count, assets (with nested tag details), and naming_quality (with alias_collisions, cryptic_names, verdict). This gives the agent a complete picture of what to expect, fully compensating for the absent output schema.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description provides extensive parameter documentation in the Args block: endpoint, root, max_depth, include_standard—including defaults, meanings (e.g., 'root: Root node id to discover from (default i=85, the Objects folder)'), and constraints (e.g., 'capped server-side at 8'). This fully compensates for the missing schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it 'Auto-discover OPC-UA tags and build a semantic asset model' with specific actions: walk address space, collect Variable nodes, enrich with metadata, group into assets, and report naming quality. It distinguishes from siblings like opcua_browse (which just browses nodes) and opcua_read_node (which reads specific nodes).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives like opcua_browse or opcua_read_node. It implies usage for initial discovery through the '[READ][risk=low]' tag and the mention of 'advisory' aliases, but lacks explicit when-to-use or when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_health_summaryA
Read-only

[READ][risk=low] Classify OPC-UA tag node-ids against warn/alarm thresholds.

Returns ok/warn/alarm/unknown counts plus the offending tags. Thresholds
come from config tags, or per-ref overrides in ``thresholds``.

Args:
    endpoint: Endpoint name from config.
    node_ids: Tag node ids to evaluate; omit to use configured tags.
    thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}}.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
node_idsNo
thresholdsNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds that it classifies and returns counts and offending tags, which is consistent. No contradictions and additional behavioral context is provided.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary line, explanation, and Args block. It is concise with no redundant information, though could be slightly more compact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the input and general output but lacks detail on the exact return format or behavior for edge cases (e.g., empty results). Without an output schema, more detail would help, but it is adequate for a straightforward read tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the burden. It explains all three parameters (endpoint, node_ids, thresholds) with type and purpose, including the structure of thresholds. This adds significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear verb 'Classify' and resource 'OPC-UA tag node-ids', and specifies output (ok/warn/alarm/unknown counts and offending tags). This distinguishes it from sibling tools like opcua_read_alarms or opcua_anomaly_scan.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains that thresholds come from config or overrides, implying usage context. It does not explicitly list when not to use or compare with alternatives, but the purpose is clear enough for an agent to decide.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_read_alarmsA
Read-only

[READ][risk=low] Best-effort surfacing of active alarm/condition booleans (untimed).

Browses the address space (bounded) for alarm-like boolean nodes reading
True. Untimed by nature — for servers with A&C event support use
opcua_alarm_events, which returns conditions WITH the server's timestamps.

Args:
    endpoint: Endpoint name from config.
    node_id: Root node id to scan from (default i=85).
    depth: Bounded scan depth.
ParametersJSON Schema
NameRequiredDescriptionDefault
depthNo
node_idNoi=85
endpointNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly, openWorld, and non-destructive. The description adds context of 'best-effort', 'bounded scan', and 'untimed', but does not detail return format or error behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Highly concise: a one-line summary followed by a clear Args section. Every sentence adds value, no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers purpose, usage, parameters, and behavior adequately. No output schema exists, so return format is not detailed, but the description implies a list of active alarms.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage. The description explains all three parameters (endpoint, node_id, depth) with defaults and purpose, compensating for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it surfaces active alarm/condition booleans without timestamps, and distinguishes from the sibling opcua_alarm_events which provides timestamped events.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly advises using opcua_alarm_events when timestamped events are needed, and notes the untimed nature of this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_read_historyA
Read-only

[READ][risk=low] OPC-UA Historical Access (HDA): raw historical values over a window.

Reads stored history for a node via the server's HistoryRead service, bounded
by ``max_points``. Returns a clear 'unsupported' note when the server does not
historize the node (no crash).

Args:
    node_id: The OPC-UA node id to read history for (e.g. ns=2;i=5).
    endpoint: Endpoint name from config.
    start: ISO-8601 window start (default: 1 hour before end).
    end: ISO-8601 window end (default: now).
    max_points: Max points to return (capped server-side at 2000).

Returns dict: {node_id, supported (bool), start, end, count,
    values:[{value, source_timestamp, status_code}]}.

Example: opcua_read_history(node_id="ns=2;i=5", start="2026-06-28T08:00:00Z").
ParametersJSON Schema
NameRequiredDescriptionDefault
endNo
startNo
node_idYes
endpointNo
max_pointsNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint, openWorldHint, destructiveHint), the description reveals that it returns an 'unsupported' note (no crash) and that max_points is capped server-side at 2000. This adds meaningful behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a tag line, a one-sentence summary, parameter descriptions, return format, and an example. Every sentence is necessary and front-loaded with key information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers parameters, behavioral notes, and the return dict structure. It is largely complete given no output schema, though it could elaborate on status_code values.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully explains all 5 parameters: node_id, endpoint, start, end, max_points. It provides formats, defaults, and an example, adding significant value over the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with '[READ][risk=low] OPC-UA Historical Access (HDA): raw historical values over a window.' This clearly states the tool reads historical data and distinguishes it from other OPC-UA tools like browse or read node.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description does not explicitly state when to use this tool versus alternatives like historian_query or opcua_read_node. It mentions error handling for unsupported nodes, but no guidance on selection criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_read_manyA
Read-only

[READ][risk=low] Batch-read multiple node ids in one session (bounded count).

Args:
    node_ids: List of OPC-UA node ids to read.
    endpoint: Endpoint name from config.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
node_idsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds 'risk=low' and 'bounded count', providing useful limits. No contradictions. It complements annotations well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, using a single line for the header and a brief Args section. Every sentence adds value, with no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema and a simple input, the description covers the main semantics. However, it does not describe the return format (e.g., a list of values or statuses), which would help an agent anticipate results. The rich annotations partially compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains 'node_ids: List of OPC-UA node ids to read' and 'endpoint: Endpoint name from config', adding meaning beyond the schema's type-only definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action 'Batch-read multiple node ids' and the resource 'node ids', distinguishing it from single-read or browse tools. The prefix '[READ]' and 'risk=low' further clarify its purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions 'in one session (bounded count)', implying efficient batch reading, but provides no explicit guidance on when to use this tool versus alternatives like opcua_read_node or opcua_browse. No exclusion criteria or context are given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_read_nodeA
Read-only

[READ][risk=low] Read one node: value, datatype, source timestamp, status code.

Args:
    node_id: The OPC-UA node id to read (e.g. ns=2;i=5).
    endpoint: Endpoint name from config.
ParametersJSON Schema
NameRequiredDescriptionDefault
node_idYes
endpointNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint and non-destructive behavior. The description adds a '[READ][risk=low]' tag and explicitly lists the return fields (value, datatype, source timestamp, status code), providing additional behavioral context beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with two short sentences plus an Args list. It front-loads the purpose with '[READ]' and efficiently covers all necessary information without any redundant text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple read tool with well-described parameters and annotations covering safety, the description is complete. It explains what is read, how to specify the node, and the endpoint parameter, and implies the output fields. No output schema is needed given the succinctness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, but the description fully compensates by explaining both parameters: node_id is described with an example format (ns=2;i=5) and endpoint as 'Endpoint name from config.' This adds meaningful context that the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it reads one OPC-UA node and lists the returned fields (value, datatype, source timestamp, status code). This distinguishes it from sibling tools like opcua_read_many (reads multiple nodes) and opcua_browse (lists nodes).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading a single node but does not explicitly state when to use this tool versus alternatives such as opcua_read_many or when not to use it. No exclusions are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_server_infoA
Read-only

[READ][risk=low] OPC-UA server status, build info, and namespace array.

Args:
    endpoint: Endpoint name from config; omit to use the default endpoint.
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds behavioral context with '[READ][risk=low]' and lists specific data returned (status, build info, namespace array), aligning with and enriching the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences: a front-loaded summary line and a parameter explanation. Every word is necessary, with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a simple single-parameter tool with no output schema, the description covers purpose and parameter meaning. It could be improved by noting return format or error conditions, but is sufficient for a read-only server info query.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates by explaining the 'endpoint' parameter pulls from config and has a default, adding meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states the tool reads OPC-UA server status, build info, and namespace array. The '[READ]' prefix and specific data types distinguish it from sibling tools like opcua_browse or opcua_read_node.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use for server metadata via the parameter instruction 'Endpoint name from config; omit to use the default endpoint.' It does not explicitly exclude other use cases or name alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

opcua_subscribe_sampleA
Read-only

[READ][risk=low] Sample a node a BOUNDED number of times, then return (never loops).

Args:
    node_id: The OPC-UA node id to sample.
    endpoint: Endpoint name from config.
    samples: Max number of readings (capped server-side).
    interval_ms: Delay between readings in milliseconds.
    timeout_s: Hard wall-clock cap in seconds (capped server-side).
ParametersJSON Schema
NameRequiredDescriptionDefault
node_idYes
samplesNo
endpointNo
timeout_sNo
interval_msNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only. The description adds that sampling is bounded and capped server-side, which goes beyond the annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise: one summary sentence followed by a clear list of arguments. No unnecessary words; every part adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

While the tool's behavior is well-described, the return format is not mentioned. With no output schema, the description should specify what is returned (e.g., list of values with timestamps). This omission reduces completeness for an agent needing to parse results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining each parameter's role: node_id is the node, endpoint from config, samples max readings capped, interval_ms delay, timeout_s hard cap. This adds significant meaning beyond the schema's default values.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool samples an OPC-UA node a bounded number of times and returns, never looping. The 'READ' tag and explicit boundedness distinguish it from continuous subscriptions and other read tools in the sibling list.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when a finite number of samples is needed rather than continuous monitoring. It does not explicitly exclude alternatives or mention related tools like opcua_read_node or sparkplug_subscribe_sample, but the bounded nature provides clear context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

pdm_forecastA
Read-only

[READ][risk=low] Forecast a value's trend + time until it crosses a warn/alarm limit.

The predictive step above baseline_check (which flags a violation that already happened): fits a
robust Theil-Sen trend to the recent history and, if it continues, estimates the ETA to the
nearest limit in the direction of travel — the early warning that makes maintenance predictive
(inverter/turbine degradation, bearing drift, filter clogging). Refuses thin history; read-only,
pure over the provided series; no device I/O.

Beyond the trend, the result deepens into three explainable, stdlib-only views: a degradation
'pattern' (gradual vs sudden vs cyclic), a remaining-useful-life 'rul' block when degrading
(linear + exponential extrapolation to the limit, a confidence band from the slope spread, and a
fit R^2), and optional time-domain 'waveform' features (RMS/kurtosis/crest/... for
vibration-type signals). Each states its own uncertainty rather than guessing.

Args:
    series: Time-ordered samples: [{value, timestamp?}] (timestamp ISO-8601; if all present the
        ETA is in seconds, otherwise in samples). >= 30 numeric samples required.
    warn_high/alarm_high/warn_low/alarm_low: Optional limits; the forecast targets the nearest
        one in the trend's direction (rising → highs, falling → lows).
    imminent_within_s: ETA (seconds) at/under which status is 'imminent' (default 86400 = 24h).
    include_waveform: Add the time-domain 'waveform' feature block (default True). Set False for
        slow trend-only signals where vibration features do not apply.

Returns dict: {status (insufficient_data|stable|degrading|imminent), samples, direction,
    slope_per_unit, unit (s|samples), current, limit:{name,value}, eta_to_limit,
    degradation:{pattern,confidence,rationale,metrics},
    waveform:{rms,crest_factor,kurtosis,...} (when include_waveform),
    rul:{linear,exponential,eta_band,recommended_model,confidence,...} (when degrading)}.

Example: pdm_forecast(series=[{"value": 62.1, "timestamp": "2026-07-12T00:00:00Z"}, ...],
    warn_high=75, alarm_high=85).
ParametersJSON Schema
NameRequiredDescriptionDefault
seriesYes
warn_lowNo
alarm_lowNo
warn_highNo
alarm_highNo
include_waveformNo
imminent_within_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that the tool is read-only and performs no device I/O, consistent with annotations (`readOnlyHint: true`, `destructiveHint: false`). It also details the computational approach (robust Theil-Sen trend) and the conditions under which the tool returns `insufficient_data`. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured but somewhat verbose. It front-loads a concise one-line summary, then elaborates on context, parameters, and return structure. Some details (e.g., specific statistical method, mention of 'stdlib-only views') could be trimmed, but the overall clarity and organization justify a score of 4.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description thoroughly documents the return structure including `status`, `direction`, `degradation`, `waveform`, `rul`, etc. It covers parameter semantics, behavior, and an example, making the tool fully understandable for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by providing detailed explanations for each parameter: `series` (time-ordered, required, format), limits (optional, targeted by direction), `include_waveform` (default True, when to set False), and `imminent_within_s` (default 86400). An example is also given, adding significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool forecasts a value's trend and time until it crosses limits. It uses specific verbs and resources ('forecast a value's trend + time') and distinguishes itself from the sibling `baseline_check` by noting it is predictive rather than reactive.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states this tool is a predictive step above `baseline_check` and provides context for when it should be used (e.g., for inverter/turbine degradation, bearing drift). It also mentions it refuses thin history, giving implicit guidance on prerequisites. However, it does not explicitly state when not to use it or provide direct alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_driftA
Read-only

[READ][risk=low] Has this program changed since its approved snapshot, and what moved?

Three verdicts, and the wording of each is load-bearing. **identical** means
the same SHA-256 and nothing else earns the word. **logic_changed** means the
extracted structure differs — reported per block, naming which categories
(variables / calls / branches / timers_counters) moved. **changed_outside_
extracted_structure** means the bytes differ while every block fingerprint
matched: usually comments or formatting, but these parsers extract structure
rather than parse a grammar, so a real change inside a construct they do not
model looks identical from here. Calling that "documentation only" would be
the comfortable reading of evidence that does not support it, so it is not
called that, and it is not a clearance — line and comment counts are reported
beside it so a reviewer can see which way it leans.

Nothing here decides whether a change was authorised; that is change control's
job. No device is touched — this reads a file a person exported.

Args:
    path: The current exported program file to check.
    name: Tracked program name (defaults to the file's stem).
    against: Snapshot id to compare with; default is the latest.

Returns dict: {program, name_source, baseline:{snapshot_id, taken_at, label,
    source_file}, current:{source_file}, verdict, content_changed,
    structure_changed, content_sha256:{before, after}, blocks:{added[],
    removed[], changed:[{block, kind, line, previous_line, changed[]}],
    unchanged}, totals:{block_count, line_count, comment_count}, parse_errors,
    note, advisory}.

Example: plc_program_drift(path="~/exports/Line3_today.scl", name="Line3").
ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
pathYes
againstNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the readOnlyHint annotation, the description discloses important behavior: no device is touched, the verdicts are load-bearing, and 'changed_outside_extracted_structure' does not mean 'documentation only' due to parser limitations. It also clarifies that this tool does not determine authorization. These are exactly the non-obvious behavioral traits an agent needs, and no annotation contradiction exists.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Though detailed, the description is well-structured and front-loaded: purpose, then verdict semantics, then caveats, then parameters, return format, and an example. Every section earns its place, especially the verdict definitions and parser caveat, which are essential for correct interpretation of results.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description compensates by listing the complete return dict structure, including nested fields like blocks and totals. It also covers parameters, defaults, example usage, and risk context. For a tool with this complexity, nothing essential is missing for an agent to select and invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries full responsibility for parameter meaning. It documents all three parameters — path, name, and against — including defaults ('file stem', 'latest'). It also explains what 'against' refers to as a snapshot id, which the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening question states exactly what the tool does: determine whether a program changed since its approved snapshot and identify what moved. It defines the three verdicts precisely, making the tool's scope and semantics unambiguous. This clearly separates it from snapshot creation, history, and other PLC program analysis tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear usage context: it operates on an exported file, touches no device, and does not decide whether changes were authorized. It implicitly tells the agent when to use this tool and explicitly warns against using it for change-control decisions. However, it does not name alternative sibling tools such as baseline_check or plc_program_history or state when to prefer them.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_historyA
Read-only

[READ][risk=low] Tracked programs, or one program's snapshot history.

Local read of the program-baseline store — no file is parsed and no device is
touched. Nothing is ever pruned automatically: a change-control history that
quietly drops last quarter's baseline is worse than one that grows, and a
stored row is block names, hashes and counts rather than source. Removing history is a
deliberate act and is CLI-only (`iaiops program forget`) — deleting
change-control evidence should not be one tool call away.

Args:
    name: Tracked program name. Omit for the list of every tracked program.

Returns dict (listing): {store, program_count, programs:[{program,
    snapshot_count, latest, latest_taken_at}]}; (one program): {store,
    program, snapshot_count, snapshots:[{snapshot_id, taken_at, source_file,
    content_sha256, label, note}]}.

Example: plc_program_history(name="Line3").
ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations, the description adds important behavioral details: no automatic pruning, removal is deliberately CLI-only, stored data contains block names/hashes/counts rather than source, and no file or device is touched. This substantially exceeds what the annotations already convey.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the read-only tag and core purpose, then uses clear sections for Args, Returns, and Example. The prose about pruning is somewhat elaborate, but it earns its place by explaining why history is never automatically dropped and why deletion is restricted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema present, the description fully documents both possible return shapes: the listing form and the single-program snapshot form. The optional parameter behavior and an example are also present, making the tool straightforward to invoke correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, but the description fully compensates for the single parameter: it explains what `name` selects and the effect of omitting it. The example reinforces the expected invocation syntax.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies a specific verb ('read') and resource ('program-baseline store'), and the first sentence distinguishes between two behaviors: listing tracked programs versus viewing one program's snapshot history. It also differentiates from device-reading siblings by stating 'no file is parsed and no device is touched.'

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Clear context is provided: this tool reads local program-baseline history, and the optional `name` behavior is explained. It does not explicitly name sibling tools to use instead, but the framing and scoping make the use case sufficiently clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_outlineA
Read-only

[READ][risk=low] Structural outline of an EXPORTED PLC program file.

Parses one exported text file (Siemens SCL/ST .scl/.st, AWL/STL .awl,
Rockwell Studio 5000 .L5X — .txt is content-sniffed) and returns blocks
(FB/FC/OB/DB/routines/AOIs) with VAR sections, IF/CASE branch inventory,
timers/counters, and the call graph. Never uploads from a live PLC; reads
exactly the named file (≤5 MB). Every element cites source_file + line
(rung number for L5X ladder) — quote those citations when explaining.
Malformed sections degrade to entries in parse_errors, never a crash.

Args:
    path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).

Returns dict: {source_file, format, stats:{blocks, variables, call_edges,
    branches, timers_counters, comments, lines, parse_errors},
    blocks:[{name, kind, language, line, end_line, variables (≤100,
    variables_truncated), calls, branches, timers_counters, networks,
    comment}] (≤50, blocks_truncated), call_graph:[{caller, callee,
    source_file, line}], parse_errors, citation_note}.

Example: plc_program_outline(path="~/exports/Line3_Conveyor.scl").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnly and non-destructive. The description adds valuable details: file size limit, format detection, error handling (malformed sections yield parse_errors, not crashes), truncation limits, and citation requirements. This goes beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a clear [READ][risk=low] tag and a succinct summary sentence. It efficiently layers details about capabilities, parameters, return structure, and example, without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (parsing multiple PLC file formats, returning structured data with many fields) and absence of an output schema, the description fully covers the return structure, constraints, and error behavior, leaving no gaps for an AI agent to invoke incorrectly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The single parameter 'path' is described with full file type specifications, size limit, and an example. Schema coverage is 0%, so the description compensates well by adding meaning beyond the schema's bare type definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns a 'structural outline of an EXPORTED PLC program file', specifies supported formats, and explicitly distinguishes from live PLC interactions, making its purpose distinct from siblings like plc_program_xref.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit usage context: 'Never uploads from a live PLC; reads exactly the named file (≤5 MB)' and lists supported file types. It implies when to use (offline file analysis) but lacks explicit alternatives or when-not-to-use scenarios, though sibling names offer clues.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_sectionA
Read-only

[READ][risk=low] Source text of ONE named block from an exported program.

Returns the exact source of a single block (FB/FC/OB/DB name for SCL/AWL;
Program.Routine or routine name for L5X — rungs are rendered as
'[rung N] ...'), capped at 200 lines with an explicit truncated flag, so
the agent reads exactly the section it is explaining instead of guessing.
Unknown block names fail with the list of available blocks.

Args:
    path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
    block: Block/routine name (case-insensitive; quotes optional).

Returns dict: {source_file, format, block, kind, start_line, end_line,
    lines_returned, truncated, source, parse_errors}.

Example: plc_program_section(path="~/exports/Line3.scl", block="FB_Conveyor").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
blockYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds significant behavioral details beyond annotations: read-only nature (though already in annotations), truncation at 200 lines with a flag, error handling (unknown block names return available list), and return format. Annotations already indicate readOnlyHint and destructiveHint, so no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with an upfront summary tag, clear sentences, and a logical flow. Could be slightly more concise by omitting the argument list that mirrors the schema, but still efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Comprehensive for a read tool with no output schema: describes return dict fields, gives an example, explains error behavior, and covers constraints (file size, line limit, truncation). No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 0% description coverage, so description must compensate. It adds constraints for 'path' (must exist, ≤5 MB) and 'block' (case-insensitive, optional quotes), providing meaning beyond type/required status alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clearly states it returns the source text of one named block from an exported program. Distinguishes from sibling tools like plc_program_outline and plc_program_xref by specifying it retrieves the exact source for a single block.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'so the agent reads exactly the section it is explaining instead of guessing', giving a clear use case. Does not explicitly state when not to use or mention alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_snapshotA
Read-only

[READ][risk=low] Record an exported program's structure as a change baseline.

A control program is a controlled document, and the usual way an undocumented
change to one gets noticed is that somebody remembers. This gives the
comparison a number: the file's SHA-256, plus a per-block structural
fingerprint (name/kind/language, declared variables, calls, branch conditions,
timers) that deliberately excludes line numbers, comments and block order — so
adding a comment at the top of a file does not report the whole program as
changed. Stored locally under the iaiops home as block names, hashes and
counts — never a declaration, a source line or a comment — so the store is not
a second copy of the program. Reads the named EXPORTED file only; never a live
PLC upload.

Re-snapshotting a byte-identical file records nothing and says so — a history
padded with identical rows hides the rows that are not.

Args:
    path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
    name: Program identity across exports. Defaults to the file's stem, and
        the result says which was used — the export path changes every time
        somebody opens the engineering station, the program does not.
    label: Short label, e.g. "approved v3.2 / MOC-118".
    note: Free note recorded with the snapshot.

Returns dict: {status ('recorded'|'unchanged'), program, name_source,
    snapshot:{snapshot_id, taken_at, source_file, content_sha256, label, note},
    block_count, snapshot_count, previous_snapshot}.

Example: plc_program_snapshot(path="~/exports/Line3.scl", label="approved v3.2").
ParametersJSON Schema
NameRequiredDescriptionDefault
nameNo
noteNo
pathYes
labelNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=true and destructiveHint=false; the description adds substantial behavioral context: the fingerprint deliberately excludes line numbers/comments/block order so cosmetic edits don't flag a change, the store keeps only hashes and counts (never source), and re-snapshotting a byte-identical file records nothing and returns status 'unchanged'. This goes well beyond the annotations and matches them — no contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but visibly structured: purpose tag, rationale, behavioral notes, labeled Args/Returns sections, and a worked example. It is front-loaded with the core purpose. The controlled-document rationale paragraph is somewhat verbose, and the length is justified by the tool's nuanced baseline semantics, but it could be tightened without losing value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 4-parameter tool with no output schema, the description is complete: it documents every parameter with constraints, specifies the exact return dict shape including status values, discloses side-effect-free storage behavior, states the idempotency semantics, and gives a call example. There are no schema or annotation gaps left unaddressed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden — and it succeeds. Each parameter gets real meaning: path gains file extensions, existence and ≤5 MB constraints; name gains cross-export identity, stem default, and the name_source feedback behavior; label gets a concrete example; note gets a purpose. This fully compensates for the empty schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The lead sentence states a specific verb and resource: 'Record an exported program's structure as a change baseline.' The scope is sharply differentiated from siblings like plc_program_drift (compare against a baseline) and plc_program_history (show past snapshots) by making the recording role explicit. The '[READ][risk=low]' tag and 'never a live PLC upload' also pin down what the tool is and is not.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives clear context for when to use the tool — establishing a baseline for a controlled program document — and states exclusions ('Reads the named EXPORTED file only; never a live PLC upload'). However, it never explicitly names sibling alternatives such as plc_program_drift or plc_program_history for the comparison side of the workflow, leaving the agent to infer the full workflow from the baseline semantics.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_visibilityA
Read-only

[READ][risk=low] Maintainability / operational-risk profile of a legacy PLC program.

The "what am I inheriting?" view over one EXPORTED program (SCL/ST, AWL/STL,
Rockwell L5X): folds the structural outline into documentation coverage, the
least-commented blocks, blocks nothing references (possible dead code), the
complexity hotspots, risky constructs (unconditional JMPs, retentive RTO
timers, loops), and a TRANSPARENT additive risk score whose every point cites
its reason. Structural only — it anchors an engineer's review of a line
somebody else left behind, not a semantic understanding. Reads exactly the
named file (≤5 MB); never a live PLC upload. Every finding cites source_file +
line (rung number for L5X ladder).

Args:
    path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).

Returns dict: {source_file, fmt, stats:{blocks, call_edges, line_count,
    comment_count, comment_ratio, variables, branches, timers_counters},
    documentation:{comment_ratio, band ('well_commented'|'sparse'|
    'undocumented'), uncommented_block_count, uncommented_blocks},
    entry_points:[{name, kind}], unreferenced_blocks:[{name, kind,
    source_file, line}], complexity_hotspots:[{block, kind, score, branches,
    calls, timers_counters, source_file, line}], risky_constructs:{
    unconditional_jumps, unconditional_jump_count, loops, loop_count,
    retentive_timers, retentive_timer_count}, risk:{score (0..100), band
    ('low'|'medium'|'high'), reasons[]}, parse_errors, note}.

Example: plc_program_visibility(path="~/exports/Line3_Conveyor.scl").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond readOnlyHint and destructiveHint, description adds key behavioral details: works only on exported files (no live upload), file size limit (≤5 MB), structural analysis only (no semantic understanding), every finding cites source file and line. Transparent about limitations and capabilities.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured: lead with risk level and purpose, then detailed explanation of outputs, Args, Returns dict, and example. Some redundancy (e.g., 'structural only' repeated) but overall efficient and front-loaded. Slightly lengthy yet justified by complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, description provides a comprehensive dictionary of return fields with types and descriptions. Includes examples, input constraints, and explicit risk scoring details. Adequate for an agent to correctly invoke and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 0% description coverage for path. Description compensates fully by specifying allowed extensions (.st, .scl, .awl, .l5x, .txt), existence requirement, and size constraint (≤5 MB). Provides essential context beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb and resource: 'maintainability/operational-risk profile of a legacy PLC program'. Distinguishes from siblings like plc_program_outline by specifying it provides a comprehensive risk assessment including dead code, complexity hotspots, and risky constructs, and explicitly states it is structural only, not semantic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Implicit usage context: 'The "what am I inheriting?" view' and 'anchors an engineer's review of a line somebody else left behind.' However, no explicit comparison to sibling tools like plc_program_outline or plc_program_xref, nor guidance on when not to use this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plc_program_xrefA
Read-only

[READ][risk=low] Cross-reference one symbol in an exported PLC program.

Finds every read/write/call/declare site of a symbol or absolute address
(e.g. Motor_Run, "FB_Conveyor", DB10.DBX0.1, M0.0, Tank[2].Level) in one
exported file, quoting the surrounding source line verbatim so the agent
cites real code. Access classification is heuristic (op/regex based, not
data-flow analysis): SCL ':='→write, '('→call; AWL T/=/S/R→write,
L/A/O…→read, CALL→call; L5X OTE/OTL/OTU/RES and MOV-dest→write. For L5X,
line is the rung number.

Args:
    path: Exported program file (.st/.scl/.awl/.l5x/.txt; must exist, ≤5 MB).
    symbol: Symbol / tag / absolute address to trace (word-bounded match).

Returns dict: {source_file, format, symbol, hit_count,
    hits:[{symbol, access, block, source_file, line, source_line}] (≤200),
    hits_truncated, by_access:{read, write, call, declare, reference}}.

Example: plc_program_xref(path="~/exports/OB1.awl", symbol="M10.0").
ParametersJSON Schema
NameRequiredDescriptionDefault
pathYes
symbolYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant behavioral context beyond annotations: it explains the heuristic (op/regex based, not data-flow analysis), details access classification per format (SCL, AWL, L5X), and notes verbatim source line quoting. This complements the readOnlyHint annotation well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a tag, summary, heuristics, Args, returns, and example. It is front-loaded with the purpose. While somewhat lengthy, every sentence adds value, earning a 4.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description comprehensively explains the return dict, including fields like source_file, format, hits, by_access. It also covers file type constraints and heuristic behavior, making it complete for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining both parameters: path includes file types, existence, and size constraint; symbol includes examples and word-bounded match requirement. This adds meaning beyond the schema's type definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool cross-references a symbol in an exported PLC program, finding every read/write/call/declare site. It distinguishes from sibling tools like plc_program_outline by focusing on symbol tracing rather than program structure.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for tracing symbol accesses in exported files but does not explicitly state when to use this tool over alternatives, nor does it provide exclusions or when-not-to-use guidance. The file size constraint is mentioned but not in a usage comparison context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profinet_asset_inventoryA
Read-only

[READ][risk=low] PROFINET asset register from a DCP IdentifyAll sweep.

Segment-wide, read-only — no per-device connection. The DCP device-role bitmask
is decoded when the client exposes it; pnio-dcp does not, so roles and the
controller/device counts come back empty and 0. Names, MACs and IP suites are
unaffected — those are what the register is for.

Args:
    endpoint: Endpoint name from config (protocol 'profinet').

Returns dict: {endpoint, asset_count, io_controller_count, io_device_count,
    assets:[{name_of_station, mac, ip, vendor_id, device_id, roles[], family}],
    method:'dcp_identify_all'}.

Example: profinet_asset_inventory(endpoint="cell1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.3/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond the annotations by disclosing specific behaviors: it is read-only and segment-wide, notes the DCP device-role bitmask limitation ('roles and the controller/device counts come back empty and 0'), and clarifies that 'Names, MACs and IP suites are unaffected.' This provides valuable context not available in readOnlyHint or destructiveHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections for READ/risk, overview, args, returns, and example. It is longer than strictly necessary, but the extra length is justified by the important caveat about role decoding. No wasted sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description provides a detailed return dictionary format and method name. It also covers limitations and gives an example. It does not mention error conditions or what happens if the endpoint is invalid, but for a simple one-parameter read tool, the coverage is quite complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has only one optional parameter (endpoint) with 0% description coverage, so the description carries the burden. It explains endpoint as 'Endpoint name from config (protocol 'profinet')' and provides an example call, which adds meaning. However, it does not clarify default behavior when endpoint is null or what valid endpoint names look like, so it is adequate but not thorough.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: 'PROFINET asset register from a DCP IdentifyAll sweep.' It specifies a concrete verb and resource, and distinguishes itself from sibling tools by emphasizing 'Segment-wide, read-only — no per-device connection.' This differentiates it from per-station tools like profinet_identify_station.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use the tool: 'Segment-wide, read-only — no per-device connection.' It implies this is for asset inventory across an entire segment rather than individual stations. It also highlights a limitation (roles may be empty with pnio-dcp), but it does not explicitly name alternative tools or state when not to use it, so it falls short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profinet_dcp_setA
Destructive

[WRITE][risk=HIGH][MOC] DCP Set — re-address one PROFINET station (off by default).

OT-DANGEROUS. Defaults to dry_run=True (nothing set). Re-addresses a live
station's name-of-station and/or IP suite via a unicast DCP Set (can disrupt the
IO connection). Captures the BEFORE addressing (by MAC) and records an undo
descriptor. Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to
apply. 未经授权勿对生产控制系统写入.

Args:
    mac: Target station MAC, e.g. '00:1b:1b:12:34:56' (from profinet_discover).
    set_name: New name-of-station (omit to leave unchanged).
    set_ip: New IP address (omit to leave the IP suite unchanged).
    netmask: New subnet mask (used with set_ip).
    gateway: New default gateway (used with set_ip).
    endpoint: Endpoint name from config (protocol 'profinet').
    dry_run: When True (default) returns a preview without setting anything.

Returns dict: dry-run → {mac, dry_run:true, before, would_set, note};
    applied → {mac, dry_run:false, before, set, applied:true, _undo_id}.

Example (preview): profinet_dcp_set(mac="00:1b:1b:12:34:56", set_name="plc-new").
ParametersJSON Schema
NameRequiredDescriptionDefault
macYes
set_ipNo
dry_runNo
gatewayNo
netmaskNo
endpointNo
set_nameNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes beyond annotations by detailing the risky nature ('OT-DANGEROUS', 'can disrupt the IO connection'), the dry_run safety mechanism, and the undo capability. It also explains the return dict structure, providing full behavioral transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but well-structured, starting with the core action and risk, then dry_run behavior, parameter list, return format, and an example. While slightly long, it adds necessary information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 params, no output schema), the description is highly complete. It covers safety, parameters, return values, undo mechanism, and includes an example. The Chinese warning adds context for potential users.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining all 7 parameters: mac (with example), set_name, set_ip, netmask, gateway, endpoint, and dry_run (default behavior). It specifies which parameters are used together and provides a usage example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 're-address one PROFINET station via a unicast DCP Set'. It specifies the action (DCP Set), resource (PROFINET station), and scope (name and/or IP suite). This distinguishes it from siblings like profinet_discover (discovery) and ethercat_set_state (EtherCAT).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (to re-address a station) and warns about disrupting IO connection. It notes the dry_run default and the need for an approver. However, it lacks explicit guidance on when not to use it or alternatives, though sibling context provides implicit differentiation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profinet_discoverA
Read-only

[READ][risk=low] DCP IdentifyAll — every PROFINET station on the segment.

One layer-2 broadcast surfaces all stations without connecting to any. Needs
raw-socket access on the NIC on the PROFINET subnet (pnio-dcp extra); degrades
to a teaching error dict when pnio-dcp/permission/NIC is missing.

Args:
    endpoint: Endpoint name from config (protocol 'profinet'); omit for default.

Returns dict: {endpoint, local_ip, station_count, stations:[{name_of_station,
    mac, ip, netmask, gateway, vendor_id, device_id, device_role_raw,
    device_roles[], device_family}]}. vendor_id/device_id/device_role* are
    always empty — pnio-dcp does not expose them (see the connector note).

Example: profinet_discover(endpoint="cell1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes well beyond the readOnly/openWorld annotations by labeling it as READ with low risk, clarifying it operates via a broadcast without connecting to any station, and disclosing the dependency on raw-socket permissions and pnio-dcp. It also transparently notes that vendor/device fields are always empty due to pnio-dcp limitations, and explains the degradation to an error dict when prerequisites are missing.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficiently structured with a '[READ][risk=low]' tag, a concise explanation, requirements, argument documentation, return format, and an example. Every section adds value, and the information is front-loaded with the tool's primary purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Since there is no output schema, the description thoroughly explains the return dict and all its fields, including the caveat about always-empty vendor/device fields. It also covers prerequisites and error behavior, making the tool fully understandable without external references.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With zero schema description coverage, the description fully compensates by explaining that the endpoint parameter refers to the endpoint name from config with protocol 'profinet' and that omitting it uses the default. This gives the parameter clear semantic meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as 'DCP IdentifyAll' that surfaces every PROFINET station on the segment via a layer-2 broadcast. It specifies the action (discover all stations), the resource (PROFINET devices), and distinguishes it from station-specific sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description clearly explains the context for using this tool (to list all stations on the network) and specifies prerequisites like raw-socket access and the pnio-dcp extra. It does not explicitly mention alternative tools for single-station identification or parameter reading, but the broadcast scope and 'all stations' wording make the intended use clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profinet_identify_stationA
Read-only

[READ][risk=low] Identify one station by its PROFINET name-of-station.

Args:
    name_of_station: Exact (case-insensitive) PROFINET station name, e.g. 'plc1'.
    endpoint: Endpoint name from config (protocol 'profinet').

Returns dict: {endpoint, found (bool), name_of_station, mac, ip, netmask,
    gateway, vendor_id, device_id, device_roles[], device_family}.

Example: profinet_identify_station(name_of_station="et200sp-1", endpoint="cell1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
name_of_stationYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations provide readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds a [READ][risk=low] prefix and details the return dict, but doesn't disclose any additional behavioral traits beyond the annotations. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, with clear sections for purpose, arguments, returns, and example. It is front-loaded with a risk tag and contains no unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (two parameters, read-only, no output schema), the description provides complete information: purpose, parameters, return structure, and an example. Annotations cover safety, so no gaps remain.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries full responsibility. It explains both parameters: name_of_station (exact, case-insensitive, with example) and endpoint (from config, protocol hint). An example call is provided, adding significant value.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool identifies one station by its PROFINET name-of-station, with a verb and specific resource. It distinguishes from sibling tools like profinet_discover (which lists all stations) and profinet_station_params (which gets parameters).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool (to identify a specific station by name) but does not explicitly state when not to use it or provide alternatives. However, the context is clear, and the example usage sets expectations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

profinet_station_paramsA
Read-only

[READ][risk=low] Targeted DCP Get for one station (by MAC): name + IP suite.

Args:
    mac: The station's MAC address, e.g. '00:1b:1b:12:34:56'.
    endpoint: Endpoint name from config (protocol 'profinet').

Returns dict: {endpoint, mac, found (bool), name_of_station, ip, netmask, gateway}.

Example: profinet_station_params(mac="00:1b:1b:12:34:56", endpoint="cell1").
ParametersJSON Schema
NameRequiredDescriptionDefault
macYes
endpointNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, indicating a safe read operation. The description reinforces this with '[READ][risk=low]' and details the return dict, including a 'found' boolean. Since annotations carry the main behavioral burden, the description adds useful context about the return format and safety.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized with a title line, parameter list, return format, and example. It is concise (3 sentences plus the example line) with no wasted words. Every sentence serves a purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description explains the return dict structure. Parameter semantics are fully covered. The tool is low complexity with 2 parameters, and the example clarifies usage. It is complete enough for an agent to effectively invoke the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully compensates by explaining both parameters: 'mac: The station's MAC address, e.g. '00:1b:1b:12:34:56'' and 'endpoint: Endpoint name from config (protocol 'profinet')'. It also provides an example call, adding value beyond the schema's type-only definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it performs a 'Targeted DCP Get for one station (by MAC)', retrieving name and IP suite. This distinguishes it from sibling profinet tools like profinet_discover (likely for discovering all stations) and profinet_identify_station (for identification). The verb 'get' and resource 'station params' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when targeting a specific station by MAC, and the example and parameter explanation provide context. However, it does not explicitly state when to use this tool instead of alternatives like profinet_discover or profinet_asset_inventory. The guidance is clear but not exhaustive.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

protocols_supportedA
Read-only

[READ][risk=low] Capability map — protocols, status, tools, connection params.

Call this to discover what iaiops can do before choosing a protocol/tool.
Lists implemented protocols (OPC-UA incl. HDA, Modbus, S7comm, Mitsubishi MC,
MTConnect, MQTT/Sparkplug B full-decode, EtherNet/IP Logix) and the EtherCAT
roadmap stub, plus cross-protocol analytics (OEE/downtime, asset inventory,
CoV), each with its read/write tools and the endpoint params it needs.

Also reports whether this server runs under the no-egress gate, so a model is
TOLD the posture instead of having to infer it from tools it cannot see.
Read/write authorisation is NOT a server posture here — it is the caller's
decision; every call (read or write, MCP or CLI) is audited.

Returns dict: {tool, posture, implemented_protocols:[...], roadmap_stubs:[...],
    protocols:[{protocol, status, library, transport, auth, read_tools,
    write_tools, params}], diagnostics:[...], analytics:[...], tool_counts,
    safety, write_note, no_egress_mode, no_egress_note}.

Example: protocols_supported().
ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds valuable behavioral context: it returns a rich dict with details, explains the no-egress gate, and clarifies that read/write authorisation is the caller's decision and all calls are audited.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is relatively long but well-structured with a summary, list of protocols, and return format. Every sentence provides value, though some brevity could be achieved without losing clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given zero parameters and no output schema, the description provides a comprehensive return dict structure and explains key behaviors (no-egress gate, audit). It is complete for a discovery tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters with 100% schema coverage. The description does not need to add parameter details, and the baseline for 0 parameters is 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is a 'capability map' to 'discover what iaiops can do before choosing a protocol/tool', with specific verb and resource. It distinguishes from sibling tools that are specific operations (e.g., modbus_read_holding) by being a discovery tool.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Call this to discover what iaiops can do before choosing a protocol/tool', providing clear usage context. It does not explicitly list when not to use, but the purpose is clearly for initial discovery.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rca_corpus_from_maintenanceA
Read-only

[READ][risk=low] Turn a CMMS/work-order export into the RCA incident corpus.

Auto-builds the labeled history learn_cause_weights needs from closed maintenance
records: an explicit taxonomy cause column wins; else a built-in EN/中文 CMMS
synonym table (extendable via 'synonyms'); else UNAMBIGUOUS keyword inference
over the row's free text using the copilot's own cause keywords. Rows it cannot
map land in 'unmapped' with the reason — never silently guessed. 'signals' come
from an explicit column or the symptom/alarm text (may stay empty — no fabricated
evidence). Pure + advisory; with learn=true the learned weights are included.

Args:
    rows: Work-order records, one dict each. Recognized cause columns:
        cause / root_cause / failure_class / category / problem_code; free-text
        columns: description / problem / notes / comment / text / 故障描述;
        signal text: symptom(s) / alarm(s) / 现象.
    synonyms: Extra site vocabulary, e.g. {"spindle crash": "mechanical_fault"};
        values must be taxonomy causes.
    learn: Also run learn_cause_weights on the mapped corpus (default true).
    min_samples: Passed to learn_cause_weights (default 8).
    smoothing: Passed to learn_cause_weights (default 1.0).

Returns dict: {corpus:[{cause, signals}], n_rows, n_mapped, unmapped:[{row,
    reason, excerpt}], mapped_via, weights?, next_step}.

Example: rca_corpus_from_maintenance(rows=[{"category":"轴承损坏",
    "symptom":"drive overload alarm"}], synonyms={"spindle crash":"mechanical_fault"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
rowsYes
learnNo
synonymsNo
smoothingNo
min_samplesNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description provides detailed behavioral traits: it is read-only, rows that cannot be mapped are placed in 'unmapped' with reason (no silent guessing), and signals may stay empty. This goes beyond the annotations which only indicate readOnlyHint=true.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a header, paragraph, parameter list, return format, and example. It is slightly long but every sentence adds value, and the front-loading of purpose and risk helps the agent quickly understand the tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description includes a detailed return dict structure (corpus, n_rows, n_mapped, unmapped, mapped_via, weights?, next_step) and thoroughly explains the mapping logic. It covers all necessary details for a tool with 5 parameters and one required field.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description fully explains all 5 parameters: rows (lists recognized columns), synonyms (format and constraint), learn, min_samples, smoothing. It also includes an example, adding significant meaning beyond the schema's property names.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Turn a CMMS/work-order export into the RCA incident corpus.' It explains the mapping process with priority order and distinguishes it from siblings by focusing on building the corpus needed for learn_cause_weights.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use it (to build labeled corpus for learn_cause_weights) and provides context such as the synonym table and keyword inference. However, it does not explicitly mention alternatives or when not to use it.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rca_narrateA

[READ][risk=low] Narrate a cited RCA verdict in plain language via an on-box LLM.

Air-gapped: hands the already-computed, already-cited verdict to a LOCAL model (Ollama) that
ONLY rephrases it — it never adds a cause, number, or citation (strict prompt; see docs/RCA.md).
Read-only; no device I/O. Needs the extra + a running local model: pip install iaiops[ollama].

Args:
    verdict: An RCA verdict dict (e.g. the output of downtime_root_cause).
    base_url: Ollama server URL (default http://localhost:11434).
    model: Local model name (default 'llama3.1').
    provider: LLM provider (currently 'ollama').

Returns dict: {provider, model, narration}.

Example: rca_narrate(verdict=<downtime_root_cause output>, model="llama3.1").
ParametersJSON Schema
NameRequiredDescriptionDefault
modelNollama3.1
verdictYes
base_urlNohttp://localhost:11434
providerNoollama

TDQS

A3.7/5.0
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description claims 'Read-only; no device I/O' and tags [READ], but annotations set readOnlyHint=false, creating a direct contradiction. Per scoring rules, this warrants a score of 1 and flags annotation contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a header, paragraphs, and bulleted args. It front-loads key information (read-only, air-gapped). Could be slightly more concise, but clear and logical.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description details the return dict and provides an example. It covers prerequisites, dependencies, and usage context. Without the contradiction, it would be near complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must compensate. It explains the verdict parameter as an RCA verdict dict from downtime_root_cause, and provides defaults for base_url, model, and provider. This adds meaningful context beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'narrate' and the resource 'RCA verdict', and distinguishes it from sibling tools like downtime_root_cause by explicitly linking as its companion. It is specific and unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use (after obtaining an RCA verdict), what it does (rephrase, never add causes), and prerequisites (pip install), but lacks an explicit 'when not to use' or comparison with alternatives, though implicit from context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s7_cpu_infoA
Read-only

[READ][risk=low] S7 CPU identity + run/stop status (proves the link).

Args:
    endpoint: Endpoint name from config (protocol must be 's7'); omit for default.

Returns dict: {endpoint, rack, slot, cpu_status (e.g. 'run'/'stop'),
    cpu_info: {module, serial, version, ...}}.

Example: s7_cpu_info(endpoint="press1").
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false, so the agent knows it's safe. The description adds context like 'risk=low' and 'proves the link', which goes beyond annotations. No contradiction.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is short and front-loaded with purpose. It uses a clear structure with Args and Returns sections. Every sentence contributes information without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple input (1 optional param) and no output schema, the description covers the return structure and provides an example. It could mention error handling for invalid endpoints, but overall it is complete enough for a low-complexity tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must add meaning. It explains that endpoint is optional, protocol must be 's7', and omitting uses default. An example is provided. This adds value beyond the schema definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool reads S7 CPU identity and run/stop status, using specific verbs and resource. It distinguishes from sibling S7 tools by focusing on CPU info rather than memory areas. The phrase 'proves the link' adds context.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no explicit guidance on when to use this tool vs alternatives like s7_read_db. It implies usage for connection verification, but does not mention exclusions or when not to use. With many sibling tools, more guidance would be helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s7_read_areaA
Read-only

[READ][risk=low] Read count items of a type from an S7 memory area.

Args:
    area: Memory area — DB | M (merker/flag) | I (input) | Q (output).
    dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL|CHAR.
    start: Byte offset within the area/DB (0-based).
    endpoint: Endpoint name from config.
    db: Data block number (required when area=DB).
    count: Number of consecutive items (1..100, capped server-side).
    bit: Bit offset 0..7 (only when dtype=BIT).

Returns dict: {endpoint, area, db, dtype, start, count,
    items:[{address, value}]}. ``value`` is bool/int/float per dtype.

Example: s7_read_area(area="DB", dtype="REAL", start=4, db=1, count=2).
ParametersJSON Schema
NameRequiredDescriptionDefault
dbNo
bitNo
areaYes
countNo
dtypeYes
startYes
endpointNo

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false, so the agent knows this is a safe read operation. The description adds valuable behavioral context: the count parameter is 'capped server-side' (1..100), and it specifies the return type structure with address and value per data type. This goes beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with sections (Args, Returns, Example) and uses bullet-style lists. However, it is slightly verbose for a read operation; some redundancy (e.g., repeating 'count' in Returns) could be trimmed. Overall, it's well-organized and front-loaded with purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, no output schema), the description is largely complete: it explains all parameters, the return dictionary format, and provides a concrete example. However, it lacks guidance on how this tool relates to similar siblings (s7_read_db, s7_read_many) and does not mention potential errors or prerequisites like endpoint availability.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides no descriptions (0% coverage), so the description must compensate fully. It does so excellently: every parameter is explained with acceptable values (area enum, dtype list, start as byte offset, endpoint from config, db required when area=DB, count range 1..100, bit offset for BIT type). The example further clarifies usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Read') and resource ('S7 memory area') with specific verb and resource. It lists memory area types and data types, making the purpose unmistakable. However, it does not explicitly differentiate this tool from similar siblings like s7_read_db or s7_read_many, which could cause confusion for an AI agent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage through parameter examples (e.g., 'area=DB, dtype=REAL, start=4, db=1, count=2') but provides no explicit guidance on when to use this tool versus alternatives like s7_read_db or s7_read_many. No when-not-to-use or exclusionary context is given.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s7_read_dbA
Read-only

[READ][risk=low] Read count dtype items from data block db.

Args:
    db: Data block number (e.g. 1 for DB1).
    dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL.
    start: Byte offset within the DB (0-based).
    endpoint: Endpoint name from config.
    count: Number of consecutive items (1..100).

Returns dict: {endpoint, area:'DB', db, dtype, start, count, items:[{address, value}]}.

Example: s7_read_db(db=1, dtype="INT", start=0, count=10).
ParametersJSON Schema
NameRequiredDescriptionDefault
dbYes
countNo
dtypeYes
startYes
endpointNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds constraints (count 1..100, start 0-based) and specifies the return format. No contradictions; the description supplements the annotations with useful behavioral details.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact with a clear structure: brief summary, parameter list, return format, and example. Every sentence serves a purpose without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 5 parameters, no output schema, and present annotations, the description covers the tool's behavior thoroughly—explaining all parameters, constraints, the return dict structure, and an example. No gaps remain for an agent to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has no descriptions (0% coverage), but the description fully explains each parameter: db, dtype, start, endpoint, count. It provides examples and acceptable values (e.g., S7 data types list). This adds significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description starts with '[READ]' and clearly states 'Read count dtype items from data block db', specifying the verb and resource. It distinguishes from sibling tools like s7_read_area and s7_read_many by focusing on a specific data block read with explicit dtype and offset.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for reading items from a data block and provides an example, but does not explicitly state when to use this tool versus alternatives like s7_read_area or s7_read_many. No exclusions or conditions are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s7_read_manyA
Read-only

[READ][risk=low] Batch-read raw pyS7 address strings in one request.

Args:
    addresses: pyS7 addresses, e.g. ["DB1,REAL4", "DB1,X0.0", "MW10", "I0.0"].
    endpoint: Endpoint name from config.

Returns dict: {endpoint, count, items:[{address, value}]}.

Example: s7_read_many(addresses=["DB1,REAL4","M0.0"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
endpointNo
addressesYes

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint, openWorldHint, and destructiveHint. The description adds beyond these by specifying the return format (dict with endpoint, count, items) and confirming it is a read operation. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with a clear structure: purpose line, Args section, Returns section, and Example. Every sentence adds value with no repetition or fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description adequately explains the return format and provides a complete example. All parameters are described with sufficient detail for an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description fully compensates. It explains the 'addresses' parameter with examples like 'DB1,REAL4' and 'MW10' and defines 'endpoint' as 'Endpoint name from config', adding meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Batch-read raw pyS7 address strings' with a specific verb and resource. It distinguishes from sibling read tools like s7_read_area and s7_read_db by emphasizing 'raw pyS7 address strings' and batch operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides a clear use case (batch-read multiple addresses) and an example. However, it does not explicitly state when not to use it or mention alternatives, leaving some ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

s7_write_dbA
Destructive

[WRITE][risk=HIGH][MOC] Write ONE value to an S7 data block (off by default).

OT-DANGEROUS. Defaults to dry_run=True (nothing written). Captures the BEFORE
value (read-back) and records an undo descriptor so the change is reversible.
Set dry_run=False AND record an approver (OPCUA_AUDIT_APPROVED_BY) to apply.
未经授权勿对生产控制系统写入.

Args:
    db: Data block number.
    dtype: S7 data type — BIT|BYTE|WORD|INT|DWORD|DINT|REAL|LREAL.
    start: Byte offset within the DB.
    value: Value to write (coerced to the dtype's Python type).
    endpoint: Endpoint name from config.
    dry_run: When True (default) returns a preview without writing.

Returns dict: dry-run → {address, dry_run:true, before, would_write, note};
    applied → {address, dry_run:false, before, written, applied:true, _undo_id}.

Example (preview): s7_write_db(db=1, dtype="INT", start=0, value=42).
ParametersJSON Schema
NameRequiredDescriptionDefault
dbYes
dtypeYes
startYes
valueYes
dry_runNo
endpointNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate destructivity, and the description adds crucial safety context: captures BEFORE value, records undo descriptor, requires approver for actual write. This goes beyond annotations, though it could be more explicit about error recovery.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Very concise and well-structured: summary line, risk note, behavior details, argument list, return dict format, and example. Every sentence adds value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema, but description fully documents return format. Includes example and explains both dry-run and applied scenarios. Missing error handling or permission details, but overall complete for safe usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description provides meaningful parameter info: dtype lists exact types, start is 'Byte offset', value is coerced. The example further clarifies usage. Could add constraints like valid DB ranges.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Write ONE value to an S7 data block', specifying the verb and resource. It distinguishes from siblings like s7_read_db by emphasizing the write action and including a risk label. The summary line and examples reinforce the purpose.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states default dry_run=True for preview, and that actual writing requires dry_run=False and an approver. Provides clear when-to-use guidance but does not explicitly contrast with alternative write tools (though siblings are mostly read tools).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

site_readinessA
Read-only

[READ][risk=low] Which scenarios THIS site can run today, and what each gap needs.

The companion to `protocols_supported`, one altitude down. That one says what
the product can do; this says what this installation can do — and calling the
first without the second is how an agent plans a scenario the site has no
inputs for.

Contacts nothing: no device, no network, no historian. It is derived from
`config.yaml` and the local store, which is what makes it runnable against a
site nobody has authorised you to probe — the site that most needs it.

Three states, and the middle one carries the value: `ready`, `degraded` (it
RUNS, on less than full evidence — root cause without a historian still ranks
causes, it just cannot see the two hours before the stoppage) and `blocked`.

`blocked_on` is the actionable half: one missing input usually unlocks several
scenarios, ranked by how many.

It never fills a gap in for you. Which tag is the production counter is
process knowledge, and a wrong guess yields plausible-looking OEE numbers —
considerably worse than an error (D16). Where a prerequisite cannot be
supplied at all yet, the row says `not_yet_expressible` rather than implying
somebody forgot to configure it.

`db` overrides the local store path; empty means the iaiops store.
ParametersJSON Schema
NameRequiredDescriptionDefault
dbNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Despite annotations already declaring readOnlyHint and non-destructive behavior, the description adds substantial behavioral context: 'Contacts nothing: no device, no network, no historian,' and that it is derived from `config.yaml` and the local store. It also clarifies the three possible states, explains that `blocked_on` is the actionable half, and discloses that it never fills gaps and uses `not_yet_expressible` rather than implying misconfiguration. No contradiction exists with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but dense and every section earns its place: summary, relationship to sibling, safety behavior, state semantics, actionable output, gap-handling philosophy, and the parameter override. It is front-loaded with the core purpose and risk posture, and the structure makes it easy for an agent to extract the key facts.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with one optional parameter and no output schema, the description is complete. It explains what the tool returns semantically (ready/degraded/blocked, blocked_on, not_yet_expressible), how to interpret the mid-state, and how the db parameter affects execution. An agent has enough to select, invoke, and interpret results correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description carries the full burden for explaining the single parameter. It does so explicitly: '`db` overrides the local store path; empty means the iaiops store.' This clarifies both the override behavior and the default, which is exactly what the agent needs to invoke the tool correctly.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Which scenarios THIS site can run today, and what each gap needs.' It clearly differentiates itself from the sibling `protocols_supported` by stating one altitude down: 'That one says what the product can do; this says what this installation can do.' No ambiguity remains about what the tool is for.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly names the companion tool `protocols_supported`, explains the relationship, and warns that calling the first without the second leads to planning a scenario the site has no inputs for. It also tells the agent when this tool is especially valuable: it can run against a site nobody has authorized probing. This is clear when-to-use and alternative-routing guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sparkplug_decode_payloadA
Read-only

[READ][risk=low] Decode a single raw Sparkplug B payload to structured metrics.

Full protobuf decode (vendored Eclipse Tahu schema): per metric returns name,
alias, datatype (Int/Float/Bool/String/DateTime/DataSet/Template…), value,
timestamp, and is_historical / is_null flags. Rich types expand: a DataSet
value decodes to {columns, types, rows} and a Template value to {template_ref,
is_definition, version, members, parameters} (members decoded recursively).

Args:
    payload: Raw Sparkplug B protobuf bytes as a string, ``base64`` (default) or ``hex``.
    encoding: 'base64' or 'hex'.
    alias_map: Optional {alias: name} (from a prior BIRTH) so alias-only
        NDATA/DDATA metrics resolve to names.

Returns dict: {encoding:'sparkplug_b', timestamp, seq, uuid, metric_count,
    historical_count, metrics:[{name, alias, datatype, value, timestamp,
    is_historical, is_null}]}. A DataSet ``value`` is {dataset:true, columns,
    types, rows, row_count}; a Template ``value`` is {template:true,
    template_ref, is_definition, version, members:[{name, type, value}],
    parameters}.

Example: sparkplug_decode_payload(payload="CAESBwoDYWJjEAE=", encoding="base64").
ParametersJSON Schema
NameRequiredDescriptionDefault
payloadYes
encodingNobase64
alias_mapNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, destructiveHint=false, and openWorldHint=true. The description adds valuable behavioral details: it uses a vendored Eclipse Tahu schema, returns flags like is_historical/is_null, and recursively expands DataSet and Template values. There is no contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a [READ][risk=low] tag, then concisely states purpose, then lists parameters, return format, and an example. While informative, it is slightly verbose in detailing return fields that are also summarized later; a bit of redundancy. Still efficient overall.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite lacking an output schema, the description provides a complete return structure including nested expansions for DataSet and Template values. It covers all parameters, encoding details, and alias usage. For a protobuf decode tool with 3 parameters and no output schema, this is thorough and sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, meaning the input schema provides no descriptions for the 3 parameters. The description fully compensates by explaining each parameter: 'payload' (raw bytes as base64 or hex default), 'encoding' (base64 or hex), and 'alias_map' (optional alias-to-name mapping). Also provides an example with an encoded payload.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Decode a single raw Sparkplug B payload to structured metrics.' It specifies the verb 'decode', the resource 'Sparkplug B payload', and the output 'structured metrics'. Among 100+ sibling tools, this uniquely targets raw payload decoding, contrasting with subscription, node listing, and generic MQTT tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the tool's inputs and output but does not explicitly state when to use it vs. alternatives like sparkplug_subscribe_sample or sparkplug_node_list. Usage context is implied through the example and parameter details, but no 'when not to use' or exclusion guidance is provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sparkplug_live_schemaA
Read-only

[READ][risk=low] Capture a LIVE Sparkplug schema (bounded) → drift-ready dict.

Subscribes, collects up to ``max_msgs`` messages or until ``duration_s``, decodes
NBIRTH/DBIRTH metrics, and returns ``schema`` = {node: {metric: datatype}} (node =
group/edge[/device]) — exactly the shape uns_schema_drift accepts. Use it as a
baseline or current snapshot.

Args:
    endpoint: Endpoint name from config.
    topic: Topic filter (default 'spBv1.0/#').
    duration_s: Capture window in seconds (1..60).
    max_msgs: Max messages to capture (1..500).

Returns dict: {endpoint, topic, message_count, birth_count, node_count,
    schema:{node:{metric:datatype}}}.

Example: sparkplug_live_schema(topic="spBv1.0/Plant1/#", duration_s=15).
ParametersJSON Schema
NameRequiredDescriptionDefault
topicNospBv1.0/#
endpointNo
max_msgsNo
duration_sNo

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive behavior. The description adds detail about subscribing, collecting messages, and decoding, which is consistent with annotations. No contradiction found.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary, parameter list, return format, and example. It is front-loaded and every sentence serves a purpose without redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only tool with four parameters and no output schema, the description covers the core functionality, return shape, and provides an example. It lacks error handling or edge-case details but is sufficient for the intended use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description lists each parameter with a brief explanation, including defaults and the topic filter syntax. This adds meaning beyond the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool captures a LIVE Sparkplug schema, decodes NBIRTH/DBIRTH metrics, and returns a dict. It uses specific verbs and resources, and the purpose is distinct from sibling tools like sparkplug_decode_payload or sparkplug_subscribe_sample.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description suggests using it as a baseline or current snapshot, providing clear usage context. However, it does not explicitly state when not to use it or mention alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sparkplug_node_listA
Read-only

[READ][risk=low] Discover edge nodes/devices + online state + primary-host STATE.

Builds the birth/death + seq model from BIRTH/DATA/DEATH/STATE topics: each
node reports online/born, its devices, learned metric aliases, and seq gaps;
STATE topics surface primary-host status.

Args:
    endpoint: Endpoint name from config.
    timeout_s: Observation window in seconds (1..60). Longer catches infrequent nodes.
    count: Max messages to inspect (1..500).

Returns dict: {endpoint, node_count, nodes:[{group_id, edge_node_id, online,
    born, devices:[...], metric_aliases_known, seq_gap_count, seq_issues}],
    primary_hosts:[{host_id, state}]}.

Example: sparkplug_node_list(timeout_s=15).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
endpointNo
timeout_sNo

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark it read-only and non-destructive. The description adds valuable context: it details the internal model built from BIRTH/DATA/DEATH/STATE topics, explains what 'online' means, and lists return fields including seq gaps and primary host state. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with summary, parameter doc, return structure, and example. It is slightly verbose (e.g., repeating 'builds the birth/death + seq model'), but every sentence adds value given the complex domain. Could be tightened, but still effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of Sparkplug and lack of output schema, the description thoroughly explains the return dict structure with all nested fields. It covers parameter behavior, default values, and provides an example. No gaps remain for an agent to select and invoke this tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 0% description coverage, but the description compensates fully with detailed explanations for each parameter (endpoint from config, timeout_s range 1-60, count 1-500) and their purpose. Includes an example invocation, making parameter usage crystal clear.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool discovers edge nodes/devices and online state plus primary-host state, using specific Sparkplug topics. It clearly distinguishes from sibling tools like sparkplug_subscribe_sample or sparkplug_decode_payload by focusing on node listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains use cases via the example and parameter guidance (e.g., longer timeout for infrequent nodes), but does not explicitly contrast with alternatives among the many Sparkplug-related siblings. The context is clear enough for an agent to infer appropriate use.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

sparkplug_subscribe_sampleA
Read-only

[READ][risk=low] Bounded Sparkplug B sample with full decode + birth/death/seq.

Topics are parsed and payloads fully protobuf-decoded; a birth/death + seq
model resolves aliases (from NBIRTH/DBIRTH), applies NDATA/DDATA by alias, and
flags is_historical metrics and seq gaps.

Args:
    endpoint: Endpoint name from config.
    topic: Topic filter (default 'spBv1.0/#').
    count: Max messages (1..500).
    timeout_s: Max seconds to wait (1..60).

Returns dict: {endpoint, topic, message_count, historical_metric_count,
    seq_gap_count, samples:[{topic, sparkplug:{group_id, message_type,
    edge_node_id, device_id}, payload:{metrics:[{name, alias, datatype, value,
    is_historical}]}}]}.

Example: sparkplug_subscribe_sample(topic="spBv1.0/Plant1/#", count=20).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
topicNo
endpointNo
timeout_sNo

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate read-only and non-destructive nature. The description adds valuable behavioral context: bounded count/timeout, full protobuf decoding, alias resolution from birth certificates, flagging of historical metrics and sequence gaps. This goes well beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (summary, technical details, args, returns, example). It is moderately concise; every sentence adds information, though the technical paragraph could be slightly more succinct.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description fully details the return dictionary structure, making the tool's output understandable. It covers purpose, inputs, outputs, and an example. Missing usage guidelines and error handling, but otherwise complete for a tool of this complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema coverage, the description carries the full burden. It provides parameter names, brief descriptions, and constraints (count: 1..500, timeout: 1..60) not present in the schema. The example aids understanding. No details on endpoint source or topic format beyond defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool as a bounded Sparkplug B sample with full decode and birth/death/seq handling. It specifies the exact resource (Sparkplug B topics) and verb (subscribe and sample), distinguishing it from siblings like sparkplug_decode_payload or mqtt_read_topic.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. While the description implies it is for sampling a bounded number of messages, it does not mention when not to use it (e.g., for continuous subscription or decoding individual payloads).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stream_publishA

[READ][risk=low] Publish already-read normalized points to a message bus (NATS).

Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON
message on ``<subject_prefix>.tag.<metric>``; non-numeric points are skipped (use a historian
sink for text/state). Needs the extra: pip install iaiops[nats].

Args:
    points: Collected point dicts (e.g. from *_read_many): {ref/metric, value, timestamp, ...}.
    subject_prefix: NATS subject root (default 'iaiops').
    servers: Comma-separated NATS server URLs (default nats://localhost:4222).
    token: Optional NATS auth token.
    tls: Use TLS to the broker.
    publisher: Bus kind (currently 'nats').

Returns dict: {publisher, subject_prefix, received, published, skipped_non_numeric}.

Example: stream_publish(points=[{"ref": "line1.temp", "value": 21.5}], subject_prefix="plant").
ParametersJSON Schema
NameRequiredDescriptionDefault
tlsNo
tokenNo
pointsYes
serversNonats://localhost:4222
publisherNonats
subject_prefixNoiaiops

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate readOnlyHint=false and destructiveHint=false, and the description aligns by stating it is a publish (write) operation of already-read data. It adds context: non-numeric points are skipped, and the tool requires an extra pip install. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a summary line, behavioral explanation, Args, Returns, and Example. It is front-loaded with the purpose. While not overly verbose, every sentence adds value and it remains focused.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has 6 parameters, no output schema, and no enums, the description comprehensively covers input parameters, return value format, and provides an example. It is complete enough for an agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description fully compensates by explaining each parameter in the Args section (points, subject_prefix, servers, token, tls, publisher) and providing an example. This adds essential meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it publishes already-read normalized points to a NATS message bus, specifying it is for egress of read data and not a control write. It distinguishes from sibling tools like stream_publish_event, historian_push, and mqtt_publish by focusing on NATS.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains to use this tool for publishing already-read numeric points, notes that non-numeric points are skipped, and suggests using a historian sink for text/state. It also mentions the needed pip install. While it doesn't explicitly list when not to use, it provides clear context for appropriate usage.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

stream_publish_eventA

[READ][risk=low] Publish one computed event (RCA verdict / alarm) to a message bus (NATS).

Egress of a finding the brain already COMPUTED — e.g. an RCA verdict or an alarm episode — to
``<subject_prefix>.<subject>`` as JSON. NOT a control write. Needs: pip install iaiops[nats].

Args:
    subject: Event subject suffix (e.g. 'rca.verdict', 'alarm.flood').
    event: The event payload dict (published as JSON).
    servers/token/tls/subject_prefix/publisher: bus connection (see stream_publish).

Returns dict: {publisher, subject, published}.

Example: stream_publish_event(subject="rca.verdict", event={"primary_cause": "seal"}).
ParametersJSON Schema
NameRequiredDescriptionDefault
tlsNo
eventYes
tokenNo
serversNonats://localhost:4222
subjectYes
publisherNonats
subject_prefixNoiaiops

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=false and destructiveHint=false. The description adds that it publishes to NATS, is not a control write, requires pip install iaiops[nats], and returns a dict with publisher, subject, published. This goes beyond annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a lead line, parameter list, return info, and example. Every sentence adds value. It is front-loaded with the core purpose. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 7 parameters, no output schema, and many siblings, the description covers the output format, gives an example, and references stream_publish for connection details. It lacks edge cases or error handling, but overall provides sufficient context for an agent to use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so description must compensate. It defines subject and event with examples and types. For the 5 connection parameters (servers, token, tls, subject_prefix, publisher), it merely groups them and defers to stream_publish, lacking individual details. This provides basic but incomplete semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool publishes one computed event to a message bus (NATS), with specific verb 'publish' and resource 'event'. It distinguishes from siblings by noting it's for computed findings (RCA verdict/alarm) and explicitly says 'NOT a control write', contrasting with stream_publish.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use: for egress of already computed results, and not for control writes. It references stream_publish for connection details, indicating alternative for raw publishing. An example further clarifies usage. Lacks explicit when-not-to-use scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

subscription_healthA
Read-only

[READ][risk=low] Health of a sequenced subscription feed (OPC-UA or Sparkplug B).

Detects dropped notifications (sequence gaps), duplicates / out-of-order, a high
republish-rejection rate, and overloaded channels — the classic Kepware
"too many tags on one channel → republish/queue-flush dropouts" fault.

Args:
    sequence: Sequence numbers actually received, in arrival order.
    republish_requested: How many republish requests were made.
    republish_rejected: How many were rejected (server couldn't keep up).
    tags_per_channel: {channel/endpoint: tag_count} — flags channels over the max.
    max_tags_per_channel: Density above which a channel is flagged (default 5000).
    wrap_at: Modulus for rolling counters (e.g. 256 for Sparkplug B seq); omit
        for monotonic OPC-UA counters.

Returns dict: {received, missed_count, duplicate_count, out_of_order_count,
    republish_requested, republish_rejected, republish_reject_rate,
    overloaded_channels:[{channel, tags}], max_tags_per_channel,
    verdict ('ok'|'reordered'|'lossy'|'overloaded'), recommendation}.

Example: subscription_health(sequence=[1,2,4,5], tags_per_channel={"ch1":7000}).
ParametersJSON Schema
NameRequiredDescriptionDefault
wrap_atNo
sequenceYes
tags_per_channelNo
republish_rejectedNo
republish_requestedNo
max_tags_per_channelNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, and the description adds behavioral details such as being a read operation with low risk, and explains the algorithmic detection of issues. This goes beyond the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, args, returns, example) and front-loaded with the key purpose. However, it is somewhat lengthy, but every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (6 params, no output schema), the description is complete: it explains all inputs, details the return dict structure, and provides an example. This fully equips an agent to use the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema coverage, the description provides thorough explanations for all 6 parameters, including type hints, defaults, and an example. This fully compensates for the lack of schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: analyzing the health of a sequenced subscription feed (OPC-UA or Sparkplug B). It specifies what it detects (sequence gaps, duplicates, etc.), making it distinct from sibling tools like 'opcua_health_summary' or 'sparkplug_subscribe_sample'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage when monitoring subscription feeds and suspecting sequence issues or overloaded channels. It provides context but does not explicitly state when not to use it or suggest alternative tools for different scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

tag_healthA
Read-only

[READ][risk=low] Rank tag offenders by bad-quality / flatline / range / anomaly.

Args:
    tags: Per-tag dicts — {ref, label?, samples:[scalars or {value, good|quality}],
        warn_high?, alarm_high?, warn_low?, alarm_low?}.
    thresholds: Optional {ref: {warn_high, alarm_high, warn_low, alarm_low}} override.

Returns dict: {evaluated, overall ('ok'|'warn'|'alarm'), offender_count,
    offenders:[{ref, label, samples, latest, flags:[...], anomaly_count,
    severity (0..3)}], results:[...]}. Flags include bad_quality, flatline,
    out_of_range_warn/alarm, statistical_anomaly.

Example: tag_health(tags=[{"ref":"ns=2;i=5","samples":[70,71,70,99]}]).
ParametersJSON Schema
NameRequiredDescriptionDefault
tagsYes
thresholdsNo

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds detail on the output structure, flags, and severity levels, going beyond the annotations by explaining the behavioral aspects of the ranking and return format.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a summary line and then organized into Args and Returns. It is slightly lengthy but necessary due to the tool's complexity; could be trimmed without losing essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description comprehensively explains the return values (dict with overall, offenders, flags) since no output schema exists. It covers the main use case but lacks mention of error handling or edge cases, which is acceptable for a read-only tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by detailing the structure of 'tags' (e.g., per-tag dicts with optional fields) and 'thresholds' (optional override). This adds significant meaning beyond the minimal schema definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Rank tag offenders by bad-quality / flatline / range / anomaly', which clearly specifies the verb 'rank' and the resource 'tag offenders'. It is distinct from sibling tools like alarm_bad_actors or anomaly_scan, but does not explicitly differentiate them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance is provided on when to use this tool versus alternatives such as data_quality_scorecard or health_summary. The description only explains what the tool does without usage context or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_browseA
Read-only

[READ][risk=low] Browse the live topic tree (UNS) under a filter (bounded).

Args:
    endpoint: Endpoint name from config.
    topic: Topic filter to browse under (default '#').
    timeout_s: Observation window in seconds (1..60).
    count: Max messages to inspect (1..500).

Returns dict: {endpoint, filter, topic_count, topics:[...], tree:{nested segments}}.

Example: uns_browse(topic="factory/#", timeout_s=8).
ParametersJSON Schema
NameRequiredDescriptionDefault
countNo
topicNo#
endpointNo
timeout_sNo

TDQS

A4.1/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral details beyond annotations, such as risk level ('risk=low'), bounded observation window, and max message count. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and front-loaded with purpose. It lists arguments, return format, and an example in a clear, structured manner. Every sentence adds value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the return format (endpoint, filter, topic_count, topics, tree) despite the lack of an output schema. However, it could be more explicit about edge cases or the exact structure of the tree.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite schema coverage being 0%, the description thoroughly explains each parameter: endpoint, topic, timeout_s, count, including defaults, ranges, and example usage. This adds significant meaning beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it is a read-only operation to browse the live UNS topic tree under a bounded filter. The verb 'browse' and resource 'topic tree (UNS)' are specific and distinguish it from sibling tools like uns_topic_audit or uns_live_audit.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance on when to use this tool versus alternatives. The description lacks any 'when to use' or 'when not to' statements, leaving the agent to infer context from the name and parameters alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_live_auditA
Read-only

[READ][risk=low] Capture the LIVE UNS topic tree (bounded) then audit it.

Closes the governance loop: subscribes to a live broker, collects up to
``max_msgs`` messages or until ``duration_s`` (whichever first), then runs the
naming-conformance + topic-sprawl audit over the observed topics. Never an
open-ended loop.

Args:
    endpoint: Endpoint name from config (protocol must be 'mqtt').
    topic: Topic filter to capture under (default '#').
    duration_s: Capture window in seconds (1..60, capped server-side).
    max_msgs: Max messages to capture (1..500, capped server-side).
    allowed_roots: Permitted top-level segments; others are flagged (optional).
    min_segments: Minimum namespace depth a well-formed topic must have.
    max_leaf_parents: A leaf under more than this many parents is scattered.

Returns dict: the uns_topic_audit result (topic_count, depth, verdict, findings)
    plus capture:{endpoint, topic, observed_messages, unique_topics, topics[]}.

Example: uns_live_audit(topic="factory/#", duration_s=8, allowed_roots=["factory"]).
ParametersJSON Schema
NameRequiredDescriptionDefault
topicNo#
endpointNo
max_msgsNo
duration_sNo
min_segmentsNo
allowed_rootsNo
max_leaf_parentsNo

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds behavioral context: subscribes to a live broker, collects up to max_msgs or duration_s (bounded), and runs naming-conformance + topic-sprawl audit. It does not contradict annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: a header line, a paragraph on governance loop, an Args list, Returns, and an Example. It is somewhat lengthy but every sentence adds value. Could be slightly more concise, but overall effective.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers all aspects: behavior, parameters, return format (including nested dict shape), and provides an example. Since there is no output schema, the description's explanation of the return dict is essential and well-provided.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With schema description coverage at 0%, the description fully compensates by explaining each parameter in the Args section, including bounds (e.g., duration_s: 1..60 capped, max_msgs: 1..500 capped), their purpose (e.g., allowed_roots: 'Permitted top-level segments; others are flagged'), and a usage example.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Capture the LIVE UNS topic tree (bounded) then audit it', specifying the action (capture + audit), the resource (LIVE UNS topic tree), and the bounded nature. It distinguishes from sibling tools like uns_topic_audit (offline audit) by emphasizing live capture.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains the tool's role: 'Closes the governance loop' and describes the capture-then-audit process. It clarifies the tool is not an open-ended loop. However, it does not explicitly mention when to avoid this tool or suggest alternatives (e.g., uns_topic_audit for offline audits).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_live_driftA
Read-only

[READ][risk=low] Capture the LIVE Sparkplug schema (bounded) and diff vs baseline.

Captures current node/metric definitions from live BIRTHs, then runs schema drift
against ``baseline`` — added / removed / type-changed metrics per node with a
none/additive/breaking verdict.

Args:
    baseline: Prior schema {node:{metric:datatype}} (e.g. from sparkplug_live_schema).
    endpoint: Endpoint name from config.
    topic: Topic filter (default 'spBv1.0/#').
    duration_s: Capture window in seconds (1..60).
    max_msgs: Max messages to capture (1..500).

Returns dict: the uns_schema_drift result (changed_nodes, verdict, node_changes)
    plus capture:{endpoint, topic, message_count, birth_count, node_count}.

Example: uns_live_drift(baseline={"Plant1/Edge1":{"Temperature":"Double"}}).
ParametersJSON Schema
NameRequiredDescriptionDefault
topicNospBv1.0/#
baselineYes
endpointNo
max_msgsNo
duration_sNo

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. The description adds significant transparency: it explains the bounded capture via duration_s and max_msgs, the live BIRTHs as data source, and the structure of the return value (changed_nodes, verdict, node_changes plus capture metadata). This goes beyond annotations to fully disclose behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact yet complete: a one-liner summary, a brief explanation, then structured sections for Args, Returns, and a concrete Example. Every sentence is informative, with no redundancy. It is front-loaded with the core purpose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given no output schema, the description fully explains the return value (drift result plus capture info). Constraints (duration_s 1..60, max_msgs 1..500) are included. The tool's complexity is low (read-only drift), and the description covers all needed aspects for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% coverage (no descriptions in schema properties), but the description compensates with an explicit Args section covering all five parameters: baseline, endpoint, topic, duration_s, max_msgs. Each has type, default, and purpose. Baseline is described as a structured object. The example also demonstrates parameter usage. This provides full semantic meaning.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear verb-resource pair: 'Capture the LIVE Sparkplug schema (bounded) and diff vs baseline.' It specifies the tool's action (capture and diff) and the resource (Sparkplug schema). It distinguishes itself by mentioning the baseline from sparkplug_live_schema and the output type uns_schema_drift, setting it apart from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use the tool: to capture live schema and compare against a baseline. It references the baseline source (e.g., from sparkplug_live_schema), guiding the user on how to prepare input. The return structure and example further clarify usage. No explicit exclusions are needed given the straightforward use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_publishA

[READ][risk=low] Publish already-read normalized points to an MQTT broker / UNS.

Egress of data the agent already READ — NOT a control write. Each numeric point becomes a JSON
message on ``<topic_prefix>/<metric>``, with a dotted metric nested into topic levels
(``line1.temp`` -> ``plant/line1/temp``) so a Unified Namespace stays browsable. Non-numeric
points are skipped (use a historian sink for text/state). The topic is always derived from
``topic_prefix`` — it is never taken verbatim, so this cannot address a command topic. Needs the
extra: pip install iaiops[mqtt].

Args:
    points: Collected point dicts (e.g. from *_read_many): {ref/metric, value, timestamp, ...}.
    topic_prefix: Root of the topic tree (default 'iaiops'); wildcards are stripped.
    host: Broker hostname or IP (default localhost).
    port: Broker port; 0 picks 8883 with TLS else 1883.
    username: Optional broker username.
    password: Optional broker password.
    use_tls: Use TLS to the broker.
    qos: MQTT QoS 0/1/2 (default 0, fire-and-forget); values outside 0-2 are clamped.
    retain: Ask the broker to retain the last value per topic (useful for a UNS).

Returns dict: {publisher, topic_prefix, broker, received, published, skipped_non_numeric}.

Example: uns_publish(points=[{"ref": "line1.temp", "value": 21.5}], topic_prefix="plant",
    host="10.0.0.5").
ParametersJSON Schema
NameRequiredDescriptionDefault
qosNo
hostNolocalhost
portNo
pointsYes
retainNo
use_tlsNo
passwordNo
usernameNo
topic_prefixNoiaiops

TDQS

A5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses rich behavioral detail beyond the annotations: dotted-metric topic nesting, non-numeric point skipping, derived topic prefix with wildcard stripping, QoS clamping, port/TLS auto-selection, and the exact return dictionary. Annotations are minimal and safe (destructiveHint false), so the description carries and fully satisfies the burden. There is no contradiction with readOnlyHint=false because the publication is a side-effect write, while '[READ]' refers to source data already read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but every section earns its place: a purpose statement, safety clarification, behavioral details, a structured parameter list, return type, and a concrete example. It is front-loaded with the core purpose and risk tag before diving into details, and the formatting makes it easy to scan.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 9 parameters, no output schema, and no parameter descriptions in the schema, the description is remarkably complete. It defines the return dict, covers edge cases (non-numeric skip, wildcard stripping, QoS clamping), mentions the installation prerequisite, provides an example, and clarifies the safety profile. Nothing an agent needs to call this tool correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must fully explain each of the 9 parameters. It does: points, topic_prefix, host, port, username, password, use_tls, qos, and retain, each with defaults, meaning, and behavioral notes (e.g., 'wildcards are stripped', 'values outside 0-2 are clamped'). This comprehensively compensates for the schema gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific action: 'Publish already-read normalized points to an MQTT broker / UNS.' It clearly defines the resource (numeric points) and differentiates from control-write tools by noting 'NOT a control write' and from historian sinks for non-numeric data. This makes its purpose unambiguous and distinguishable from siblings.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says when to use: to egress data the agent has already read. It gives when-not guidance: 'Non-numeric points are skipped (use a historian sink for text/state)' and 'cannot address a command topic.' It also mentions the prerequisite pip install, leaving no ambiguity about invocation context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_schema_driftA
Read-only

[READ][risk=low] Detect Sparkplug/UNS schema drift between two snapshots.

Compares baseline vs current node/metric definitions (e.g. two NBIRTH snapshots)
and reports added / removed / type-changed metrics per node, with a verdict.

Args:
    baseline: {node: {metric: datatype}} or [{node|topic, metrics:[{name, datatype}]}].
    current: Same shape — the newer snapshot to compare against the baseline.

Returns dict: {baseline_nodes, current_nodes, changed_nodes,
    verdict ('none'|'additive'|'breaking'), node_changes:[{node, node_status,
    added[], removed[], type_changed:[{metric, from, to}]}]}.

Example: uns_schema_drift(baseline={"N1":{"temp":"Float"}},
    current={"N1":{"temp":"Int32","rpm":"Float"}}).
ParametersJSON Schema
NameRequiredDescriptionDefault
currentYes
baselineYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description tags the tool as [READ][risk=low], aligning with annotations (readOnlyHint=true, destructiveHint=false). It discloses the output structure and the type of changes detected (added, removed, type-changed), going beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: a one-line title, explanation of purpose, argument format, return type, and a concrete example. Every sentence adds value without fluff.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers input format, output structure with all keys, and a usage example. With no output schema, this provides sufficient context for an agent to understand what the tool returns and how to use it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 0% schema description coverage, the description thoroughly explains the expected shape and format of both parameters (baseline and current) including an example. This fully compensates for the lack of schema-level description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool detects schema drift between two snapshots for Sparkplug/UNS, specifying the verb 'detect' and resource 'schema drift'. It distinguishes itself from siblings like uns_browse or uns_topic_audit by focusing on comparison of snapshots.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains what the tool does (compare baseline vs current) and provides an example, but does not explicitly contrast with sibling tools like uns_live_drift or baseline_check. The usage context is clear enough for an agent familiar with the domain.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

uns_topic_auditA
Read-only

[READ][risk=low] Govern a UNS topic tree: naming conformance + topic sprawl.

Pure analysis over a provided list of UNS topic strings (no live broker). Flags
non-conforming roots, too-shallow topics, casing collisions of the same logical
name, leaf metrics scattered under many parents, depth outliers, and duplicates.

Args:
    topics: UNS topic strings, e.g. ["Enterprise/Site/Area/Line1/temperature", ...].
    allowed_roots: Permitted top-level segments; others are flagged (optional).
    min_segments: Minimum namespace depth a well-formed topic must have.
    max_leaf_parents: A leaf appearing under more than this many parents is scattered.

Returns dict: {topic_count, unique_topics, root_count, roots[], depth{min,max,mean},
    verdict ('clean'|'minor'|'sprawling'), sprawl_findings, findings{
    non_conforming_root[], too_shallow[], casing_collisions[], scattered_leaves[],
    depth_outliers[], duplicate_topics[]}}.

Example: uns_topic_audit(topics=["Ent/Site/Line1/temp","Ent/site/Line1/Temp"],
    allowed_roots=["Ent"], min_segments=3).
ParametersJSON Schema
NameRequiredDescriptionDefault
topicsYes
min_segmentsNo
allowed_rootsNo
max_leaf_parentsNo

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The descriptions adds significant behavioral context beyond annotations. It declares the tool as read-only and low risk, consistent with readOnlyHint=true, and details the exact types of analysis performed (e.g., flagging non-conforming roots, casing collisions, scattered leaves). No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a header, a concise explanation, and clear Args/Returns sections. It front-loads the core purpose and risk level. While detailed, every sentence contributes value, though the Returns block could be slightly more compact. Overall, it strikes a good balance between completeness and brevity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite having no output schema, the description provides a comprehensive dict structure for return values. It covers all parameter explanations, analysis logic, and expected outputs. The annotations already handle safety, and the description fills in all behavioral and usage gaps, making the tool well-understood by an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema has 0% description coverage, so the description carries the full burden. It provides clear semantic explanations for all 4 parameters: topics (UNS topic strings), allowed_roots (permitted top-level segments), min_segments (minimum depth), and max_leaf_parents (scatter threshold). This adds essential meaning beyond the schema's type-only definitions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: to govern a UNS topic tree by performing naming conformance and topic sprawl analysis. It explicitly specifies that it works on a provided list of topic strings (no live broker), distinguishing it from sibling tools like uns_live_audit and uns_browse that operate on live data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for static topic analysis by stating 'no live broker', but it does not explicitly list when to use this tool versus alternatives (e.g., uns_live_audit for live monitoring). There is no direct mention of when not to use it or explicit sibling comparisons, leaving room for ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

verify_determinismA
Read-only

[READ][risk=low] Prove this engine's analysis is reproducible without a model.

Runs a named suite of analyses (availability, production counts, the Six Big
Losses, ISA-18.2 alarm load, control charts, the conservative baseline, the
RCA copilot) over a pinned reference dataset, canonically encodes each result
and digests it — twice in this process and, with ``subprocesses``, once more
in each of two fresh interpreters started at different PYTHONHASHSEED values.
That last arm is the one that catches a set or dict iteration order reaching a
result; a single run never can. The socket API raises throughout, so a
computation that reached for a device or a hostname fails here rather than
quietly succeeding on a machine that happens to be online. ``sys.modules`` is
checked afterwards for any model library — empty is the guarantee.

Use it to answer "how do I know your AI didn't make this number up": the
answer is that no model is in the path, and here is the SHA-256 that says so,
reproducible on the customer's own box. Read-only; nothing is written unless
the CLI (`iaiops verify determinism --out record.json`) is used to save the
signable record for a validation file.

Args:
    subprocesses: Also re-run in two fresh interpreters at fixed, different
        hash seeds (default True; adds roughly a second).

Returns dict: {check, result:{verdict ('reproducible'|'not_reproducible'),
    suite_digest, dataset:{name, revision, digest}, checks:[{name, covers,
    digest}], arms:[{arm, suite_digest, matches_first_arm}], arms_disagreeing,
    model_modules_loaded, network}, context:{iaiops_version, python, platform,
    generated_at, ...}, note}. ``result`` is identical between runs; ``context``
    is not — it records when and where this run happened.

Example: verify_determinism().
ParametersJSON Schema
NameRequiredDescriptionDefault
subprocessesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses subprocess execution, fixed differing PYTHONHASHSEED runs, socket API failures, the sys.modules model-libery check, and the fact that result is stable across runs while context is not. It also states the read-only caveat with the CLI --out path. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with purpose and risk, and each paragraph adds relevant behavior, parameters, or output shape. It is slightly verbose for a one-parameter tool, with the Returns dict and user-story framing adding length, but nothing is padding.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a single-parameter read-only verification tool, the description covers purpose, when to use it, execution model, side-effect caveat, return structure, and how to interpret reproducibility. Even with an output schema present, the inline Returns dict adds useful detail without leaving any gap needed to invoke the tool correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the Args section fully compensates by explaining that subprocesses re-runs in two fresh interpreters at fixed different hash seeds, defaults to true, and adds about a second. This is exactly the behavioral meaning the schema alone does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening line states a specific verb and object: prove the engine's analysis is reproducible without a model. The next sentence enumerates the exact suite of analyses and the pinned reference dataset, and the socket/sys.modules constraints make it unmistakable among the many sibling health/read tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit use case: answer 'how do I know your AI didn't make this number up', and clarifies the tool is read-only unless the CLI flag is added. It does not name alternatives or when-not-to-use conditions, so it misses the full when/when-not/alternatives bar.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 5 tool updatesv0.27.0
    • Addedalarm_event_clusters
    • Addedbaseline_check_in_context
    • Addedbaseline_learn_contextual
    • Addeddevice_advisory_check
    • Addeddowntime_attribution
  2. 4 tool updatesv0.26.0
    • Addedplc_program_drift
    • Addedplc_program_history
    • Addedplc_program_snapshot
    • Addedverify_determinism
  3. 9 tool updatesv0.25.0
    • Addedinvestigation_list
    • Addedinvestigation_open
    • Addedinvestigation_readiness
    • Addedinvestigation_show
    • Addedline_relation_declare
    • Addedline_relations_list
    • Addedmechanism_library_check
    • Addedmechanism_library_list
    • Addedsite_readiness
  4. 1 tool updatev0.23.0
    • Addeduns_publish
  5. 134 tool updatesv0.1.0
    • First observedadopt_alias_map
    • First observedalarm_bad_actors
    • First observedalarm_cascade
    • First observedalarm_flood_analysis
    • First observedalarm_rationalization_worksheet
    • First observedanomaly_scan
    • First observedasset_inventory
    • First observedbaseline_check
    • First observedbaseline_learn
    • First observedbaseline_record_change
    • First observedbaseline_status
    • First observedchangeover_analysis
    • First observedcompliance_dengbao_levels
    • First observedcompliance_evidence_bundle
    • First observedcompliance_frameworks
    • First observedcompliance_mapping
    • First observedcompliance_report
    • First observedcross_protocol_asset_model
    • First observeddata_quality_fleet_rollup
    • First observeddata_quality_scorecard
    • First observeddiagnose_dataflow
    • First observeddiff_alias_map
    • First observeddowntime_events
    • First observeddowntime_root_cause
    • First observeddowntime_root_cause_live
    • First observeddowntime_triage
    • First observedeip_controller_info
    • First observedeip_list_tags
    • First observedeip_read_many
    • First observedeip_read_tag
    • First observedeip_write_tag
    • First observedethercat_master_state
    • First observedethercat_read_pdo
    • First observedethercat_read_sdo
    • First observedethercat_set_state
    • First observedethercat_slave_info
    • First observedethercat_slaves
    • First observedethercat_write_sdo
    • First observedexport_data
    • First observedfins_cpu_info
    • First observedfins_cpu_status
    • First observedfins_read_bits
    • First observedfins_read_many
    • First observedfins_read_words
    • First observedfins_write_words
    • First observedfleet_incidents
    • First observedfleet_status
    • First observedhealth_summary
    • First observedheartbeat_health
    • First observedhistorian_coverage
    • First observedhistorian_health
    • First observedhistorian_push
    • First observedhistorian_query
    • First observedignition_alarm_status
    • First observedignition_gateway_status
    • First observedignition_tag_browse
    • First observedignition_tag_history
    • First observedignition_tag_read
    • First observediolink_device_info
    • First observediolink_master_info
    • First observediolink_ports
    • First observediolink_read_isdu
    • First observediolink_read_pdin
    • First observediolink_scan
    • First observedlearn_cause_weights
    • First observedmc_cclink_link_read
    • First observedmc_cclink_network_health
    • First observedmc_cclink_templates
    • First observedmc_cpu_status
    • First observedmc_read_bits
    • First observedmc_read_many
    • First observedmc_read_words
    • First observedmc_write_words
    • First observedmodbus_apply_template
    • First observedmodbus_detect_byte_order
    • First observedmodbus_health_summary
    • First observedmodbus_list_templates
    • First observedmodbus_read_coils
    • First observedmodbus_read_discrete
    • First observedmodbus_read_holding
    • First observedmodbus_read_input
    • First observedmonitor_changes
    • First observedmqtt_publish
    • First observedmqtt_read_topic
    • First observedmtconnect_assets
    • First observedmtconnect_current
    • First observedmtconnect_oee_snapshot
    • First observedmtconnect_probe
    • First observedmtconnect_sample
    • First observedoee_compute
    • First observedoee_multidim
    • First observedopcua_alarm_events
    • First observedopcua_anomaly_scan
    • First observedopcua_browse
    • First observedopcua_diagnose_connection
    • First observedopcua_discover_tags
    • First observedopcua_health_summary
    • First observedopcua_read_alarms
    • First observedopcua_read_history
    • First observedopcua_read_many
    • First observedopcua_read_node
    • First observedopcua_server_info
    • First observedopcua_subscribe_sample
    • First observedpdm_forecast
    • First observedplc_program_outline
    • First observedplc_program_section
    • First observedplc_program_visibility
    • First observedplc_program_xref
    • First observedprofinet_asset_inventory
    • First observedprofinet_dcp_set
    • First observedprofinet_discover
    • First observedprofinet_identify_station
    • First observedprofinet_station_params
    • First observedprotocols_supported
    • First observedrca_corpus_from_maintenance
    • First observedrca_narrate
    • First observeds7_cpu_info
    • First observeds7_read_area
    • First observeds7_read_db
    • First observeds7_read_many
    • First observeds7_write_db
    • First observedsparkplug_decode_payload
    • First observedsparkplug_live_schema
    • First observedsparkplug_node_list
    • First observedsparkplug_subscribe_sample
    • First observedstream_publish
    • First observedstream_publish_event
    • First observedsubscription_health
    • First observedtag_health
    • First observeduns_browse
    • First observeduns_live_audit
    • First observeduns_live_drift
    • First observeduns_schema_drift
    • First observeduns_topic_audit

TDQS

A3.8/5.0
Disambiguation4/5

Tools are mostly distinct due to protocol prefixes (opcua_, s7_, eip_) and specific functionality (e.g., data_quality_scorecard vs. alarm_flood_analysis). However, there is overlap among alarm analysis tools (alarm_flood_analysis, alarm_bad_actors, alarm_cascade) and downtime tools (downtime_root_cause, downtime_triage, downtime_events), which could cause confusion. Descriptions help differentiate, but the large number of similar-sounding tools makes misselection possible.

Naming Consistency3/5

Tool names follow a mix of conventions: some use protocol prefix (opcua_read_node), some use verb_noun (read_many), and some use noun_verb (cpu_info). While consistent within protocol groups, the overall pattern is inconsistent across the server. The naming is still readable, but the lack of a unified pattern reduces predictability.

Tool Count2/5

With 134 tools, the set is excessively large for an agent to manage effectively. While the broad scope covering many OT protocols and analytics justifies a high count, the number is overwhelming. Many tools have similar purposes (e.g., multiple alarm analyses), and the agent may struggle to select the right tool quickly. This exceeds typical coherence thresholds.

Completeness5/5

The tool set is exceptionally comprehensive, covering major OT protocols (OPC-UA, Modbus, S7, Mitsubishi MC, EtherNet/IP, PROFINET, EtherCAT, IO-Link, etc.), advanced analytics (downtime root cause, OEE, alarm management, data quality, historian, compliance), and even PLC program analysis. Read and write tools (with safety guards) are included, along with diagnostics and asset management. There are no significant gaps for its stated purpose.

Maintenance

ActivityActive
ResponsivenessSlow

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Connects AI agents to OPC UA-enabled industrial systems for real-time monitoring and control of operational data. It enables users to read, write, and browse industrial device nodes through natural language interactions.
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to interact with inSCADA systems via the Model Context Protocol, providing 39 tools for live data, alarms, scripts, historical analysis, charts, and more.
    39
    66
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables LLMs to connect to factory PLC sensors, read register data, analyze predictive maintenance, and monitor energy consumption in industrial environments.
    3
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Exposes a deterministic IoT edge runtime — Modbus/CAN/J1939 acquisition, local rules, alarms, and history — to AI assistants as typed, governed MCP tools. Reads are safe by default; device control stays deny-by-default, explicitly confirmed, and audited.
    23
    3
    Apache 2.0

Latest Blog Posts

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/industrial-aiops/industrial-aiops'

If you have feedback or need assistance with the MCP directory API, please join our Discord server