Skip to content
Agentmart
Submit a tool

FTX MCP — FactoryTalk Optix MCP Server

MCP server for FactoryTalk Optix: author, preview, and verify Studio changes via the emulator.

Connector by asqi-carter · GitHub account verified by the MCP Registry

IndexedLicense unknownRemote (HTTP)★ 17
Write a review

Chalk Labs

Need help deploying FTX MCP — FactoryTalk Optix MCP Server?

Chalk Labs sets up agents like this inside real teams: connected to your tools, tested on your data, with a human in the loop where it matters.

Book a call

Install

Pick your client. Read the repository before you give any tool access to your data.

No install instructions from the source yet. Check the repository for setup steps.

Get the weekly diff

The weekly diff: one email a week with new agent tools, notable updates and grade changes, plus security alerts for tools you follow. Double opt-in, one-click unsubscribe.

We use your email only for this newsletter. Privacy

About

MCP server for FactoryTalk Optix: author, preview, and verify Studio changes via the emulator.

No reviews yet. Installed it? Reviews come from verified installers only. How reviews work

Permissions

What this server can do and what it asks for, from its tool list, install config and code. Checked Oct 25, 2026.

Runs code on install

Its package runs an install script (such as npm postinstall or setup.py code) as soon as you install it, before any tool is called. Read the script first.

Tools
19 read · 49 write · 1 delete · 8 not yet classified
Secrets
None asked for
Install scripts
Runs code on install
Runs as
Python package

Tools by what they do 77

Read from the source code; the running server may list different tools.

Read 19 · Look things up without changing anything.

  • optix_cdp_diff
  • optix_cdp_find_text
  • optix_cdp_read_text
  • optix_cdp_screenshot
  • optix_cdp_sweep
  • optix_describe_node
  • optix_describe_type
  • optix_find
  • optix_get_project_map
  • optix_get_skill
  • optix_list_projects
  • optix_list_screens
Show 7 more tools
  • optix_list_skills
  • optix_list_ui_types
  • optix_observe
  • optix_read_file
  • optix_read_netlogic
  • optix_runtime_status
  • optix_studio_log

Write 49 · Create, change, send or run things.

  • optix_add_model_variable
  • optix_add_widget
  • optix_bridge_add_bound_widget
  • optix_bridge_add_label
  • optix_bridge_add_navigation_panel_item
  • optix_bridge_add_translation
  • optix_bridge_add_translations
  • optix_bridge_arm
  • optix_bridge_attach_expression
  • optix_bridge_attach_formatter
  • optix_bridge_bind_property
  • optix_bridge_convert_to_type
Show 37 more tools
  • optix_bridge_create_alias
  • optix_bridge_create_folder
  • optix_bridge_create_netlogic
  • optix_bridge_create_object
  • optix_bridge_create_type
  • optix_bridge_create_variable
  • optix_bridge_create_widget
  • optix_bridge_edit
  • optix_bridge_ensure_web_engine
  • optix_bridge_import_tags
  • optix_bridge_invoke_method
  • optix_bridge_log_tail
  • optix_bridge_move_node
  • optix_bridge_remove_translation
  • optix_bridge_reorder
  • optix_bridge_retype
  • optix_bridge_set_modelling_rule
  • optix_bridge_set_property
  • optix_bridge_set_text_key
  • optix_bridge_status
  • optix_bridge_validate_expression
  • optix_bridge_wire_event
  • optix_build_check
  • optix_cdp_click
  • optix_cdp_fill
  • optix_cdp_key
  • optix_cdp_navigate
  • optix_cdp_restart
  • optix_cdp_type
  • optix_deploy
  • optix_deploy_preflight
  • optix_deploy_updatesvc
  • optix_execute_method
  • optix_runtime_start
  • optix_runtime_stop
  • optix_save
  • optix_set_property

Delete 1 · Delete, drop, revoke or wipe things.

  • optix_bridge_delete_node

Not yet classified 8 · We could not tell from the name and description.

  • optix_active_target
  • optix_cdp_ocr
  • optix_emulator
  • optix_interact
  • optix_project
  • optix_routes
  • optix_schema
  • optix_status

Network hosts it talks to 1

  • github.com · found in code

Files it touches

  • %LOCALAPPDATA%
  • %LOCALAPPDATA%\\ftx-mcp\\bridges\\
  • %LOCALAPPDATA%\Programs\Tesseract-OCR\tesseract.exe
  • Your home directory (~)
  • C:\\Windows
  • C:\\WINDOWS\\system32
  • Any path the agent passes to its tools

Tools (77)

