Metadata-Version: 2.4
Name: ftx-mcp
Version: 1.0.4
Summary: MCP server for authoring, previewing, and verifying FactoryTalk Optix Studio changes via the emulator, single Windows box.
Author: ASQI
License-Expression: MIT
Project-URL: Homepage, https://github.com/asqi-carter/ftx-mcp
Project-URL: Issues, https://github.com/asqi-carter/ftx-mcp/issues
Project-URL: Specification, https://github.com/asqi-carter/ftx-mcp/blob/main/docs/architecture.md
Keywords: factorytalk,optix,mcp,rockwell,ot
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Installation/Setup
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: fastapi>=0.110
Requires-Dist: pydantic>=2.5
Requires-Dist: uvicorn>=0.27
Requires-Dist: mcp>=1.2
Requires-Dist: anyio>=4
Requires-Dist: psutil>=5.9
Requires-Dist: websocket-client>=1.7
Requires-Dist: pyyaml>=6
Requires-Dist: uiautomation>=2.0; sys_platform == "win32"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21; extra == "dev"
Requires-Dist: ruff>=0.5; extra == "dev"
Requires-Dist: mypy>=1.10; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Provides-Extra: visual
Requires-Dist: Pillow>=10; extra == "visual"
Dynamic: license-file

# ftx-mcp

<!-- mcp-name: io.github.asqi-carter/ftx-mcp -->

**Talk to your FactoryTalk Optix project.** ftx-mcp connects AI tools
(Desktop, Cowork, Code — or any MCP client) to FactoryTalk Optix Studio on
your Windows machine, so you can build and change HMI screens by describing
what you want:

> *"Add a header that says 'Hello Optix' to Screen 1 and show me."*
>
> *"Bind that label's visibility to Model/PumpRunning."*
>
> *"Looks right. Launch the emulator and validate it."*

Your LLM authors the change directly into your open Studio project, runs the
emulator, and looks at the rendered runtime to confirm it worked. It is a
development and testing companion: shipping to hardware stays in Studio's own
Deploy dialog, in your hands. Everything besides the LLM calls runs locally
on your machine. No cloud service, no API key; your LLM of choice provides
the intelligence.

