tiax MCP server — tool reference
tiax-agent mcp (official MCP SDK; the legacy tiax mcp serves the same catalog) serves
in two concurrency lanes (cache calls never queue behind a live call):
- Cache tools answer instantly from the scanned
.tiaxcache. No TIA Portal involved, ever. - Live tools touch the real project, one at a time, in a persistent engine per TIA version
(TIA Portal and the project stay open between calls), or in a one-shot child tiax process per call
with
--no-engine. Long operations emit MCP progress notifications every 5 seconds.
What a session lists depends on the toolset (--toolset explore|generate|commission|admin|extend|all)
and on the policy (a tool the policy refuses whatever its arguments is not listed). Every tool stays
callable; find_tool searches the full catalog.
Registration
tiax-agent setup --client <list> or --all writes the server entry for Claude Desktop, Cursor,
VS Code, Claude Code, Windsurf, Cline, Codex CLI and Gemini CLI (INSTALL.md).
By hand, for Claude Code:
claude mcp add tiatool -- "C:\Program Files\TIATool\tiax-agent.exe" mcp --tiax "C:\Workspaces\<project>\.tiax"
Without a cache the server still starts; refresh_scan creates it. Call refresh_scan after any
export.
Long calls: tool timeouts
export_project, compile_project and build_from_source legitimately take 40 seconds to several
minutes (the first call starts TIA Portal headless and opens the project). Most MCP clients default
to a shorter tool-call timeout:
- Claude Code reads
MCP_TOOL_TIMEOUT(milliseconds) from its own environment, not from the server entry: start it withMCP_TOOL_TIMEOUT=600000 claude, or put"MCP_TOOL_TIMEOUT": "600000"under"env"in~/.claude/settings.json. (MCP_TIMEOUTis only the server start-up timeout and does not help; setup no longer writes it.) - Cline, Codex CLI, Gemini CLI:
tiax-agent setupwrites a 600 s per-server timeout into the entry. - Other clients: their own tool-timeout setting. Progress notifications keep the session alive where the client honours them, but the hard timeout must still cover the operation.
Tool catalog
Generated from docs/tiax/mcp-catalog.json (tiax-agent catalog) by
python3 tools/capabilities.py render — do not edit the table by hand. Status comes
from the capability registry (docs/capabilities.json, docs/tiax/capabilities.md);
non-proven tools carry the same status line in their MCP description.
| Tool | Arguments (bold = required) | Lane | Licence | Status | Summary |
|---|---|---|---|---|---|
project_stats |
— | cache | read | proven | Inventory of the TIA project: PLCs, block counts by type and language, and the fidelity roll-up saying how much of the project is actually readable. |
list_blocks |
type, language, plc, name_contains |
cache | read | proven | List blocks in the project. |
get_block |
name |
cache | read | proven | The full record for one block: interface tree, per-network logic as SCL, calls, and read/write edges. |
who_writes_tag |
symbol, exact |
cache | read | unit_tested | Every place a tag or variable is WRITTEN, with the block, network, and the logic that writes it. |
who_reads_tag |
symbol, exact |
cache | read | unit_tested | Every place a tag or variable is READ, with block, network and the reading logic. |
who_calls |
block |
cache | read | proven | Which blocks call the given block, with the instance name used. |
what_block_calls |
block |
cache | read | proven | Which blocks the given block calls (callees, from CallInfo), including the instance DB used — the downward half of the call graph; who_calls is the upward half. |
unreachable_blocks |
— | cache | read | proven | Code blocks never reached from any OB — dead code candidates. |
search_project |
text, limit |
cache | read | proven | Ranked free-text search across block names, titles, comments and logic — and HMI content (screen texts, tag bindings, events). |
list_screens |
device, name_contains |
cache | read | proven | HMI screens, templates and popups in the scanned project — name, device, object count and fidelity. |
get_screen |
name |
cache | read | proven | The full record for one HMI screen: every object with its texts, tag bindings, animations and events, plus the tags_used and navigation rollups. |
hmi_tag_map |
filter |
cache | read | proven | Every HMI tag with its table, connection and the screens using it (joined by name over each screen's tags_used). |
where_is_tag_used_on_hmi |
symbol, exact |
cache | read | proven | Where a PLC-side symbol shows up on the HMI: screens whose tags_used match and HMI tag tables whose tag names match. |
tia_status |
— | live | read | unit_tested | Live environment check: installed TIA Portal Openness versions, whether a TIA Portal process is running (with PIDs), the cache being served and whether it is stale, and the scanner version. |
refresh_scan |
exports_folder |
live | read | proven | Re-scan the exports folder into the cache this server is serving, then reload the index in place, so the cache tools answer from fresh data. |
backup_project |
project |
live | read | unit_tested | Zip the whole project folder to a restore point beside it — the same backup every write tool takes automatically, on demand. |
export_project |
project, output_folder, compile, incremental, attach, timeout_min, task |
live | conditional | unverified | Export all PLC blocks, tag tables, types, watch tables and external sources from the REAL project to SIMATIC ML XML in output_folder. |
list_devices |
project, attach |
live | read | unverified | The REAL project's hardware tree: devices, plugged modules, article numbers, firmware and I/O address ranges. |
compile_project |
project, plc, hmi, block, task, verify, verify_targets |
live | write | unverified | Compile every PLC and HMI target in the REAL project (or the plc / hmi named, or only the given blocks of one PLC) and save it. |
clean_sources |
project, only, dry_run, task, verify, verify_targets |
live | write | proven | Delete leftover external source files from the REAL project (they break TIA's Search and Cross-references) and remove the stale XRef cache. |
build_from_source |
project, source_folder, no_hardware, no_hmi_tags, no_compile, dry_run, delete_blocks, plc, hmi, task, verify, verify_targets |
live | write | unit_tested | Generate the REAL project from a source folder: hardware.json modules, TagTables/*.xml, *.scl block sources, optional HmiTags, then compile. |
import_block |
project, block_xml, plc, hmi, task, verify, verify_targets |
live | write | unit_tested | Surgically import ONE edited SIMATIC ML block XML into the REAL project, overriding the block of the same name inside a transaction. |
hmi_import_screens |
project, screens_folder, plc, hmi, task, verify, verify_targets |
live | write | unit_tested | Import every *.xml in screens_folder as an HMI screen, overwriting by name. |
hmi_import_tags |
project, tag_files_dir, plc, hmi, task, verify, verify_targets |
live | write | unit_tested | Import HMI tags ONE PER FILE: tag_files_dir holds one subfolder per (existing) tag table, each containing |
add_project_languages |
project, languages, task, verify, verify_targets |
live | write | proven | Add cultures to the project's active languages, e.g. |
generate_equipment |
equipment, output_folder, tag_table |
live | read | unit_tested | Generate PLC code for pumps, valves and motors from proven templates, named per the SCL naming convention: FB FB_Pump/FB_Valve/FB_Motor (feedback supervision, thermal trip, latched faults with reset), one instance DB per equipment (IDB_Pump_P101), command struct in DB_Equipment, PLC tags I_P101_Running/Q_P101_Run in a tag table, and an FC 'Equipment' calling every instance. |
io_list_import |
file, output_folder, project_name, dry_run |
live | read | unit_tested | Turn an electrical I/O list (CSV or XLSX; columns Name/Tag, Address, optional Type, Comment, Table, Station, Module, OrderNumber, Firmware, Slot — English/German/Dutch headers recognised) into PLC tag tables (TagTables/*.xml for build_from_source), a hardware.json module plan, and an AutomationML file for hardware_import. |
generate_alarms |
alarms, output_folder, languages, classes, hmi_tag_prefix, first_number |
live | read | unit_tested | Generate a bit-coded alarm system: DB_Alarms (alarm Words), FC 'Alarms' packing each trigger into its bit, a WinCC Comfort/Advanced discrete-alarm CSV, the HMI tag list, and a Unified alarm spec for unified_build. |
project_diff |
old_cache, new_cache, filter |
cache | read | unit_tested | Compare two scans (.tiax caches) — e.g. |
export_docs |
output_file, filter, include_scl |
live | read | proven | Write project documentation from the cache: block catalogue, per-block interface tables, calls / called-by, tag tables with addresses, HMI screen inventory. |
hardware_import |
project, aml, mode, task, verify, verify_targets |
live | write | unverified | Import hardware from an AutomationML (.aml) file into the REAL project via the CAx interface — devices, modules by order number + firmware, tag tables. |
library_list |
project, global_library |
live | read | unverified | List the types (blocks, PLC data types, faceplates…) of the project library or a global library, with versions, states and the default version. |
library_use |
project, type, plc, global_library, version, update, task, verify, verify_targets |
live | write | unverified | Use a library type in the REAL project: instantiate a released block/PLC-data-type version into a PLC (keeps the link to the type), or with update=true update all instances in the PLC to the latest released version. |
alarm_texts |
project, action, xlsx, plc, task |
live | conditional | unverified | PLC alarm text lists as Excel: action=export writes the XLSX (two sheets, lists + entries); edit it (or let the model fill translations); action=import overrides the lists from it (entries of a list in the file replace that list's entries). |
plc_online |
project, plc |
live | read | unverified | Online state of a PLC (Offline/Connecting/Online/Incompatible…) and the PC interfaces TIA can reach it through — run before plc_download to pick pc_interface. |
plc_download |
project, plc, pc_interface, pc_interface_number, ip, hardware, software, allow_stop, allow_reinit, start_after, confirm_token, task |
live | write | unverified | Download the compiled program (and optionally hardware config) to a real PLC or a PLCSIM Advanced instance. |
unified_build |
project, spec, spec_file, what_if, task, verify, verify_targets |
live | write | unverified | Generate WinCC Unified screens from a JSON spec into the REAL project: screens, items (HmiButton, HmiIOField, HmiText, HmiCircle, HmiRectangle…) with position/size/text, tag bindings (validated against the HMI tag tables), Release-event navigation buttons, and discrete alarms (from generate_alarms). |
plcsim |
action, instance, tags, set, power_off, task |
live | conditional | unverified | Control S7-PLCSIM Advanced: action list | start (register, power on, RUN) | stop | read (tags) | write (set). |
plcsim_test |
instance, spec, spec_file, task |
live | write | unverified | Run an input→output test spec against a PLCSIM Advanced instance: per case set inputs, wait, assert outputs (Bool/Int exact, Real with tolerance or {min,max}). |
explain_error |
text, limit |
cache | read | unit_tested | Look up an error message (TIA Portal, Openness, compiler, import, tiax) in the field-proven knowledge base and return the matching entries with their rule and fix. |
verify_change |
targets, interface_delta, allow_attribute_changes, baseline, candidate, task |
cache | read | unit_tested | The verify gate between a baseline cache and the cache taken after a change: 1 blast radius vs the declared targets (instance DBs of a target allowed), 2 block attributes (author, family, version, language, safety, memory layout), 3 interface (start value changes = warning), 4 scan shape (counts, failure ledger, readable %, fidelity regressions), 5 remanence and External* per member. |
audit_project |
profile, rule, show_settled |
cache | read | unit_tested | Audit the scanned project: multiple writers, declared-never-written and written-never-read members, unwired FB inputs at call sites, POKE/PEEK/BLKMOV with literal offsets, retain in volatile DBs and mixed lifetimes, external HMI tags with no PLC match (by name), lossy renderings, and the Modbus register-map self-check on Standard-layout DBs. |
finding_verdict |
fingerprint, verdict, note |
cache | read | unit_tested | Record a verdict on an audit finding (by fingerprint from audit_project): accepted (real, will fix or live with), false_positive, wont_fix, or open again. |
workspace_init |
folder, project, name, exports, cache, customer, site, serial, standard |
cache | read | unit_tested | Create the project workspace (the per-project work folder: tiatool.workspace.json, journal.jsonl, plan.json, assumptions.md, decisions.md, findings.json — plain text, git-friendly). |
workspace_status |
— | cache | read | unit_tested | One-call situation report: workspace, cache freshness and format, active baseline, licence, plan task counts, last writes with their verify results, open assumptions and findings, and the suggested next step. |
task |
action, id, title, detail, status, note |
cache | read | unit_tested | The change plan (plan.json). |
assumption |
action, title, status, why, impact, next_action, follow_up_of, number, resolution, all |
cache | read | unit_tested | The numbered assumptions register (assumptions.md; knowledge/standards/assumptions-register.md). |
decision_add |
title, text, by |
cache | read | unit_tested | Append a decision to decisions.md (what was decided, why, by whom). |
baseline_set |
name, note |
cache | read | unit_tested | Freeze the current cache as a named baseline (copied to snapshots/ |
restore_backup |
project, backup, mode, list, confirm_token, task |
live | conditional | unit_tested | Restore a project from one of its timestamped restore points. |
template_list |
category |
cache | read | unit_tested | List the equipment templates (built-in, %APPDATA%\TIATool\templates overrides, |
template_show |
id, include_source |
cache | read | unit_tested | Show one template: signals (role, direction, type, required), parameters with defaults and units, HMI commands and statuses, interlock input, ISA-18.2 alarms, compliance notes (to confirm), SimHarness tests, and the SclSelfCheck result. |
model_validate |
model |
cache | read | unit_tested | Check the equipment model ( |
model_generate |
model, batch, out, overwrite |
cache | read | unit_tested | Generate a build_from_source folder from the equipment model into |
model_from_io_list |
io_list, out, cpu_family, tia_version |
cache | read | unit_tested | Draft model/equipment.json from an I/O list (CSV/XLSX/tab text with name, address, type, comment, table): tags like I_BP1_Running / Q_BP1_Run are grouped by equipment and matched to the template whose signals fit best. |
template_extract |
block, id, overwrite |
cache | read | unit_tested | Turn an FB from the scanned project (cache) into a template skeleton in |
openness_browse |
project, path, depth |
live | read | unverified | Explore the LIVE Openness object model of the project — anything Openness exposes, including what no dedicated tool covers. |
openness_get |
project, path, attribute |
live | read | unverified | Read ONE attribute of a live Openness object, with its access mode and types. |
openness_set |
project, path, attribute, value, confirm_token, task, verify, verify_targets |
live | write | unverified | WRITE one attribute of a live Openness object (any writable attribute openness_browse lists). |
openness_invoke |
project, path, action, args, confirm_token, task, verify, verify_targets |
live | conditional | unverified | Run one Openness ACTION on a live object (the actions openness_browse lists, with their parameter types). |
find_tool |
query, toolset, limit |
cache | read | unit_tested | Search the FULL tool catalog by name and description — including tools this session does not list (tiax-agent --toolset). |
script_check |
code, tia_version, project |
cache | read | unit_tested | Compile a C# Openness script and check it against the guard rail — nothing runs and no project is opened. |
script_run |
project, code, mode, args, timeout_minutes, no_transaction, confirm_token, task, verify, verify_targets |
live | conditional | unverified | Run a C# script against the REAL project inside the TIATool engine. |
extension_run |
id, project, args, timeout_minutes, confirm_token, task, verify, verify_targets |
live | conditional | unverified | Run a saved extension (built-in, %APPDATA%\TIATool\extensions or |
extension_save |
id, title, description, category, mode, parameters, code, from_run, tags, min_tia, overwrite, force_unverified |
cache | read | unit_tested | Promote a script that compiled AND ran successfully in this session (script_run) to a reusable extension: writes |
extension_list |
query, category, kind |
cache | read | unit_tested | Search the extension library: built-in pack (~40 live Openness scripts + offline cache queries: watch/force tables, text lists, technology objects, libraries, network, HMI, UMAC, tags, UDTs, blocks...), then %APPDATA%\TIATool\extensions and |
extension_show |
id |
cache | read | unit_tested | One extension in full: manifest (description, parameters as JSON Schema, mode, min_tia, status, provenance), where it comes from (builtin / user / workspace override) and its code (script.cs or query.js). |
cache_query |
code, extension, args |
cache | read | unit_tested | Run JavaScript over the scanned cache — offline, read-only, no TIA Portal — for any question the fixed cache tools do not answer. |
knowledge_add |
title, symptom, cause, fix, evidence, tags, overwrite |
cache | read | unit_tested | Record what this session learned so the next one does not hit it again: writes a knowledge-base entry ( |
project_create |
project, task |
live | write | unverified | Create a new, empty TIA project. |
project_archive |
project, out |
live | read | unverified | Archive the REAL project to a compressed .zapNN file (Project.Archive). |
project_retrieve |
archive, out_dir |
live | read | unverified | Retrieve a .zapNN archive into a NEW folder (missing or empty) and report the project file found there. |
scl_lint |
scl_text, style_check |
cache | read | unit_tested | Check SCL source text before it goes anywhere near TIA: every FUNCTION_BLOCK, FUNCTION, DATA_BLOCK, TYPE and ORGANIZATION_BLOCK, with line numbers. |
scl_apply |
project, scl_text, plc, group, compile, confirm, task, verify, verify_targets |
live | write | unverified | Apply SCL source text to ONE PLC of the REAL project: scl_lint first (errors refuse; warnings refuse unless confirm=true), backup, generate the blocks through a temporary external source that is deleted again, compile only that PLC, save. |
plc_compare_online |
project, plc, pc_interface, pc_interface_number |
live | read | unverified | Labs: compare the REAL project's PLC software with what runs on the PLC (offline vs online, the CompareToOnline tree) and list what differs. |
Typical durations: cache lane instant; live tools 30 s – 3 min with a cold Portal (seconds once the
engine has the project open), build_from_source 2–10 min (dry_run: seconds). A write is followed
by the post-write verify (an incremental export and a scan). Raise the client's tool timeout
accordingly (above).
Licence column: every tool needs an active licence. read never changes a project, write does
(needs the licence's write feature), conditional writes for some arguments only — for example
script_run mode=write, restore_backup mode=in_place, openness_invoke of a writing action).
Result semantics: a child exit code of 2 (partial success) comes back as a
normal result prefixed PARTIAL — the operation completed with a failure ledger; read it before trusting the result. Exit 1 or 64 comes back with
isError: true carrying the tail of the child's output. Refusals by the argument rails or the policy
carry _meta.refused (invalid_arguments, policy) with the rule and the argument.
Safety rails (not negotiable over MCP)
- Argument rails. Every call is checked against the tool's
inputSchema(no undeclared arguments, right types, enums, required arguments, no NUL) before the policy and the licence. A string that starts with-is refused outside free-text fields, and child processes get--key=valuearguments on a command line escaped the way Windows splits it — no argument can become--no-backup,--allow-tia-runningor--in-place.dry_run/what_ifexist only where the tool really previews. - Policy before licence. The machine policy (
%ProgramData%\TIATool\policy.json) over the workspace policy decides tools, read-only, online access (allow_online, default false), scripts, allowed folders, confirmations and write rate (security/policy.md). - A person approves.
plc_download, an in-placerestore_backup, write scripts and extensions,openness_set/openness_invokeand whatever the policy lists ask the user — as a form in the client (MCP elicitation; the model never sees a token) or throughtiax-agent approve <id>. Theconfirm_tokenround trip is used only underconfirm_mode: in_band. - Backups are always on. Every write tool zips the whole project folder beside it before touching
anything, as a timestamped restore point (
<name>_tiax_backup_<yyyyMMdd-HHmmss>.zip+.jsonsidecar with reason and sha256; the newest 20 are kept). No MCP schema exposes--no-backup. - No fight with the TIA Portal UI. Every tool that opens the project refuses while a TIA Portal
UI process runs, naming the PID(s); writes answer
UI_SESSION_OPEN. Reads can go through the UI instead withattach: true(export_project,list_devices). Portal processes the engine owns do not count. - Explicit targets. In a project with several PLCs or HMIs,
plc/hminame the target; an ambiguous one is refused withAMBIGUOUS_TARGETbefore anything changes. - Journal and verify. Every write is journaled (OS user, host, client, approval, hash chain) in
the workspace — an implicit one per project when none is configured — and followed by
export → scan → verify gate (
verify: falseskips it for one call). - No silent retries. If the engine dies after a verb was sent, the call fails and is not retried (the write may be half-done; the backup is the restore point). Any exception resets the engine session (close without saving).
- Staleness is never hidden. Cache tools prefix their answers with a STALE warning whenever the
exports are newer than the cache, or the cache was written by an older record revision;
refresh_scanre-scans and reloads the index in place. - Version safety. Opening a project never upgrades it, and the call goes to the engine of the
project's version (
tiax.exe↔tiax-v21.exe) by its extension. - Untrusted project text. Comments, titles and HMI texts come back fenced as
UNTRUSTED PROJECT DATA, so instructions hidden in a project read as data.
Recommended flow for a write session: tia_status → (scl_lint, or build_from_source with
dry_run: true) → the write (the user approves when asked) → the post-write pipeline verifies it →
workspace_status shows the journal and the verdict.
HMI cache tools
HMI tools answer from the cache like the other cache tools; against a format-1 cache they reply "re-run tiax scan" instead of guessing. HMI↔PLC links are matched by name — SIMATIC ML exports do not carry the ControllerTag link.
Built from docs/tiax/mcp-tools.md in the product repository. Links to files that are not published here are shown as plain text.