twincat-mcp
Server Configuration
Describes the environment variables required to run the server.
| Name | Required | Description | Default |
|---|---|---|---|
| TCMCP_DOCS | No | Infosys documentation lookup on/off. Default 1. | 1 |
| TCMCP_MODE | No | Start mode: `readonly` / `guarded` / `full`. | guarded |
| TCMCP_CONFIG | No | Path to the TOML config file (otherwise `./twincat_mcp.toml` or `~/.twincat_mcp/config.toml`). | |
| TCMCP_PYTHON | No | Python executable used by the launcher (discovery order: TCMCP_PYTHON → `py -3` → `python` → %LOCALAPPDATA%\Programs\Python\Python3*). | python |
| TCMCP_CONFIRM | No | `0` → destructive ops in full mode need no confirmation. | 1 |
| TCMCP_PROGIDS | No | `;`-separated DTE ProgIDs to try, in order. Default: 17.0, 15.0, VS 18/17/16. | |
| TCMCP_AMS_PORT | No | Target ADS port. Default 851. | 851 |
| TCMCP_MAX_MODE | No | Ceiling for `tc_set_mode`. Default = mode. | |
| TCMCP_SOLUTION | No | `.sln` to attach to; also sets project root. | |
| TCMCP_AUDIT_LOG | No | JSONL audit file path. | ~/.twincat_mcp/audit.jsonl |
| TCMCP_AMS_NET_ID | No | Target AmsNetId. Default: local. | |
| TCMCP_DOCS_BOOKS | No | `;`-separated default Infosys books to index. Default: 8 core PLC libraries. | |
| TCMCP_DOCS_CACHE | No | Infosys cache directory. | ~/.twincat_mcp/infosys |
| TCMCP_HTTP_TOKEN | No | Bearer token gate for HTTP mode (`--http` / `--token`). | |
| TCMCP_WRITE_DENY | No | `;`-separated fnmatch patterns for denied writes (deny always wins). Default empty. | |
| TCMCP_AUDIT_READS | No | Also log reads. Default 0. | 0 |
| TCMCP_WRITE_ALLOW | No | `;`-separated fnmatch patterns for allowed writes (deny always wins). Default empty. | |
| TCMCP_ALLOW_SAFETY | No | Set to `1` to allow XAE edits to `TISC` / `^Safety` paths; otherwise refused. | |
| TCMCP_DOCS_EXCLUDE | No | `;`-separated exclude regexes for Infosys books. | |
| TCMCP_PROJECT_ROOT | No | Folder for `proj_*` tools. Default: solution folder. | |
| TCMCP_TCUNIT_RESULT | No | TcUnit result path on the target. | C:\TwinCAT\3.1\Boot\TcUnit_xUnit_testresults.xml |
| TCMCP_XAE_ATTACH_ONLY | No | `0` → `xae_attach` may launch a shell. Default 1. | 1 |
| TCMCP_DOCS_WEB_FALLBACK | No | Enable sitemap-verified web fallback for Infosys search. Default 1. | 1 |
Instructions
Guidance the server publishes about itself, which clients place ahead of the tool catalog so the model reads it before choosing anything.
This server publishes no instructions, or was last inspected before Glama recorded them.
Capabilities
Features and capabilities supported by this server
Protocol revision2025-11-25
| Capability | Details |
|---|---|
| tools | {
"listChanged": false
} |
| prompts | {
"listChanged": false
} |
| resources | {
"subscribe": false,
"listChanged": false
} |
Tools
Functions exposed to the LLM to take actions
| Name | Description |
|---|---|
| tc_doctorA | Environment check: platform, pyads/router, local AMS NetId, XAE ProgIDs in the registry, running XAE shells, project root, safety mode. Run this first. |
| tc_safety_statusA | Current safety mode, ceiling, allow/deny lists, pending confirmation tokens. |
| tc_set_modeA | Switch safety mode: readonly | guarded | full. Escalation is capped at the configured max_mode (TCMCP_MAX_MODE); lowering is always allowed. |
| tc_request_confirmationA | Issue a single-use confirm_token for a control/destructive tool. Use the exact action name of the tool (e.g. 'xae_activate_configuration') and its target. |
| tc_audit_tailB | Last n audit records (mutating calls, confirmations, mode changes). |
| ads_connectA | (Re)connect to a target. ams_net_id like '5.12.34.56.1.1', 'local' for this PC, None = keep current; port 851 = PLC runtime 1. Re-targeting to a NetId other than the configured one is control-class (it changes which machine every later write hits). |
| ads_statusA | Composite status: connection, PLC runtime state, TwinCAT system mode (RUN/CONFIG), device name/version. With port=N returns only the ADS state of that port (852 PLC2, 500 NC, 10000 system service, 65535 EtherCAT master 1). |
| ads_list_symbolsB | Browse the runtime symbol table. pattern is fnmatch ('MAIN.', 'valve'; bare text is wrapped in ''). type_filter substring-matches the type ('ST_', 'BOOL', 'FB_'). flag filters by symbol flag: PERSISTENT, READONLY, STATIC, ATTRIBUTES … compact=true returns 'name : type' strings only (one fifth of the tokens). |
| ads_symbol_infoB | Type, size, index group/offset, flags (READONLY, PERSISTENT …) and comment of one symbol. |
| ads_readA | Read one symbol with type-aware decoding. Structs/FB instances/arrays of structs decode into a nested tree (datatype table); TIME/DATE/DT/TOD get readable text; enums get names. Trees larger than max_chars are summarised (member names + sizes) — use ads_leaves or ads_dump for the full content. |
| ads_read_manyB | Read several symbols in one ADS sum-command. Returns {name: value | {error}}. |
| ads_writeB | Write a symbol on the running PLC. Accepts JSON scalars, lists for arrays, and literals like 'T#1s500ms', 'D#2026-10-15', '16#FF'. Returns before/after. Gated: readonly=never; guarded=write_allowlist; full=denylist only. |
| ads_write_manyA | Write several symbols sequentially ({name: value}). Each one is gated and audited; stops at the first refusal. |
| ads_io_readA | Raw process image of the PLC: area 'I' (%IB inputs) or 'Q' (%QB outputs) at a byte offset — what the task actually sees/wrote, independent of symbol names (link checks). |
| ads_read_rawC | Raw ADS read by index group/offset on any port (hex + little-endian uint). |
| ads_write_rawA | Raw ADS write by index group/offset — PLC runtime ports (851-859) only. Every symbol whose memory overlaps the written range is checked against the write allow/deny lists; the raw target itself is 'raw://'. |
| ads_watchA | Sample symbols for duration_ms every interval_ms (polling trace). change_only keeps only rows where a value changed. Caps: 60 s, ≥10 ms, 5000 rows. Use for timing questions: 'does bDone pulse?', 'how long is the valve open?'. |
| ads_wait_untilB | Block until symbol value (==, !=, >, >=, <, <=) or timeout. Returns met/elapsed. |
| ads_plc_stateA | PLC runtime control via ADS: run | stop | reset. 'reset' is a cold reset (all non-persistent data lost). Control-class: confirmation in guarded mode. |
| ads_system_modeA | Switch TwinCAT on the target between 'run' and 'config' mode (restarts the runtime, I/O goes down). Destructive-class. |
| ads_ethercatA | EtherCAT master state (INIT/PREOP/SAFEOP/OP) and slave count via the master's ADS port (default 65535 for the first master; see Device → ADS tab in XAE). |
| ads_routesB | Local static ADS routes (parsed from StaticRoutes.xml on this PC). |
| ads_add_route_to_plcC | Create the PLC-side route back to this PC (UDP discovery protocol, needs the target's Windows/TC-BSD credentials). Control-class. |
| rec_startA | Start a continuous real-time recording of online PLC variables (runs in the background until rec_stop, duration_s, max_events or stop_when). Select by explicit symbols (an FB or struct instance expands to all its leaves), prefix ('MAIN.fbFill' → every leaf under it) or fnmatch pattern. mode: 'cycle' = one PLC-timestamped sample per symbol per cycle_ms (ADS notification, cycle-accurate); 'change' = PLC-timestamped sample only when the value changes (checked every cycle_ms); 'poll' = sum-read every cycle_ms from this PC. Triggers: start_when='MAIN.bStart == TRUE' with pre_trigger_ms keeps the events before the trigger (scope-style); stop_when='MAIN.fbFill.bDone == TRUE'. Events stream to a JSONL file. |
| rec_scanB | Enumerate the variables that could be recorded and what each would cost. source='runtime' walks the live symbol/datatype tables (every scalar leaf under prefix, or all programs/GVLs); source='project' walks the source declarations (works offline). pattern = fnmatch filter on the full path. Returns counts by type and by group (program.instance) with bytes/s estimates at cycle_ms, a suggested mode per leaf, and — when checklist='' — writes ~/.twincat_mcp/profiles/.checklist.csv with a 'select' column to mark (preselect = patterns already marked). Then rec_profile_save(name, from_checklist=name). |
| rec_profile_saveA | Save a named capture profile. Sources combine: explicit symbols (mode='auto' picks cycle for REAL/TIME, change for BOOL/INT/enum, poll for strings — or give cycle|change|poll), a marked checklist (path, or the name given to rec_scan), and/or {attribute 'tcmcp.record' := 'cycle'} pragmas in the source (from_attributes=true; scope limits to one program). Triggers and the default cycle are stored with the profile. rec_profile_start(name) replays it. |
| rec_profile_listC | Saved capture profiles (name, symbol count, modes, source). |
| rec_profile_getB | One profile in full: every symbol with its mode and cycle, triggers, per-group cost estimate. |
| rec_profile_deleteC | Delete a profile and its checklist file. |
| rec_profile_startA | Start recording a saved profile: one recording per (mode, cycle_ms) group, all named '/@'. Triggers given here override the profile's. Returns the recording ids; rec_profile_stop(name) stops them together, rec_stats/rec_export work per id. |
| rec_profile_stopA | Stop every live recording started from this profile; returns per-recording status + stats. |
| rec_listB | Recordings of this session (live status) and recording files on disk. |
| rec_statusB | Live status of one recording: events, rate, drops, armed/triggered, last value per symbol. |
| rec_snapshotC | Most recent events of a running (or finished) recording — the live tail. |
| rec_statsA | Per-symbol statistics over the whole recording so far: count, first/last, min/max/mean, change count, BOOL rising/falling edges with timestamps, and value runs (state timeline with dwell times) — computed incrementally, no re-read of the file. |
| rec_readB | Read a time window of a recording from its file. wide=true pivots to one row per event with all selected symbols forward-filled (what you want for 'what else was true when X happened'). Works on finished recordings from earlier sessions too. |
| rec_stopB | Stop a recording, release the ADS notifications, finalize the file; returns status + stats. |
| rec_exportB | Export a recording to CSV: csv_wide (t_ms + one column per symbol, forward-filled) or csv_long (t_ms,symbol,value). Default path next to the JSONL. |
| rec_deleteA | Stop (if running) and delete a recording and its exports from disk. |
| test_expectA | Assert conditions on live values. checks: [{symbol, op, value, tolerance?}], op ∈ == != > >= < <= ~= (relative/abs tolerance) in between. within_ms>0 waits until all hold. Returns pass/fail per check with the time each one was met. |
| test_stableB | Assert a value does not move more than tolerance for duration_ms (settle check for a weight, pressure, PID output, state). |
| test_responseA | Write a stimulus ({symbol: value}) and measure the PLC-timestamped latency until
|
| test_scenarioA | Scripted FB test against the live PLC with a recording in parallel. spec = {name, record:{symbols|prefix|pattern, mode, cycle_ms}, steps:[{at_ms?, write:{sym:val}} | {expect:[checks], within_ms} | {wait_ms} | {wait_until:{symbol,op,value,timeout_ms}} | {stable:{symbol,duration_ms,tolerance}}], final_expect:[checks], timeout_ms, restore, stop_on_fail}. Every written symbol is gated before the run starts; written values are restored at the end. Returns per-step results, overall pass, and the recording id. |
| ads_app_infoB | PLC application info (TwinCAT_SystemInfoVarList._AppInfo): project/app name, online change count, boot data loaded, task count, logged-in flag, app timestamp. |
| ads_task_statsB | PLC task timing (TwinCAT_SystemInfoVarList._TaskInfo[n]): cycle time, last/min/max/mean
execution time over |
| ads_pingC | ADS round-trip time statistics to the target (router/route/network health). |
| ads_call_methodA | Invoke an FB method on the running PLC via ADS RPC. The method must carry {attribute 'TcRpcEnable'}. inputs: [{type:'LREAL', value: 12.5}, …] in VAR_INPUT order (use base types: INT not E_Enum); outputs: ['BOOL', …] in VAR_OUTPUT order. Write-class. |
| snap_saveB | Save a named snapshot of live values (expanded like rec_start) for regression comparison — parameters, recipes, whole FB instances before/after a change. |
| snap_compareB | Diff snapshot |
| snap_listC | Saved snapshots. |
| rec_pulsesB | Pulse / dwell analysis of one recorded symbol: for BOOL → pulse count, high/low widths, period, frequency, duty (fine-dosing valve pulses); for other types → state timeline with dwell times. |
| rec_latencyA | Edge-to-edge latency in a recording: from each time |
| proj_interfaceB | Public interface of an FB/program: inputs/outputs/in-out with types and comments, methods (access, signature), properties (get/set), actions, extends/implements. |
| proj_lintA | Static checks over one object or the whole project: unused locals, naming prefixes
(override map via |
| proj_call_graphA | Call graph from a program/FB: FB instances it invokes, functions and methods it calls,
recursively to |
| tcunit_scaffoldA | Generate _Tests.TcPOU (TcUnit.FB_TestSuite) with Test_InitialState and one test method per public method, arranged from the FB interface, and register it in the .plcproj. Assertions are left as TODO stubs. |
| ads_dumpA | Read EVERY variable on the PLC (all top-level symbols, fully expanded through the datatype table — structs, FB instances, arrays of structs) in one pass and write a nested JSON tree plus a flat CSV (path,type,value). pattern limits the roots ('MAIN.', 'GVL_'); system/library symbols excluded unless include_system. Returns counts, file paths and a 50-leaf preview; use proj_read_file / rec-style tooling on the files for detail. |
| ads_leavesB | Enumerate every scalar leaf under a symbol with byte offsets (datatype table): 'MAIN' → all program variables, 'MAIN.arrSteps' → arrSteps[1].nId … With values=true each leaf is decoded from one read of the whole symbol. |
| ads_typesB | Runtime datatype table: describe one type (members with offsets/sizes, array bounds, enum literals, attributes) or list types matching a pattern. |
| proj_variablesA | Every variable the project source declares, flattened to runtime instance paths by walking programs and GVLs through FB/STRUCT definitions (MAIN.fbFill.fbValve.bOpen …). scope = one program/GVL/FB to walk instead of all. Library-typed variables stay as one item with their type. |
| proj_vs_runtimeA | Cross-check the source against the running PLC: variables declared in the project but not present online (not compiled / not activated / optimised away) and online variables under the same programs/GVLs that the source does not declare (stale boot project, library internals). Use after a deploy to prove the target runs this source. |
| wf_debug_symbolB | One-call debugging dossier for a variable: live value, declaring file:line chain, the statements that write it, code excerpts around them, and a short change watch. |
| wf_fb_profileB | Profile an FB instance for duration_s: records every leaf (change mode), samples task timing in parallel, then reports most-active symbols, boolean pulse rates, state dwell timelines, silent symbols and the FB's cost on the task. Read-only on the PLC. |
| wf_release_checkA | Go/no-go before a deploy: git changes, build result, lint, source-vs-runtime, TcUnit result on the target, task health. Writes nothing to the PLC. |
| wf_project_overviewA | Orientation in one call: index summary, programs with call trees, FBs with interfaces, GVLs/DUTs, lint summary, git state. |
| rec_compareA | Before/after comparison of two recordings: per-symbol stat deltas (count, min, max, mean, changes, edges) and pulse width/period deltas for BOOLs — timing regression after a code change. |
| xae_dialogsA | Modal dialogs currently open in the attached XAE shell (title, text, buttons), the watchdog's auto-answer rules and its recent log. A pending dialog blocks every COM call. |
| xae_dialog_resolveA | Click a button on an open XAE dialog ('OK', 'Yes', 'No', 'Cancel'…). remember=true adds an auto-answer rule for that title (never for machine-affecting prompts). Control-class; machine-affecting prompts (activate/run/download/login/delete/safety) are destructive-class. |
| xae_io_disableA | Set/clear the Disabled flag on I/O devices under TIID (all, or the named ones) so a configuration activates without the hardware present — TcUnit on a PC, dry runs. |
| xae_linksB | Variable links of the PLC instance: every AT %I*/%Q* variable with its link target; lists the unlinked ones (the usual reason an output never moves). |
| ads_discoverA | Broadcast search for TwinCAT targets on the local network (UDP 48899): NetId, host name, TwinCAT version, IP — the same thing XAE's 'Broadcast Search' does. |
| hmi_scanB | Index HMI symbol bindings: TE2000 .view/.content/.usercontrol/.json (%s%PLC1.X%/s%) and TcVIS files. root defaults to project.hmi_root, else the project root. |
| hmi_bindingsB | Which HMI files/controls bind a PLC symbol (fnmatch on the symbol path). |
| hmi_vs_runtimeB | Broken HMI bindings: symbols bound in the HMI that do not exist on the running PLC (and, with check_source, whether the source declares them), plus declared variables with no HMI. |
| exp_templateB | A complete example experiment spec to edit (YAML text + the same as JSON): factors × levels, runs per level, preconditions, start/done conditions, measures (last/latency/pulses/settle/ dwell/edges/expr…), metrics (mean/std/cpk/p95), criteria, writes_allowed. kind: dosing_fill. |
| exp_validateA | Validate a spec (YAML/JSON text, a dict, or a saved experiment by name): structure, measures, metrics, criteria, writes_allowed vs what the spec writes, the server guard's view of each write, symbol resolution on the connected PLC, planned run count and a duration estimate. |
| exp_saveB | Save an experiment spec (YAML or JSON) under <experiments_dir>//spec.yaml. Runs already recorded for that name are kept; resume picks up where they stopped. |
| exp_listC | Experiments on disk with run counts, state and whether a report exists. |
| exp_getB | Spec, status and run summary of one experiment. |
| exp_runsD | Run records: level, status, measures, recording ids, duration, error. |
| exp_runA | Run an experiment in the background: per level × repetition → preconditions → factor values written → snapshot → capture profile started → stimulus → start acknowledged (done_when must go false) → done_when → settle → stop → measures → runs.jsonl. Factor values are read first and restored at the end or on abort (read back and checked). Every write is re-checked against the server guard, pinned to the machine the experiment started on, and audited with symbol and value; a refusal, a target change or a timed-out write stops the experiment. dry_run resolves every symbol, coerces condition values (enum names → ints) and prints the plan without writing. Starting is control-class: in guarded mode it asks once (elicitation / confirm_token); in full mode it does not. Only one experiment may run at a time. |
| exp_statusA | Live state of a running experiment: planned/done/failed, current level, ETA, last error, live recording ids. For an experiment from an earlier session, the persisted status. |
| exp_abortA | Stop a running experiment after the current step; recordings are closed, factor values restored. |
| exp_evaluateB | Metrics per level with 95 % CIs and the criteria verdicts (pass / fail / inconclusive with the run count that would settle it). Deterministic from runs.jsonl; rerunnable by anyone. |
| exp_reportA | Write <experiments_dir>//report.md and report.html: identity (machine, TwinCAT version, project, git state, safety mode), criteria table, metrics per level, charts (primary measure per run; per-level mean/CI), run table, the spec, the audit log of writes during the run, and the interpretation — stored separately and labelled as not computed. interpretation= saves a new one (author=agent|operator|). firmware_check=true runs proj_vs_runtime first. |
| exp_compareB | Two experiments with the same levels side by side: metric deltas and whether their 95 % CIs separate (the before/after question with error bars). |
| infosys_booksA | List Infosys books (documentation sets) from the site's own sitemap, with page counts and whether they are indexed locally. pattern is a glob on the slug ('tcplclib_*', 'json'); category: plc-library | function-tf | engineering-te | twincat-system | hardware | other. TwinCAT 2 books are excluded. First call downloads the sitemap (a few MB, cached 7 days). |
| infosys_indexA | Index a book (or glob of books, e.g. 'tcplclib_tc3_*') into the local cache: fetches every page that is new or changed since the last run (sitemap lastmod), extracts title/kind/library/ declaration, builds the full-text index. Tc2_System ≈ 300 pages ≈ 30-60 s. Needed before infosys_search_symbols/search_code can see a library; infosys_search falls back to the web. |
| infosys_search_symbolsA | Find library symbols (function blocks, functions, structs, enums, aliases, interfaces, GVLs) by name fragment in the indexed books; exact > prefix > contains. kind: FunctionBlock | Function | Program | Method | Property | Action | Enum | Struct | Union | Alias | Interface | GlobalVariable | Library. library: 'Tc2_System' or the book slug. Indexes the default libraries on first use if nothing is indexed. |
| infosys_declarationB | Declaration of a library symbol as data: kind, inputs/outputs/in_out (name, type, default, description from the page's table), struct members, enum values, return type, EXTENDS / IMPLEMENTS, plus the ST declaration text and the page URL. The thing to call before writing code against an FB you have not used before. |
| infosys_searchB | Full-text search over the indexed Infosys pages (FTS5, bm25-ranked, excerpt with [hits]). When the local index has nothing, falls back to a DuckDuckGo site: query whose results are verified against the Infosys sitemap (TwinCAT 3 only) and fetched for title/excerpt; the 'backend' field says which path answered. |
| infosys_search_codeB | Search the code examples ( blocks) of indexed pages for a fragment — a call pattern, an attribute, a constant. language: st | xml | cpp | csharp. Returns the matching lines with context and the page URL. |
| infosys_get_pageA | A documentation page as Markdown (headings, tables, fenced code). ref: full Infosys URL, 'book/pageid', a bare page id, or a symbol name ('ADSREAD'). Fetched live and cached; works for any page that exists on the site, indexed or not. refresh=true bypasses the cache. |
| ads_exportB | Generate code from the runtime: fmt=csharp (explicit-offset structs + enums for Beckhoff.TwinCAT.Ads ReadAny/WriteAny), typescript (interfaces), json (type descriptions), or csharp_symbols (const symbol paths under prefix). types = struct/enum names; prefix = take the types of every symbol under it. |
| snap_applyA | Write a saved snapshot back to the PLC (recipe / parameter restore). dry_run lists the differences only. Every differing symbol is gated like ads_write. |
| proj_validate_xmlA | Structural validation of .TcPOU/.TcDUT/.TcGVL files: XML well-formedness, Name/Id, GUID format + project-wide uniqueness, Declaration/Implementation presence, property accessor VAR blocks, LineIds vs implementation line counts, EOF newline. fix=true applies safe fixes (.bak written); regenerate_lineids rebuilds LineIds blocks. |
| ipc_eventlogA | Windows event log of the target (Windows 7/10/11 IPCs): runs wevtutil on the IPC via the System Service, then reads the result file back. Not available on Windows CE / TC-BSD targets (use the XAE error list for ADS logger messages there). Destructive-class because it starts a process on the IPC. |
| tc_session_reportA | Markdown handover of this session: mode changes, writes, deploys and other mutating calls from the audit log, recordings, snapshots and dumps produced. Written to ~/.twincat_mcp/reports/.md (or out_path). |
| ipc_read_fileA | Read a file from the target IPC's file system over ADS (no share needed), e.g. 'C:\TwinCAT\3.1\Boot\TcUnit_xUnit_testresults.xml' or a log. Binary → base64. |
| ipc_list_dirB | List files on the target matching a Win32 pattern, e.g. 'C:\TwinCAT\3.1\Boot*'. |
| ipc_write_fileC | Write a file on the target IPC (text or base64). Control-class. |
| ipc_delete_fileC | Delete a file on the target IPC. Destructive-class. |
| ipc_start_processC | Start a process on the target IPC (NT_StartProcess equivalent). Destructive-class. |
| ipc_rebootC | Reboot (or shut down) the target IPC via the System Service. Destructive-class. |
| xae_attachA | Attach to the running XAE shell / Visual Studio (Running Object Table). Picks the instance holding solution_path when given. launch=true starts a new shell (slow). |
| xae_statusC | Shell version, open solution, projects, TwinCAT project name, target NetId, started flag. |
| xae_open_solutionB | Open a .sln in the attached shell. |
| xae_buildA | Build the solution (File.SaveAll first by default). Returns success, error/warning items with file:line (VS error list, or parsed from the Build output pane) and the output tail. check_all_objects=true runs PLC 'Check all objects' instead (compiles unused POUs). |
| xae_diagnosticsA | Current error list (errors/warnings/messages with file:line) plus the tail of the Build output pane, without rebuilding. |
| xae_list_commandsB | List DTE command names containing a substring (to discover what this shell exposes). |
| xae_commandB | Execute an arbitrary DTE command (e.g. 'PLC.Login'). Control-class; commands whose name contains download/reset/activate/restart/delete/remove/shutdown are destructive-class. |
| xae_plcA | PLC online actions through the shell: login | logout | start | stop | reset_cold | reset_origin | download. Command names vary by shell version; all candidates are tried. download/reset_cold/reset_origin are destructive-class, the rest control-class. |
| xae_targetB | Get (net_id=None) or set the target AMS NetId of the TwinCAT project. Setting is control-class. |
| xae_activate_configurationA | ActivateConfiguration on the current target (overwrites the boot project on the IPC). Destructive-class. Follow with xae_restart_twincat. |
| xae_restart_twincatC | StartRestartTwinCAT on the current target (runtime restarts in RUN mode). Destructive-class. |
| xae_deployA | Save → build → (boot project autostart on) → activate → restart, in one call. Stops at the first build error. Destructive-class (one confirmation covers all steps). Refuses when the XAE target and the ADS target of this server differ. |
| xae_tree_getA | System Manager tree item: properties, children to |
| xae_tree_consume_xmlB | ConsumeXml on a tree item — the generic write path for any configuration (add I/O boxes, link variables, set task cycle time, add project routes on TIRR …). |
| xae_tree_set_valuesB | Set element texts in a tree item's XML by relative XPath, e.g. {'TaskDef/CycleTime': '10000'} (unit 100 ns). |
| xae_tree_create_childB | Generic CreateChild (tree item types/subtypes per Infosys). For PLC objects prefer xae_pou_create. |
| xae_tree_deleteC | Delete a tree item (POU, box, task …). Destructive-class. |
| xae_plc_projectsA | PLC projects in the TwinCAT project with their tree paths (needed by PLCopen / boot tools). |
| xae_pou_getB | Declaration/implementation text of a POU/DUT/GVL/interface tree item and its methods/properties/actions. |
| xae_pou_setA | Replace declaration and/or implementation text of a POU item inside the live shell (no file round-trip, XAE keeps LineIds consistent). Build afterwards. |
| xae_pou_createB | Create a PLC object under a folder/POU: kind = program | fb | function | method | property | action | transition | struct | enum | union | alias | gvl | interface | itf_method | itf_property | folder | parameter_list. Optional code is set after creation. |
| xae_plcopen_importB | Import a PLCopen XML file into a PLC project (path from xae_plc_projects). option: none | rename | replace | skip (conflict handling). |
| xae_plcopen_exportB | Export PLC objects ('POUs.FB_X', 'DUTs.ST_Y' — folder.object) to a PLCopen XML file. |
| xae_boot_projectB | Boot project settings: set Autostart and/or GenerateBootProject (local, no activate unless activate_after_generate=true, which is then destructive-class). |
| proj_scanB | Index the project tree (.sln/.tsproj/.plcproj/.TcPOU/.TcDUT/.TcGVL/.TcIO). incremental=true re-indexes only files whose mtime changed (fast after XAE saves). |
| proj_changedA | Units whose source differs from a git revision (default: uncommitted work) plus untracked files — 'what did I change?'; pair with proj_vs_runtime for 'is it deployed?'. |
| proj_listC | List indexed objects. kind: PROGRAM | FUNCTION_BLOCK | FUNCTION | STRUCT | ENUM | UNION | ALIAS | GVL | INTERFACE | METHOD | PROPERTY | ACTION (case-insensitive). |
| proj_get_codeB | Source of an object ('FB_Valve', 'FB_Valve.Open', 'MAIN'): declaration/implementation with file line numbers, parsed VAR declarations, sub-items. |
| proj_resolve_symbolB | Map an ADS symbol path (MAIN.fbFill.fbValve.bOpen) to the file:line where each hop is declared, following variable types through FB/STRUCT definitions. |
| proj_searchC | Regex search over all declarations/implementations → unit, file, line, text. |
| proj_referencesC | Where a type/object is instantiated (variables of that type) and mentioned. |
| proj_read_fileC | Raw text of a project file (relative to project root or absolute). |
| proj_set_codeA | Write declaration/implementation back into the .TcPOU/.TcDUT/.TcGVL file (keeps the rest of the XML byte-identical, writes a .bak, drops the object's stale ). Use when XAE is closed or for batch edits; otherwise prefer xae_pou_set. |
| tcunit_resultsB | Parse a TcUnit xUnit result into a pass/fail summary. Source: the file on the target over ADS (default: configured remote path), a local file, or raw XML text. |
| tcunit_runA | Full TcUnit cycle: build → boot project autostart+generate → activate → restart → delete old result → wait for the xUnit file on the target → parse. Destructive-class (it activates a configuration on the target). plc_project_path from xae_plc_projects. |
Prompts
Interactive templates invoked by user choice
| Name | Description |
|---|---|
| debug_symbol | Investigate why a PLC variable has the value it has |
| fb_validation | Validate a function block against its specification on the live machine |
| deploy_safely | Build, check and deploy a change to the target with evidence |
| performance_audit | Find what costs cycle time and where timing is marginal |
| onboard_project | Get oriented in an unfamiliar TwinCAT project |
Resources
Contextual data attached and managed by the client
| Name | Description |
|---|---|
| res_config | |
| res_audit | |
| res_safety |
TDQS
Scored across 139 tools
Tools are grouped into coherent families (ads_*, rec_*, proj_*, xae_*) and descriptions are unusually detailed, but multiple overlapping variants exist — ads_read vs ads_read_many vs ads_dump vs ads_leaves, several write paths, several recording/test entry points — so an agent must carefully read descriptions to avoid misselection.
Names consistently use snake_case with subsystem prefixes (ads_, proj_, xae_, rec_, exp_, infosys_), and most operations include a verb. Minor deviations are noun-only/stateful names (ads_status, proj_interface, xae_plc) and the workflow-layer wf_ prefix mixed with subsystem naming, but the pattern remains readable and predictable.
139 tools is far beyond the 3–15 well-scoped range and well past the 25+ 'too many' threshold. Even for the broad TwinCAT domain, the set is a kitchen sink with layered and overlapping capabilities, imposing severe selection overhead on an agent.
Coverage is extensive across the TwinCAT lifecycle: project indexing, code get/set, build/deploy/activate, runtime ADS read/write, recording, experiments, HMI, Infosys docs, IPC, safety and audit. Some minor lifecycle gaps remain (e.g. explicit experiment deletion, HMI editing), but there are few obvious dead ends.