Read from the source code; the running server may differ. Descriptions are the server’s own words; hidden characters are shown as [U+…].

  • optix_active_target

    Which deployment target Studio's dropdown has selected — the thing an F5 (optix_emulator action="run") would actually run. Reads the LIVE per-window selection off the bridge's Studio toolbar via UI Automation, accurate even when Studio's Configuration.xml is stale (it can say Emulator while the toolbar is really on a hardware panel). `source`="uia_live" is the definitive live read; the config-file path is the lazy fallback (off-Windows, no bridge, or non-interactive session). multi-instance (v1.0.7) — pass `project` to read a SPECIFIC armed bridge's Studio window when several are up at once.…

  • optix_add_model_variable

    Author an edit adding a read+write variable to Model — does NOT deploy. Returns {edits, file, variable, target_path, preview} where target_path is the "{Model}/<name>" you pass as a widget's visible_bind / checked_bind. Tier-1 supports Boolean (the demo's PowerOn). Forward `edits` to optix_deploy, usually alongside an optix_add_widget edit in the same deploy. Refuses with `studio_open` (409) while Studio is running. Use this when: - you are about to add a bound switch/label and need the backing Boolean it reads/writes Do NOT use this when: - the variable already exists (optix_find …

  • optix_add_widget

    Author an edit that adds widget(s) to a screen — does NOT deploy. Generates correct Optix YAML (fresh GUIDs, right indentation, the proven binding shape). Forward `edits` to optix_deploy (combine with other authored edits into one deploy). Replaces hand-composing widget YAML — the thing that made "add a label" slow and error-prone. widgets: list of dicts, one per widget. Supported kinds: - label: {kind:'label', name, text, left?, top?, width?, height?, text_color?, font_size?, visible_bind?} visible_bind="{Model}/PowerOn" binds Visible to a Boolean. - switch: {k…

  • optix_bridge_add_bound_widget

    Create a widget, position it, and bind one property — in ONE call. The composite for the create -> set Left/Top/Width -> bind dance that every bound control (Switch, SpinBox, TextBox, ...) otherwise takes 3-5 calls to build. Only the args you pass are applied. TRANSACTIONAL — a failure after creation rolls the created node back automatically ({ok: false, failed_step, rolled_back: true}), so a retry with the same name is always safe. Use this when: - adding any positioned and/or bound control (the common case) Do NOT use this when: - wiring EVENTS (optix_bridge_wire_event after creating)…

  • optix_bridge_add_label

    Add a Label with text (+ optional position) in ONE call via the live bridge. The common "put a label on the screen" case in a single round-trip: creates a Label named `name` on `screen` (Optix path, no leading slash), sets its Text, and — if given — LeftMargin/TopMargin. Equivalent to optix_bridge_create_widget + optix_bridge_set_property x1-3 in one call. Requires Studio open with this project AND the bridge running. Use this when: - the user wants a label on a screen with some text (the everyday case) - you'd otherwise chain create_widget + several set_property calls Do NOT use this w…

  • optix_bridge_add_navigation_panel_item

    Add a tab to a NavigationPanel in ONE call: create the item (auto- routed into Panels), set its Title, and point it at a screen. Title is REQUIRED — an empty-Title item renders a zero-width invisible tab. screen_path (e.g. "UI/Screens/ScreenD") wires what the tab shows; omit it to wire later via set_property "Panel". Restart the emulator to see the new tab (structural edit). Use this when: - adding a navigation tab (the create/Title/Panel trio in one call) Do NOT use this when: - reordering tabs (optix_bridge_reorder) - retitling an existing tab (optix_bridge_set_property "Title")

  • optix_bridge_add_translation

    Add or update a translation for a LocalizedText key via the bridge. Registers `key` -> `value` for `locale` in the project's translation table (Add if new, Set if it exists). A UI Text holding that key then renders the translated string. Requires Studio open + the bridge. Persist with optix_save. Use this when: - adding i18n strings the UI references by key - localizing a label/message Do NOT use this when: - you want a literal one-off string (use optix_bridge_set_property) - Studio is closed

  • optix_bridge_add_translations

    Add (or overwrite) SEVERAL translation rows in one call via the bridge. `rows` is a list of {key, value[, locale]}; a row without `locale` uses the call-level `locale`. Each row is added if its key is new and set if it exists (like optix_bridge_add_translation); the result lists per row whether it was `new`. The whole list is validated before anything is written — a bad list returns {ok: False, code: "invalid_translation_rows", errors: [{code, message, row_index, field}]} and changes nothing. dry_run=True validates (including against the live table) and reports what would happen without writi…

  • optix_bridge_arm

    Arm or stop the design-time bridge for a project WITHOUT a human at the keyboard — ONE tool, pick an `action`. action: - "arm" — Execute StartBridge on the project's bridge NetLogic. - "stop" — Execute StopBridge (frees its port for another instance). `project` is REQUIRED and cannot be inferred: every other bridge tool defaults it from the serving bridge, and the whole point here is that no bridge is serving yet. Studio executes NOTHING from the NetSolution until an explicit right-click -> Execute, and its CLI has no execute verb, so this drives the real GUI gesture through UI Automat…

  • optix_bridge_attach_expression

    Attach an ExpressionEvaluator converter to a property via the bridge. The ExpressionEvaluator is FT Optix's formula language — "a dumb Excel with fewer functions" — subsuming ConditionalConverter, LinearConverter, etc. `expression` uses `{0}`,`{1}`,... placeholders bound in order to `sources` (comma-separated paths). Functions: max/min/avg/abs/trunc/ceil/floor/round/sqrt/sign/like/isempty/`if`/ left_of/right_of, plus `pow(base, exp)` on Studio 1.8+ (on 1.7 the bridge refuses it with `function_requires_version`: pow needs 1.8). Colors are `0xAARRGGBB`. Example: conditional color expression="if…

  • optix_bridge_attach_formatter

    Attach a FORMATTED DYNAMIC LINK to a property via the bridge. A DynamicLink whose path is BUILT at runtime by a StringFormatter from NAMED sources — Optix calls it a "formatted dynamic link", and in Studio it is one control: type `{#token}` into a dynamic link's path and it grows a child link per token. format = "../NavPanel{#navIdx}@NodeId" sources = "navIdx=Model/GlobalVariables/AlarmVariables/AlarmTab" `{#name}` binds to a HasSource child called `Source<name>`, so the source NAME is load-bearing — unlike optix_bridge_attach_expression, whose sources are POSITIONAL (Source0..N) a…

  • optix_bridge_bind_property

    Bind a node's property to a model variable (DynamicLink) via the bridge. Creates a live dynamic link so `node_path`.`name` tracks the model variable at `source_path`. `mode` in {Read, Write, ReadWrite}. The semantic "bind the label's Text to the status variable" op (vs a static set). Requires Studio open + the bridge running. Persist with optix_save. ALIAS/TEMPLATE binding uses `raw_path` INSTEAD of source_path: a literal NodePath like "{Alias1}/MyInt" or "../../Alias1/MyInt" that resolves PER INSTANCE at runtime — deliberately NOT resolvable at bind time; that late binding is what makes a t…

  • optix_bridge_convert_to_type

    Convert a LIVE instance into a reusable ObjectType — Studio's right-click "Convert to Type" refactor, which has no public API. Creates `type_name` (subtyping the instance's own type) in `types_folder` (must exist — optix_bridge_create_folder first), RE-AUTHORS a copy of the subtree into it (fresh nodes, DynamicLinks re-created against resolved targets — live children are never re-parented, which corrupted the model before this fix), and with replace=true (default) swaps the original for an instance of the new type. READ `skipped` — constructs the copy can't reproduce (expression converters, …

  • optix_bridge_create_alias

    Create an alias under a node — the parameter slot of a reusable component/template. `kind` sets the TYPE CONSTRAINT ("BaseObject"/"Motor", or a project type path) — without it the alias is a bare NodeId pointer with no shape for validation. `target_path` is OPTIONAL and usually ABSENT on a template: each INSTANCE points the alias via optix_bridge_set_property(<instance>/<alias>, name="Value", value=<target path>). Bind the template's widgets THROUGH the alias with optix_bridge_bind_property(raw_path="{<name>}/<child>"). Requires Studio open + the bridge. Persist with optix_save. Use this whe…

  • optix_bridge_create_folder

    Create a structural FOLDER in the LIVE model via the design-time bridge. Folders (OpcUa FolderType) are organizational nodes — Model subtrees, UI/Templates, grouping — NOT UI controls, which is why they aren't in optix_bridge_create_widget's catalog. `parent` is an Optix path ("Model", "UI"). Duplicate sibling names refuse loud (name_exists). Persist with optix_save. NOTE: the bridge does NOT auto-promote a widget dropped at the Templates root into an ObjectType (Studio does) — create types explicitly with optix_bridge_create_type. Use this when: - organizing Model/UI subtrees, creating a…

Show 62 more tools
  • optix_bridge_create_netlogic

    Register a NetLogic (C#) node in the LIVE model via the bridge — the authoring step that used to require Studio's "New -> NetLogic" menu. A NetLogic node has NO generated proxy and NO code-reference property: the runtime binds it to the class whose name equals the node BrowseName, and the SDK-style NetSolution .csproj auto-globs every .cs. So the full recipe to add running C# is: (1) write the .cs (public class <name> : BaseNetLogic { ... }) into the project's NetSolution folder with the normal file tools, (2) call this with name == that class name, (3) restart the emulator so the rebuild ins…

  • optix_bridge_create_object

    Create a plain OBJECT container — or an INSTANCE of a custom type — in the LIVE model via the design-time bridge. With no `object_type`: a BaseObjectType container (group variables under it with optix_bridge_create_variable). With `object_type` = a path to a project ObjectType (e.g. "UI/Templates/PumpCard"): creates an INSTANCE of that type — how you reuse a template made with optix_bridge_create_type / optix_bridge_convert_to_type. Passing an instance path errors not_a_type. Use this when: - structuring model data (Motor1 with Speed/Power/Running under it) - instantiating a custom templ…

  • optix_bridge_create_type

    Create an OBJECT TYPE (reusable template) in the LIVE model. `base_type` is a builtin UI type name (RowLayout, Button — see optix_list_ui_types) so the type renders like its base, OR a path to another project ObjectType (subtyping), OR omitted for a bare model-side structured type. Author the template's CONTENT by targeting the new type's path with the normal tools (create_widget/ set_property/bind_property write into types exactly like into MainWindow, which IS a WindowType). Instantiate with optix_bridge_create_object (object_type=<this type's path>). PLAN-AHEAD workflow: create the type F…

  • optix_bridge_create_variable

    Create a model variable in the LIVE model via the design-time bridge. Adds a variable `name` of `datatype` (Boolean/Int32/Double/String/ NodePointer/...) under `parent` (an Optix path, default "Model"). Live-model write, export-safe by construction. Requires Studio open with this project AND the bridge running. Persist with optix_save. `datatype="NodePointer"` makes a typed NodePointer whose Kind is the type of the node it points at (never unset/BaseObjectType): pass `target` (the node to point at, e.g. "UI/Screens/ScreenA"), or an explicit `kind` (builtin UI type name / path to a type node)…

  • optix_bridge_create_widget

    Create a UI widget on a screen in the LIVE model via the bridge. Adds a builtin control (Label/Button/Rectangle/Panel/...) as a child of `screen` (an Optix path, NO leading slash, e.g. "UI/MainWindow"). PLACEHOLDER-COLLECTION AUTO-ROUTING: some parents declare a named child collection (NavigationPanel.Panels, DataGrid.Columns, XYChart.Pens, gauges' WarningZones) — children belong INSIDE it, like Studio's drag-and-drop. Target the PARENT's path; the bridge auto-routes when widget_type fits (created_path/routed_into report the real placement). Errors are loud: ambiguous_container (pass the exp…

  • optix_bridge_delete_node

    Delete a node from the live model via the bridge. Removes the node at `node_path` (and its outbound references). Live-model op; requires Studio open + the bridge. Persist with optix_save. Check impact first if unsure (references endpoint, when available). Use this when: - removing a widget/variable you created - cleaning up scratch nodes Do NOT use this when: - you're unsure what references the node (you may break bindings) - Studio is closed

  • optix_bridge_edit

    Apply a BATCH of live-model authoring ops, validated as a whole first. Each op is a dict with an `op` field naming the verb plus that verb's fields, e.g. [{"op": "create_widget", "screen": "UI/MainWindow", "name": "Gauge1", "widget_type": "Rectangle"}, {"op": "set_property", "path": "UI/MainWindow/Gauge1", "name": "Width", "value": "120"}]. Valid ops: set_property, bind, create_widget, create_variable, create_folder, create_object, create_type, create_alias, delete, move, rename, reorder, wire_event, attach_expression, attach_formatter, attach_string_formatter, retype, add_translation, add_tr…

  • optix_bridge_ensure_web_engine

    Ensure a Web presentation engine exists so the runtime serves a canvas. Without a WebUIPresentationEngine under UI, a deployed runtime renders no web canvas (CDP verify has nothing to screenshot). Idempotent: returns {existed:true} if one is already present, else creates + configures one (Port, Protocol=HTTP, StartWindow → the first window). Requires Studio open with this project AND the bridge running. Run once during project setup, then author->save->deploy->verify has something to serve. Use this when: - setting up a new/scratch project for the deploy-verify loop - a deploy serves not…

  • optix_bridge_import_tags

    Import PLC tags into a driver station with its design-time Tag Importer. `station` is the path of an RA EtherNet/IP or TwinCAT station (e.g. "CommDrivers/RAEtherNet_IPDriver1/Station1"). `mode` is "offline" (reads `file`: an L5X for RA, a TPY for TwinCAT; absolute or project-relative; required) or "online" (reads the controller; `file` ignored; not covered by a live test - the bench has no controller). `tags` are symbol names; each one is imported with its parents and children on '.' boundaries (Motor1 never brings in Motor10). Waits for the importer at most `timeout_s` (default 120) without …

  • optix_bridge_invoke_method

    Execute an exported UAMethod on a live-model object via the bridge. Runs the method on the bridge thread under a root Optix session, which is what makes it safe: without a session, ExecuteMethod killed FTOptixStudio.exe on any method (GitHub issue #4). Exceptions the method throws are caught and logged by Optix, and Studio stays up. Needs a bridge build that advertises `invoke_session` in /bridge/health; an older build is refused with `invoke_unsupported_bridge` before the call (rebuild + re-arm, or use optix_execute_method). `args`, if given, is a comma-separated string of positional input …

  • optix_bridge_log_tail

    Tail the design-time bridge's transport diagnostics — the forensic trail for bridge drops/timeouts (why did :8768 go unreachable?). Each event is {ts, path, method, latency_ms, status, ok, error}. The log captures every transport FAILURE (timeout / connection aborted — e.g. a rebuild unloading the bridge NetLogic), every non-2xx, every real authoring op, and every health up<->down TRANSITION; the steady-state 2s health poll is deduped out so the log stays signal-dense. `contains` filters case-insensitively. Returns {file, mtime, events, returned, last_ok, ...} or {error:"no_bridge_log"} if no…

  • optix_bridge_move_node

    MOVE (reparent) a live instance to a new parent — e.g. an existing column of widgets into a freshly-created ScrollView. Implemented as re-authoring (copy under the new parent, delete the original) — a raw node-model reparent corrupts the live model. Consequence: the node gets a NEW NodeId, so INBOUND references from elsewhere to the moved subtree are NOT rewritten (outbound bindings ARE re-created). `skipped` lists anything not copied. optix_save first; render-verify after (structural change — restart emulator). Use this when: - restructuring a screen (wrapping content in a new container) …

  • optix_bridge_remove_translation

    NOT SUPPORTED: the Optix SDK cannot remove a translation row. Always changes nothing. A malformed key returns {ok: False, code: "invalid_translation_key"}; a key with no row returns {ok: False, code: "translation_not_found", key, message, nudge}; an existing key (dry_run included) returns {ok: False, code: "not_supported", key, message, nudge}. optix_bridge_edit op `remove_translation` is refused the same way (report.errors, with op_index). Use this when: - never; to change a row, edit the key in Studio's Translations editor or overwrite its text with optix_bridge_add_translation

  • optix_bridge_reorder

    Change a node's z-order among its siblings via the bridge. Render order = child order: the LAST child renders in FRONT, the first BEHIND. Pass `position="front"`, `position="back"`, or an explicit `index`. Enables a Panel background: create a Rectangle, send it to back so it sits behind the panel's other children. Live-model op; requires Studio open + the bridge. Persist with optix_save. Reload the runtime page to see the visual change. Use this when: - a background rectangle needs to go behind existing widgets - bringing a control in front of / behind overlapping widgets Do NOT use thi…

  • optix_bridge_retype

    Change an existing VARIABLE's DataType in place via the bridge. `datatype` is one of Boolean, Int16, Int32, Int64, UInt16, UInt32, UInt64, Float, Double, String, DateTime, LocalizedText (case-insensitive). The node, its children and every inbound link are kept; the value is converted element-wise. Retyping to LocalizedText carries a String / number / Boolean / DateTime / LocalizedText value over as text. A value with no text form (NodeId, ByteString, ...) or an array that would lose elements collapsing to a scalar is REFUSED, nothing changed, with {ok: False, code: "value_not_convertible", er…

  • optix_bridge_set_modelling_rule

    Set the ModellingRule of a TYPE MEMBER via the bridge. `rule` is Mandatory (every instance of the type carries the member), Optional (instances may carry it) or None (a plain child, not instantiated from the type). Case-insensitive. `node_path` must be a member under an ObjectType/VariableType; elsewhere the bridge returns `not_a_type_member`. An invalid rule returns {ok: False, code: "invalid_modelling_rule", errors: [{code, message, field, allowed}]} and changes nothing. dry_run=True resolves the node and reports `previous` / `would_set` without changing it. Persist with optix_save. optix_b…

  • optix_bridge_set_property

    Set a property on a LIVE-model node via the design-time bridge. `node_path` is an Optix path (NO leading slash), `name` the property (Text, Width, FontSize, ...), `value` a string coerced to the property's type. Materializes a freshly-created instance's inherited property (e.g. a new Label's Text) so it persists AND renders — the fix for the GetVariable-null trap. An optional child the node's TYPE declares but the instance lacks (e.g. a TrendPen's Color) is created on demand and set; the result carries created_optional_child with its name. A name the type does not declare still fails (propert…

  • optix_bridge_set_text_key

    Set a text property to a TRANSLATION KEY (LocalizedText with a TextId). Writes a LocalizedText whose TextId is `key` into the LocalizedText property `name` (e.g. Label.Text) of `node_path`, so the runtime resolves the string through the translation table per session locale. optix_bridge_set_property writes LITERAL text instead. The key need not exist yet — register it with optix_bridge_add_translation (the result's `translated` says whether a row exists now; a key with no row renders blank). Persist with optix_save. BrowseName / DisplayName / Description / NodeId / NodeClass are node attribu…

  • optix_bridge_status

    Status of the design-time read-bridge(s) (NetLogic HTTP listener(s) in Studio). multi-instance (v1.0.7) — up to several Studio instances can each have an armed bridge SIMULTANEOUSLY, one per project, so this now returns `bridges`: a list, one entry per port currently answering {available, project, bridge_version, port, reason, source}, plus `count`. With exactly ONE bridge armed it is echoed at the top level under the pre-1.0.7 single-bridge field names (`available`/ `project`/`bridge_version`/`port`/`reason`/`source`). With several armed no bridge is singled out (top-level `project`/`port` …

  • optix_bridge_validate_expression

    Syntax-check an ExpressionEvaluator formula WITHOUT attaching it. Optix validates a formula only at RUNTIME, where a bad one silently no-ops (the classic converter trap). This catches common author-time mistakes up front: unbalanced ()/{}, a placeholder {N} beyond the number of sources, an unknown function name, an unterminated string, and `pow` on a Studio older than 1.8 (`function_requires_version`, with a structured `requires_version` field). The SAME check gates optix_bridge_attach_expression — this tool is for checking BEFORE you commit. Use this when: - drafting a non-trivial formula…

  • optix_bridge_wire_event

    Wire a UI event on a node — to a NATIVE command or a NetLogic method. Builds an EventHandler so `event_type` (e.g. MouseClickEvent) on `node_path` fires an action. Prefer a NATIVE command (no custom NetLogic): command="SetVariable" with variable=<path> + value=<v>, or command="ToggleVariable" with variable=<path> — wired to FT Optix's builtin VariableCommands; or a UI command — command="OpenDialog" / "CloseDialog" / "OpenKeyboard" — whose arguments ride in `args` as "Name=Value;Name=Value" (OpenDialog: Dialog=<Dialog type path>; AliasNode=<node or empty>;ParentItem= — an empty ParentItem is l…

  • optix_build_check

    Compile the project's NetSolution C# and report errors — a safe pre-flight that never touches Studio's build or runs the emulator. WHY: a NetLogic that does not compile fails the build silently and takes the in-Studio bridge AND the emulator down with it, with no clear signal. This copies the NetSolution to a throwaway temp dir (bin/obj excluded) and builds the COPY there, so it never touches the project's own bin/obj — a concurrent Studio build cannot race it. Returns {ok, returncode, error_count, warning_count, errors:[{file,line,col,code,message}], warnings, csproj, dotnet}, plus `hint` wh…

  • optix_cdp_click

    Click (x, y) on the Optix runtime canvas via CDP — the RELIABLE path. Optix Web renders to a single <canvas> (no DOM targets) and synthetic DOM clicks no-op on buttons/switches. This injects a trusted CDP Input.dispatchMouseEvent that actually reaches Optix's hit-tester. Pass navigate_url to point Chrome at the runtime first; omit it to click whatever Chrome shows. Pair with optix_cdp_screenshot to read coordinates first. Use this when: - you need to actually trigger a button/switch on the running HMI (state changes), or navigate a NavigationPanel tab - a deploy landed but you want t…

  • optix_cdp_diff

    Compare two optix_cdp_sweep capture directories screen-by-screen — a visual regression check, no CDP session needed (pure file comparison). Matches screens by route key from each dir's manifest.json; a screen in only one dir is reported under `added`/`removed` (not an error). With Pillow installed (a hard dependency of ftx-mcp), grayscale mean-pixel-difference vs `threshold` (percent, default 2.0) decides changed/same, with a size mismatch short-circuiting to 'size_mismatch'. Without Pillow, degrades to a text-only compare using each manifest's OCR text (degraded='no_pillow'); with neither Pi…

  • optix_cdp_fill

    Update a field on the running HMI in ONE call: click (x, y), type `text`, commit with `submit` (default Enter — values don't stick without it). THE default way to set a TextBox/SpinBox value — replaces the click -> type -> key trio. select_all (default true) makes the typed text REPLACE the current value (a bare click only places a caret, so typing would append). submit=None types without committing; submit="Tab" for tab-commit fields. Fails loud with no_focused_input when the click didn't land on an editable field. Use this when: - setting a TextBox / SpinBox / editable field to a value (…

  • optix_cdp_find_text

    Locate `text` on the runtime canvas via tesseract word boxes — to find a labeled control to click, or to build a navigation route. Full-frame capture (you don't know coordinates yet). Case-insensitive; a multi-word `text` query only matches ADJACENT words on the same tesseract line. Words scoring below 40/100 are dropped before matching. `confidence` is a fraction in [0, 1] — same scale as optix_cdp_ocr/read_text. No match is NOT an error (found=false, matches=[]). Same degradation contract as optix_cdp_ocr for missing tesseract. `matches[].center_px` feeds optix_cdp_click directly — e.g. fi…

  • optix_cdp_key

    Press one named key on the running Optix HMI (CDP dispatchKeyEvent, keyDown+keyUp). THE commit step for field edits: after optix_cdp_click + optix_cdp_type, optix_cdp_key("Enter") is what makes the value stick — without it the edit is discarded on blur. Keys: Enter, Escape, Tab, Backspace, Delete, ArrowUp/Down/Left/Right. KNOWN LIMIT: arrow keys do NOT step an Optix SpinBox — click its < / > stepper buttons instead. Unknown keys return invalid_key + the valid list. Pressing with no pending edit is a safe no-op. Use this when: - committing a typed TextBox/SpinBox value (Enter) — then screen…

  • optix_cdp_navigate

    Zero-screenshot navigation to a banked screen: replays a sequence of clicks from a routes JSON file instead of screenshot -> locate -> click, click again. Routes file format (version 1): `{"version": 1, "routes": {"<name>": {"steps": [{"click": [x, y], "settle_seconds": 0.5, "expect_text": "Setup Values"}]}}}`. `click` uses the SAME coordinate convention as optix_cdp_screenshot's `region` — portable across window sizes. Convention: bank routes at `dev/ftx_ui_map.json` (see the optix-blind-authoring skill). `routes_path` accepts the `path` returned by optix_routes(action="save") directly. Rou…

  • optix_cdp_ocr

    OCR the runtime canvas via tesseract — an OPT-IN, text-only read-back. Prefer optix_cdp_screenshot + a vision model for verify (reads color, layout, AND text). Use THIS only when vision isn't available (headless/ cron run) or as a fallback when a capture renders blank. If tesseract isn't installed, returns state='failed', error='tesseract_not_installed' (optional infrastructure — never crashes the loop). Use this when: - a headless caller has no vision model but needs to read back rendered text - a screenshot came back blank and you want any text signal at all Do NOT use this when: - …

  • optix_cdp_read_text

    OCR a region of the runtime canvas via tesseract — THE cheap check for "does the screen/widget say X" — zero vision tokens. Same region coordinate convention as optix_cdp_screenshot (values all <= 1.0 are normalized viewport fractions; > 1 means absolute pixels). Omit `region` to OCR the full frame. Same degradation contract as optix_cdp_ocr: missing tesseract returns error='tesseract_not_installed' rather than raising; a malformed region returns error='bad_region'. Use this when: - checking that a specific label/widget shows expected text, cheaply (no vision model call) — e.g. confirm…

  • optix_cdp_restart

    Recover the chrome-cdp instance that screenshot/click drive. Usually you do NOT need this — screenshot/click self-heal on their own (open a page if Chrome is up but tab-less, or restart the ftx-mcp-chrome-cdp task if Chrome is down). Call this to force that recovery explicitly, or to check/repair after a reboot. Set allow_restart=False to only open a page (never relaunch the process). Use this when: - a verify tool reported cdp_unavailable and you want to repair it - after a reboot, to bring canvas-verify back without a full restart Do NOT use this when: - things are working — the too…

  • optix_cdp_screenshot

    Screenshot the running Optix HMI (emulator or deployed runtime) via CDP — THE way to visually verify a change. IMPORTANT — if your edit is NOT in the screenshot, do NOT conclude it failed: a running emulator renders its own loaded snapshot and does not pick up Studio edits. optix_emulator(action="restart"), then screenshot again before diagnosing. fresh=true forces a page reload before capture (stale-frame suspected). *** Runtime-verify tool: use THIS to confirm a deploy rendered — do NOT open the runtime in a general web browser (Cowork's visualize, a Mac/host browser). *** Drives the local…

  • optix_cdp_sweep

    Capture a full-frame screenshot (+ OCR text, if tesseract is installed) of every route in a banked routes file, in ONE CDP session — builds the visual baseline optix_cdp_diff compares against. Loads routes_path exactly like optix_cdp_navigate (same format; `routes_path` accepts the `path` from optix_routes(action="save") directly). Routes files live in the service — do NOT ask the user for host folder access. Sweeps all routes in file order, or just the names in `routes` — an unknown name fails error='route_not_found'. Steps replay like optix_cdp_navigate's clicks, but expect_text checks are…

  • optix_cdp_type

    Type a string into the focused field on the running Optix HMI (CDP Input.insertText). The keyboard half of the click-type-Enter pattern: optix_cdp_click the field FIRST, then this inserts the string at the caret/selection. Does NOT click and does NOT commit: **values don't stick until Enter** — follow with optix_cdp_key("Enter"). For the common set-a-field-value case, prefer optix_cdp_fill (click+type+commit in one call); this primitive is for mid-entry screenshots and non-standard flows. Fails loud with no_focused_input when nothing editable has focus. Use this when: - filling a TextBox /…

  • optix_deploy

    Apply edits and deploy via FTOptixStudio export -> tree swap -> runtime bounce (v0.2.x). *** REQUIRES FACTORYTALK OPTIX STUDIO CLOSED. *** Refuses with 409 studio_open while Studio is running anywhere on this box (in-memory model stomps file-level edits — this corrupted a live demo once; no override exists) — use optix_deploy_updatesvc instead if Studio is open with the bridge armed. `editor_project_open` (409) means VS/VS Code has THIS project open. Mechanism: applies `edits` to the project tree, git-commits with `commit_message`, runs `FTOptixStudio.exe export`, atomically swaps the bundle…

  • optix_deploy_preflight

    Run every deploy precondition without launching Studio. Returns {ready, blockers, warnings, checks}; ready=True iff blockers is empty. Checks: project resolves + has .optix manifest, studio_exe present, runtime_dir configured, interactive_session=True (Windows DPAPI constraint), deploy lock free, git status, runtime port probe (informational), and the corruption guard (blocker `studio_open` when Studio is running; `editor_project_open` when VS/VS Code has this project open — remediation is closing the app, no override exists). Use this when: - about to run optix_deploy on a fresh box and w…

  • optix_deploy_updatesvc

    Deploy a saved project via the FT Optix Application Update Service. THE SHIP STEP — deliberate, not the everyday verify. For iteration, use optix_emulator(action="run") + optix_cdp_screenshot instead (much faster, no transfer); deploy AFTER the emulator preview confirms the change. WORKS WITH STUDIO OPEN (contrast optix_deploy, which REFUSES while Studio is open): the `deploy` verb spawns its OWN short-lived Studio to build+transfer, so your interactive Studio + bridge stay up the whole time. Mechanism: runs the Studio `deploy` verb, which opens the SAVED project from disk, builds it, and tr…

  • optix_describe_node

    Introspect one node in the LIVE model via the design-time bridge. `path` is an Optix model path (NO leading slash), e.g. "UI/MainWindow", "Model/Motor1". Returns the node's real type, children, and property values directly from Studio's in-memory model, with no YAML guessing. REQUIRES Studio open with this project AND the bridge running, else raises `bridge_unavailable` (503) — no file-path equivalent exists. Use this when: - you need a node's exact type or property schema before editing - you want to discover what a screen/panel contains (its children) Do NOT use this when: - Studio …

  • optix_describe_type

    Property schema of a builtin UI type from the LIVE model — the "shape" of a control (which properties it has, their datatypes), so an edit can be composed against the real schema instead of guessed YAML. `type_name` is a catalog name from optix_list_ui_types (e.g. "Label", "Button"). Bridge-only (else `bridge_unavailable`); `node_not_found` for an unknown type. Use this when: - before adding/setting a property, to confirm it exists and its datatype Do NOT use this when: - you want the properties of a specific existing NODE (optix_describe_node) - Studio is closed (the bridge is down)

  • optix_emulator

    Emulator lifecycle — ONE tool, pick an `action`. Consolidates optix_run_emulator / optix_restart_emulator / optix_stop_emulator / optix_emulator_status / optix_runtime_log_tail (each formerly its own tool); replaced cleanly, no deprecated aliases. action: - "run" — F5: launch the project in Studio's built-in emulator. THE default verify step — much cheaper and faster than a deploy. F5 stages the in-Studio model (saves as part of staging) and spins up a LOCAL FTOptixRuntime. `run` is safe to repeat: if this project's emulator is already running or starting, NO F5 is sent …

  • optix_execute_method

    Right-click -> Execute a design-time [ExportMethod] on a NetLogic node, WITHOUT a human at the keyboard. The generalisation of optix_bridge_arm (which is this, hard-wired to StudioMCPBridge/StartBridge). Use it to fire a project's own design-time generators and builders — a card builder's BuildCards, a converter script's Apply — from the agent instead of asking someone to right-click. `node` is the NetLogic's name (e.g. "FormattedLinkScript"), `method` the [ExportMethod] name (e.g. "Apply"). The node must be declared in the project's NetLogic YAML; the .cs file alone is not enough, because w…

  • optix_find

    Search a project's text files for a literal string — server-side. THE discovery primitive: locate which file and line hold a screen, widget, node name, or property before reading or editing. Case- insensitive by default. Literal only — no regex, single-line queries. While Studio is open and its bridge is serving this project, the search runs against the LIVE model through the bridge (node browse-name / path / property name+value) instead of the files, so it does NOT refuse. Only when no bridge serves the project does it scan the files on disk, and that scan refuses with `studio_open` (409) wh…

  • optix_get_project_map

    Component map of the project (names + nesting) in ONE call — the cheap way to learn structure instead of walking it with repeated optix_describe_node. Depth is AUTOMATIC: a FOLDER (or no path) gives an "overview" (one line per component, "(+N inside)"/"(N vars)"); a COMPONENT path (e.g. "UI/MainWindow") gives the full "detail" subtree at depth 6 (pass depth= to override). Pointers/bindings are DEREFERENCED inline ("Panel (NodePointer -> UI/Screens/ScreenA)") — a detail map doubles as a wiring audit. match="Pump*" turns the call into a LIVE-MODEL SEARCH (name or type). MATCHING IS EXACT unles…

  • optix_get_skill

    Full content of one bundled playbook by name (from optix_list_skills). Use this when: - the task matches a playbook from the catalog Do NOT use this when: - the task is simple enough that the tool docstrings already cover it

  • optix_interact

    Act on the running Optix HMI — ONE tool, pick an `action`. Consolidates optix_cdp_click / _fill / _type / _key / _navigate; the per-action tools remain as deprecated aliases (FTXMCP_LEGACY_TOOLS). `target="web"` (default) drives the WebPresentationEngine through Chrome/CDP. `target="native"` drives the emulator's NATIVE presentation engine window (FTOptixRuntime.exe's own desktop window) by posting input straight to it: no Chrome, no CDP, the window may be behind others and the user's focus is never taken. Native supports click / fill / type / key (not navigate: click the HMI's nav buttons). …

  • optix_list_projects

    List Optix projects under OPTIX_PROJECTS_ROOT. You RARELY need this: every project-scoped tool defaults to the project open in Studio when `project` is omitted. Use this when: - the user asks "what projects are on the box?" - targeting a DIFFERENT project than the one open in Studio - no bridge is running and a tool returned no_project Do NOT use this when: - you're working with the project open in Studio — just omit `project` on the other tools; do not enumerate first

  • optix_list_screens

    List the Screen / Panel / Dialog nodes in a project's UI — the starting point for any UI edit. Returns {screens: [...], count, source}. `source` is "bridge" (live model, Studio + bridge running) or "file" (on-disk YAML). When Studio is open with this project and the bridge is up, reads live (no refusal); otherwise falls back to file mode, which still refuses with `studio_open` (409) if Studio is open with no bridge serving this project — no override either way. Use this when: - the user says "add X to the main screen" — find which screen that is - you need a screen's exact node name for …

  • optix_list_skills

    Catalog of the bundled authoring playbooks — one line each (proven recipes for navigation, bound controls, styles, expressions, alarms). Scan for a matching pattern, then optix_get_skill(name) for just that one. Use this when: - starting a task that smells like a common HMI pattern Do NOT use this when: - you already know the skill name (optix_get_skill directly)

  • optix_list_ui_types

    List the builtin UI type catalog from the LIVE model — "what controls exist?" (Label, Button, Rectangle, Panel, DataGrid, Trend, …), read from Studio's type system, not guessed. Bridge-only (else `bridge_unavailable`). Pair with optix_describe_type for a type's property schema. Use this when: - you need to know which control types are available before adding one Do NOT use this when: - you already know the type name (go straight to optix_describe_type) - Studio is closed (the bridge is down)

  • optix_observe

    Read-side capture of the running Optix HMI — ONE tool, pick a `mode`. Consolidates the optix_cdp_screenshot / _ocr / _read_text / _find_text / _diff family; the per-mode tools remain as deprecated aliases (FTXMCP_LEGACY_TOOLS). `target="web"` (default) reads the WebPresentationEngine through Chrome/CDP. `target="native"` reads the emulator's NATIVE presentation engine window (FTOptixRuntime.exe's own desktop window) straight from the window: no Chrome, no CDP, no web engine needed; the window may be covered but must not be minimized. Every mode except `diff` honors it (screenshot / ocr / read…

  • optix_project

    Studio project lifecycle via its CLI — ONE tool, pick an `action`. action: - "open" — launch Studio on an existing project and WAIT until it is really loaded. The CLI returns immediately while Studio is still loading, so readiness is the window's project identity appearing, not process existence and not a sleep. Returns state=already_open (and launches nothing) when a Studio already has it loaded. "Loaded" means bridge health identity, else the main-window title / project tree, else the Studio log line - never the Home screen's Recent list. When Studio refuses a …

  • optix_read_file

    Read a UTF-8 file under an Optix project, optionally a line range. Path-traversal is rejected. start_line/end_line are 1-based inclusive (end clamps to EOF). The result's `sha256` is the version fingerprint to cite when composing anchored edits. Refuses with `studio_open` (409) while Studio is running anywhere on this box: disk state is stale while Studio holds the project in memory, and an edit planned from it would be wrong. Close Studio and retry; no override parameter. (Operators may set `OPTIX_STUDIO_GUARD_MODE=attributed` out-of-band to allow reads when the bridge proves Studio is serv…

  • optix_read_netlogic

    Read a NetLogic C# source file by class name from ProjectFiles/NetSolution. ``cls`` is the NetLogic class name / file base name WITHOUT the .cs extension (e.g. ``"AlarmManager"`` reads ``AlarmManager.cs``). Path-traversal and malformed class names are rejected before the filesystem is touched. start_line/end_line are 1-based inclusive (end clamps to EOF). The result's ``sha256`` is the whole-file version fingerprint; ``size`` and ``total_lines`` also describe the whole file even when a range is returned. Unlike ``optix_read_file`` this tool DOES work while Studio is open: the NetSolution liv…

  • optix_routes

    Routes-file CRUD — ONE tool, pick an `action`. Consolidates optix_routes_save / _get / _list (each formerly its own tool); replaced cleanly, no deprecated aliases. Routes files live in the SERVICE (a project's `dev/<name>.json`) — do NOT ask the user for host folder access; these three actions are the entire CRUD surface for them. `project` is required for every action (no bridge-default fallback — routes files are project-scoped by path, not by what Studio has open). action: - "save" — CREATE/REPLACE a routes file, the bank half of the routes-banking loop for optix_interact(action="na…

  • optix_runtime_start

    Launch FTOptixRuntime against the swapped runtime tree for `project`. Spawns the FTOptixRuntime.exe that Studio's export bundled into OPTIX_RUNTIME_DIR/<project>/FTOptixApplication/, detached from the service process. Polls the runtime port for tcp_reachable until `timeout` seconds elapse (default 30). Same Windows interactive- session DPAPI constraint as Studio. `port` defaults to cfg.runtime_test_port (typically 8081). Runtime tree must already exist (deploy first). Use this when: - bringing up a freshly-deployed project's runtime for CDP/user - after optix_deploy with run_after_deploy…

  • optix_runtime_status

    Probe a runtime instance's reachability. slot: 'test' (default port 8081) | 'mgmt' (default port 8086, a second operator-dashboard runtime, if you run one). Use this when: - confirming a deploy actually landed (after optix_deploy with run_after_deploy=False, the caller is responsible for cycling the runtime; this probe confirms) - cold-start drift check after a Windows reboot Do NOT use this when: - you want to know whether Studio is installed (optix_status( action="health")) - you want deploy outcome details (optix_status(action="services"))

  • optix_runtime_stop

    Stop FTOptixRuntime processes attached to `project`'s runtime tree. WMI-matches FTOptixRuntime.exe processes whose CommandLine references the project's runtime tree, then Stop-Process -Force. Idempotent — stopping when nothing is running is a successful no-op. Other projects' runtimes are not touched. Use this when: - bouncing a runtime to pick up a code/asset change (call before re-deploying or before optix_runtime_start) - cleaning up a stale runtime that's holding the port Do NOT use this when: - you want to stop all FTOptixRuntime processes regardless of project (this only…

  • optix_save

    Persist the open project to disk (sends Ctrl+S to Studio). Studio has no programmatic save API, so this focuses the project's window and sends ^s, then verifies by watching the node-YAML mtime advance. If the mtime has not advanced it re-sends Ctrl+S every 5 s until `timeout` (default 30 s): the second keystroke first clicks the project-tree row in that Studio's window (Studio 1.8 has no File menu), later ones are plain Ctrl+S. Studio drops Ctrl+S while it rebuilds the user NetSolution (right after a design-time NetLogic create), hence the re-sends; polling continues 15 s after the last keyst…

  • optix_schema

    Studio type-schema operations — ONE tool, pick an `action`. Consolidates the optix_schema_dump / _list / _diff family (each formerly its own tool); replaced cleanly, no deprecated aliases. action: - "dump" — fetch + cache the FULL type-schema dump for the running Studio version. Enumerates the whole builtin type catalog into an offline cache keyed by Studio version, then returns a compact SUMMARY (never the full dump — it's large). Powers offline reads and cross-version diffing (action="diff"). Requires Studio open + bridge + the bridge's /bridge/schema/dump endpoint; mi…

  • optix_set_property

    Author a find/replace edit changing one inline property — no deploy. Changes an inline shorthand property (Text, Left, Top, Width, Height, TextColor, ...) on a named widget. Returns {edits, widget, property, old_value, new_value}. Forward `edits` to optix_deploy. `value` is the raw YAML scalar — quote text yourself, e.g. value='"Hello Optix"'. Refuses with `studio_open` (409) while Studio is running. Use this when: - the user wants to retitle/move/resize an existing widget (e.g. set Text on a label, bump Left/Top) Do NOT use this when: - the property is a child-node (a binding, an …

  • optix_status

    Deploy-stack status family — ONE tool, pick an `action`. Consolidates optix_health / optix_doctor / optix_services_status / optix_studio_version (each formerly its own tool); replaced cleanly, no deprecated aliases. These four are HETEROGENEOUS — pick the one that matches what you actually need, they are not interchangeable: action: - "health" — FAST preflight config snapshot (export-based, v0.2.x): projects_root, studio_exe, runtime_dir, interactive_session, bind config. Use this when the user asks "is everything wired up?", "is studio installed?", or before a deploy attempt t…

  • optix_studio_log

    Tail Studio's own log, FTOptixStudio.0.log — the only place Studio reports that it REJECTED an optix_execute_method call (which optix_execute_method now surfaces itself as state="rejected"). `lines` is the last N lines (1..5000, default 100); `contains` an optional case-insensitive filter applied before the tail. `lines` in the result is one <untrusted>-delimited string. Errors are structured {ok: false, code, errors}: invalid_lines, invalid_contains, no_studio_log (file missing), studio_log_unreadable. Use this when optix_execute_method says rejected, or a design-time action did nothing and…

Signals

Stars
17
Forks
6
Open issues
0
Weekly downloads
70
Last commit
Oct 15, 2026 (15 days ago)
Last release
Oct 15, 2026 (15 days ago)
Last package publish
Oct 15, 2026 (15 days ago)

From GitHub (fetched Oct 24, 2026) and the package registry.

Details

Registry name
io.github.asqi-carter/ftx-mcp
Version
1.0.9
Auth
No auth
Packages
pypi ftx-mcp
License
License unknown
First seen
Oct 24, 2026
Last checked
Oct 25, 2026

Done for you

Rather not set it up yourself?

Chalk Labs scopes, builds and runs agents for your team: the task audit, the eval harness, the integrations and the weekly ops report. Fixed scope, priced before we start.

See how we build AI agents →Read the case studies

Chalk Labs is a two-founder AI and growth studio. We build AI agents, CRMs and MVPs for Web3 and AI companies, and have shipped 50+ product and token launches.

launches shipped
50+
launches shipped
media placements
500+
media placements
founders on every account
2
founders on every account

Press we've placed: Forbes · CoinDesk · Decrypt · Cointelegraph · The Block

Rahil Jain, Co-founder, Chalk Labs. Ex-Goldman Sachs engineer. You talk to the person who builds it.

Get FTX MCP — FactoryTalk Optix MCP Server running in your business

Tell us what you want to automate. A founder replies within one working day with a plan, not a pitch deck.

Goes to the Chalk Labs founders, not the newsletter. Privacy

Need help deploying FTX MCP — FactoryTalk Optix MCP Server?

CallGet help
Cite this page

FTX MCP — FactoryTalk Optix MCP Server. Agent Mart. https://agentmart.dev/connectors/asqi-carter-ftx-mcp (last updated 2026-10-25)