[**Blog Post**](https://asqi.org/resources/ftx-mcp-v1/)

## Install (10 minutes)

Requirements: Windows 11, FactoryTalk Optix Studio 1.7.x, and an MCP client
like Claude Cowork. Also: **Google Chrome** (the CDP verify loop; skip with
`setup.ps1 -NoCdp`) and — for the Claude Desktop **Microsoft Store build**
connector path — **Node.js** (`winget install OpenJS.NodeJS.LTS`; the config
uses `npx mcp-remote`). Setup auto-installs **Tesseract OCR** via winget for
the zero-vision-token text tools (skip with `-NoOcr`; everything else works
without it) and **Pillow** into the venv for pixel diffing.

Run `setup.ps1` from a **regular PowerShell window** — not a shell hosted
inside a packaged app like the Store build of Claude Desktop, whose
`%LOCALAPPDATA%` writes are virtualized (setup now detects this and refuses).
If you downloaded a ZIP instead of cloning, run
`Get-ChildItem -Recurse | Unblock-File` first.

If `setup.ps1` (or any `bootstrap\*.ps1`) fails to run at all with a script-
execution / "running scripts is disabled" error, your machine's execution
policy is blocking unsigned scripts. Unblock them for the current window only —
no admin, no persistent policy change — then re-run:

```powershell
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass
```

```powershell
git clone https://github.com/asqi-carter/ftx-mcp.git
cd ftx-mcp
.\bootstrap\setup.ps1                                  # install (does not start anything)
.\bootstrap\services.ps1 start                         # start the service + cdp chrome
.\bootstrap\services.ps1 status                        # verify health
http://127.0.0.1:8765/ui                               # health dashboard
```

**Auth:** the default install is loopback-only with auth OFF — setup never
prompts, and no token is needed on your own box. Binding to the LAN is the
one case that requires auth: install with `.\bootstrap\setup.ps1 -EnableAuth`
(see [`docs/security.md`](docs/security.md)). If a UI/API unexpectedly asks
for a bearer token, a previous install enabled auth — re-run setup with
`-NoAuth` to clear it.

To remove an install (or reset before a clean reinstall):
`.\bootstrap\uninstall.ps1` stops and unregisters the scheduled tasks and
reaps any leftover CDP chrome; add `-All` to also delete state (issued
tokens, chrome profile, persisted auth choice) and the venv.

## Start the Studio Bridge (5 minutes)

1. **One-time bridge setup** (per project): in the Studio project tree,
   right-click **NetLogic** → add a new **DesignTime NetLogic** named
   `StudioMCPBridge`, double-click it to open the C# editor, and paste in
   [`studio-bridge/StudioMCPBridge.cs`](studio-bridge/StudioMCPBridge.cs)
   (make sure to rebuild in your code editor or save in Studio to trigger a rebuild)
2. **Setup the Project** once per Studio session: right-click
   **StudioMCPBridge** → **SetupProject** → This just adds a webui for validation access at localhost:8081
3. **Start the bridge** once per Studio session: right-click
   **StudioMCPBridge** → **StartBridge** → accept Studio's
   one-time security prompt.
4. **Verify bridge health**: Studio Output will show `listening on http://127.0.0.1:8768` (the bridge). The service dashboard at http://127.0.0.1:8765/ui shows bridge status too.

## Cowork (5 minutes)

Requirements: MCP server and bridge running. Claude desktop app downloaded.

```powershell
cd ftx-mcp                   # install + start the service
.\bootstrap\setup-mcp-client.ps1 -WriteConfig          # adds as a connector to desktop app
```

Restart Claude Desktop (You might have to end task in task manager to fully restart), then ask Claude to **"run optix_status(action='doctor')"** — it
reports anything missing, with a plain-English fix for each item.
In settings > connectors you can adjust the permissions for each of the tools

## Claude Code (5 minutes)

Requirements: MCP server healthy and claude accessible in cli

```powershell
claude mcp add --transport http ftx-mcp http://127.0.0.1:8766/mcp
```

Then in Claude Code, run `/mcp` and confirm `ftx-mcp` shows as connected.

## Visual Studio Code (5 minutes)

Create or open `.vscode/mcp.json` and add:

```json
{
  "servers": {
    "ftx-mcp": {
      "type": "http",
      "url": "http://127.0.0.1:8766/mcp"
    }
  }
}
```

## Your first change

1. Ask for a change, e.g. *"Using the ftx mcp, Add a Start and stop button that toggles
   Model/MotorRun on MainWindow, and verify it works with a label with the text of 'MOTOR RUNNING' that has visibility tied to MotorRun."*
2. Watch it work: author → emulator preview → screenshot → and when it looks
   right, you deploy it to your hardware from Studio as usual.

## What it's capable of

- **Author** widgets, properties, bindings, computed expressions, events,
  translations, and multi-screen navigation — live in the open Studio project.
- **Run** Studio's built-in emulator via F5 key and read the runtime log.
- **Verify** by looking at the webui: screenshot, click
  buttons and tabs, type into fields.
- **Hand back to you to ship** when the preview looks right, you deploy
  from Studio as usual. This distribution only runs the emulator.

The full tool list (37 tools by default — gate env vars can add more — plus
the same surface over plain HTTP for scripts and CI) is in
[docs/tool-reference.md](docs/tool-reference.md).
**Token economy:** screenshots cost ~1-2k vision tokens each; the OCR tool
family (`optix_cdp_read_text`, `find_text`, `navigate`, `sweep`/`diff`) turns
most checks into free text reads — see the `optix-blind-authoring` and
`optix-visual-regression` playbooks for the workflow (setup installs
tesseract automatically; `-NoOcr` opts out).

Bundled **authoring playbooks** (navigation, bound controls, styles,
expressions) ship with the server itself — Claude discovers them via
`optix_list_skills` / `optix_get_skill`, so every connected client gets
them with zero setup. (In Claude Code they also load natively as
[skills](skills/).)

## Security & safety posture

- **Local only.** The service binds `127.0.0.1` and talks to nothing off the
  machine. Optional bearer-token auth, enforced before any LAN bind.
- **Read-only by default.** Every tool carries MCP `readOnlyHint` /
  `destructiveHint` annotations (contract-pinned by tests) so your MCP host
  can auto-approve reads and gate writes.
- **Write gates, not hope.** Undeclared properties, array writes, duplicate
  names, and unsafe re-parents are refused with typed errors; composite
  operations roll back on failure. File-level edits are refused while Studio
  has the project open.
- **Audited.** Every model mutation appends a JSON line to a local audit
  trail (`%LOCALAPPDATA%\ftx-mcp\logs\audit.jsonl`) what, when,
  outcome.
- **Shipping stays in your hands.** Previewing never touches your runtime;
  deploying to hardware happens from Studio, full stop. This distribution
  does design time edits and testing via the emulator.

The full posture including the prompt-injection surface analysis is in
[SECURITY.md](SECURITY.md).

## Documentation

| | |
|---|---|
| [Runbook](docs/runbook.md) | First session, step by step |
| [Tool reference](docs/tool-reference.md) | Every MCP tool + the HTTP API |
| [Architecture](docs/architecture.md) | How the pieces fit together |
| [Troubleshooting](docs/troubleshooting.md) | Symptom-indexed fixes |
| [Security](docs/security.md) | Auth, ports, what talks to what |

## Compatibility

Tested with FactoryTalk Optix Studio 1.7.x on Windows 11, Python 3.12.
Optix CLI behavior is not contract-stable across major versions — pin your
Studio version in production.

## License

[MIT](LICENSE) · © 2026 ASQI · Not affiliated with or endorsed by Rockwell
Automation. FactoryTalk Optix is a trademark of Rockwell Automation, Inc.;
this project orchestrates locally installed Optix binaries without
redistributing them. See [NOTICE](NOTICE).
