@codesys/mcp-toolkit 2.2.0 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/README.md +109 -9
  3. package/README.zh-CN.md +72 -9
  4. package/dist/actions.d.ts +9 -4
  5. package/dist/actions.js +1 -1
  6. package/dist/actions.js.map +1 -1
  7. package/dist/codesys/debug.d.ts +5 -0
  8. package/dist/codesys/debug.js +89 -0
  9. package/dist/codesys/debug.js.map +1 -0
  10. package/dist/codesys/device-tools.d.ts +3 -0
  11. package/dist/codesys/device-tools.js +38 -0
  12. package/dist/codesys/device-tools.js.map +1 -0
  13. package/dist/codesys/graphical.d.ts +76 -0
  14. package/dist/codesys/graphical.js +226 -0
  15. package/dist/codesys/graphical.js.map +1 -0
  16. package/dist/codesys/lang.d.ts +39 -0
  17. package/dist/codesys/lang.js +177 -0
  18. package/dist/codesys/lang.js.map +1 -0
  19. package/dist/codesys/simtest.d.ts +48 -0
  20. package/dist/codesys/simtest.js +103 -0
  21. package/dist/codesys/simtest.js.map +1 -0
  22. package/dist/codesys/st.d.ts +1 -1
  23. package/dist/codesys/st.js.map +1 -1
  24. package/dist/codesys/trace.d.ts +19 -0
  25. package/dist/codesys/trace.js +139 -0
  26. package/dist/codesys/trace.js.map +1 -0
  27. package/dist/hmi/native.d.ts +89 -0
  28. package/dist/hmi/native.js +447 -0
  29. package/dist/hmi/native.js.map +1 -0
  30. package/dist/hmi/render.d.ts +90 -0
  31. package/dist/hmi/render.js +307 -0
  32. package/dist/hmi/render.js.map +1 -0
  33. package/dist/hmi/route.d.ts +32 -0
  34. package/dist/hmi/route.js +184 -0
  35. package/dist/hmi/route.js.map +1 -0
  36. package/dist/hmi/service.d.ts +45 -0
  37. package/dist/hmi/service.js +182 -0
  38. package/dist/hmi/service.js.map +1 -0
  39. package/dist/hmi/spec.d.ts +821 -0
  40. package/dist/hmi/spec.js +191 -0
  41. package/dist/hmi/spec.js.map +1 -0
  42. package/dist/hmi/templates.d.ts +11 -0
  43. package/dist/hmi/templates.js +92 -0
  44. package/dist/hmi/templates.js.map +1 -0
  45. package/dist/hmi/tools.d.ts +4 -0
  46. package/dist/hmi/tools.js +222 -0
  47. package/dist/hmi/tools.js.map +1 -0
  48. package/dist/hmi/value.d.ts +3 -0
  49. package/dist/hmi/value.js +26 -0
  50. package/dist/hmi/value.js.map +1 -0
  51. package/dist/panel/hmi.js +138 -0
  52. package/dist/panel.d.ts +3 -0
  53. package/dist/panel.js +17 -0
  54. package/dist/panel.js.map +1 -1
  55. package/dist/server.d.ts +1 -1
  56. package/dist/server.js +7 -2
  57. package/dist/server.js.map +1 -1
  58. package/dist/tools.d.ts +5 -1
  59. package/dist/tools.js +18 -2
  60. package/dist/tools.js.map +1 -1
  61. package/dist/viewer.d.ts +1 -1
  62. package/dist/viewer.js +13 -2
  63. package/dist/viewer.js.map +1 -1
  64. package/package.json +1 -1
  65. package/watcher/mcp_alarms.py +134 -0
  66. package/watcher/mcp_debug.py +161 -0
  67. package/watcher/mcp_devices.py +83 -0
  68. package/watcher/mcp_lang.py +179 -0
  69. package/watcher/mcp_ops.py +3 -1
  70. package/watcher/mcp_trace.py +90 -0
  71. package/watcher/mcp_ui.py +54 -0
  72. package/watcher/mcp_visu.py +422 -0
  73. package/watcher/watcher.py +35 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,91 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [Unreleased]
9
+
10
+ ## [2.3.0] - 2026-11-14
11
+
12
+ Several of the new actions use CODESYS's own services inside the IDE, beyond
13
+ what its scripting API documents: `get_signature`, `find_references`,
14
+ `rename_symbol`, `trace_setup`, `trace_record`, the debug actions,
15
+ `hmi_export_codesys` and `--show-window`. They are experimental and checked on
16
+ the versions noted below.
17
+
18
+ ### Added
19
+ - HMI screens: Claude designs live operator screens for the program
20
+ (`hmi_save_screen`): a process diagram with tanks, pumps, fans, valves and
21
+ animated pipes, plus gauges, values with sparklines, bars, status lights,
22
+ buttons, switches, setpoints, trends and alarms, bound to PLC variables, in a
23
+ dark or light theme. `hmi_screenshot` returns the screen as an image so the
24
+ model can check and polish its layout. `open_hmi` opens it in the browser
25
+ (127.0.0.1 with a token), live while the simulation runs; buttons, switches
26
+ and setpoints write to the simulation only. Screens are stored next to the
27
+ project as `<project>.hmi.json`.
28
+ - `hmi_export_codesys`: the same screen as a native CODESYS visualization,
29
+ with cards, gradients, SVG pump, fan and valve symbols in an embedded image
30
+ pool, live values, bars, tank levels, colour states, buttons, switches,
31
+ setpoints and alarm rows; a generated program scales values for bars and
32
+ levels. Built through CODESYS's visualization scripting and its element
33
+ creators. Returns a picture of the visualization. Checked on SP21.
34
+ - HMI projects with several pages: a shared header with links to every page and
35
+ the count of active alarms across all pages; page templates (`hmi_template`:
36
+ overview, unit, alarms, trends, settings); faceplate popups on pumps, fans
37
+ and valves; panel sizes 1280x720, 1920x1080, 1024x768 and 800x480; warnings
38
+ for overlapping symbols. Trend history survives page changes.
39
+ - HMI pipes connect to named ports on tanks, pumps, fans, valves and junctions
40
+ and are routed with right angles, so they meet the symbols exactly in the
41
+ browser and in CODESYS.
42
+ - `get_signature`: the interface of any POU or type from CODESYS's compiler,
43
+ including FBs in compiled libraries (TON, CTU, MC_...), with doc comments.
44
+ - `find_references`: where a variable, POU or type is declared, read, written
45
+ or called, with line and column. Both checked on SP21 and SP22.
46
+ - `trace_setup` and `trace_record`: CODESYS Trace in the simulation, returned
47
+ as a summary (BOOL edges and extremes with their times), a table and a
48
+ chart image. Checked on SP22 without a window.
49
+ - `create_graphical`: ladder, FBD and SFC programs and function blocks from a
50
+ structured description, generated as PLCopenXML. Checked on SP22: a ladder
51
+ latch, an AND into a TON and a three-step SFC compile and behave correctly
52
+ in the simulation.
53
+ - Debugging in the simulation: `breakpoint_set` (by line), `debug_status`,
54
+ `debug_step` (over, into, out), `debug_continue`, `breakpoint_clear`.
55
+ Checked on SP22 without a window.
56
+ - `rename_symbol`: rename a variable or POU everywhere it is used, from
57
+ CODESYS's cross-references (works without a window; CODESYS's own
58
+ refactoring needs one). Checked on SP22: 0 build errors after.
59
+ - `codesys_sim_test`: test cases in the simulation (write or force, cycles or
60
+ real time, expected values with comparisons and tolerances), reported as a
61
+ pass/fail table. Checked on SP22.
62
+ - `find_device` and `add_device`: search CODESYS's device repository and add
63
+ devices to the tree. Checked on SP22: Ethernet, a Modbus TCP Client and a
64
+ Modbus TCP Server device compile with 0 errors.
65
+ - `create_object` creates persistent variable lists (`persistent_vars`).
66
+ - `hmi_export_codesys` builds every page: page buttons in each header
67
+ (change shown visualization), the start page and client size of
68
+ TargetVisu and WebVisu, turning pumps and fans (8 frames chosen by the
69
+ clock), faceplates as CODESYS dialog visualizations, the pages' alarms in
70
+ CODESYS alarm management (an alarm group with Error/Warning/Info classes
71
+ and message texts), and visualization user groups with a Login button.
72
+ Checked on SP21: three pages and two dialogs compile with 0 errors; the
73
+ alarms show in CODESYS's alarm group editor with their messages after the
74
+ project is reopened, and in the simulation CODESYS's alarm manager reports
75
+ the raised fault as an active alarm.
76
+ - Input actions only go on shapes: CODESYS raises an assertion dialog when
77
+ an image element gets one.
78
+ - The browser viewer closes open connections when it stops, so an open HMI
79
+ tab no longer keeps the server from exiting. Screenshots retry once when
80
+ the headless browser hangs at start.
81
+ - Actions can return images.
82
+ - `--show-window` opens every object the model creates or writes in its editor
83
+ tab, so the CODESYS window shows the code as it is written, and, while the
84
+ simulation runs, its live values. CODESYS's scripting API has no call for
85
+ this, so it uses CODESYS's own frame (checked on SP21 and SP22); where that
86
+ isn't available, nothing opens and the call works as before.
87
+
88
+ ### Changed
89
+ - The Chinese README states model support directly and lists the models
90
+ tested with OpenCode, as suggested by Zhen Yang (Alfabete-spec), who
91
+ reviews the Chinese documentation.
92
+
8
93
  ## [2.2.0] - 2026-11-14
9
94
 
10
95
  ### Added
package/README.md CHANGED
@@ -34,6 +34,9 @@ can watch the code change as it happens.
34
34
  interfaces, without reading every object.
35
35
  - **Shows its work.** A live panel with the project tree, the code as it is
36
36
  written, compile results, and Accept or Revert for each change.
37
+ - **Designs operator screens.** Claude builds a live HMI for your program,
38
+ with tanks, pumps, valves, gauges, trends and alarms, looks at it, and
39
+ polishes it. You operate it in the browser against the simulation.
37
40
  - **Never touches a real controller.** The only online connection is to
38
41
  CODESYS's own simulation, and every online call checks for it first.
39
42
 
@@ -106,19 +109,33 @@ operation. [The reference](docs/reference.md) describes each one.
106
109
  | --- | --- |
107
110
  | **Projects** | `open_project` `create_project` `save_project` `close_project` `codesys_status` |
108
111
  | **Read code** | `get_project_tree` `read_objects` `search_code` `get_outline` |
109
- | **Change code** | `write_object` `create_object` `delete_object` `rename_object` |
112
+ | **Change code** | `write_object` `create_object` `create_graphical` `delete_object` `rename_object` |
110
113
  | **Build** | `compile` |
111
- | **Libraries** | `list_libraries` `add_library` `remove_library` `get_library_api` |
112
- | **Tasks and I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` |
114
+ | **Libraries** | `list_libraries` `add_library` `remove_library` `get_library_api` `get_signature` |
115
+ | **Navigate code** | `find_references` `rename_symbol` |
116
+ | **Tasks and I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` |
113
117
  | **Change tracking** | `checkpoint` `get_changes` `revert_object` |
114
- | **Simulation** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` |
118
+ | **Simulation** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` `codesys_sim_test` |
119
+ | **Trace** | `trace_setup` `trace_record` |
120
+ | **Debug** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
121
+ | **HMI screens** | `hmi_save_screen` `hmi_template` `hmi_screenshot` `hmi_export_codesys` `hmi_list` `hmi_delete_screen` `open_hmi` |
115
122
  | **Helpers** | `batch` `wait` `help` `open_workspace` |
116
123
 
117
124
  `batch` runs up to 50 actions in one call, which is much faster than separate
118
125
  calls.
119
126
 
120
- Version 2 edits Structured Text only. Objects with graphical bodies (SFC, CFC,
121
- LD, FBD) appear in the tree and can be read as PLCopenXML, but not edited.
127
+ Some actions go beyond what CODESYS's scripting API documents and use CODESYS's
128
+ own services inside the IDE: `get_signature`, `find_references`,
129
+ `rename_symbol`, `trace_setup`, `trace_record`, the debug actions,
130
+ `hmi_export_codesys` (with its alarms and user groups) and `--show-window`.
131
+ They are **experimental**: checked on CODESYS V3.5 SP21 and SP22 as noted in
132
+ the [changelog](CHANGELOG.md). On another version they may report that the
133
+ feature isn't available, or not work.
134
+
135
+ Claude writes Structured Text, and creates ladder (LD), FBD and SFC programs
136
+ and function blocks with `create_graphical` from a simple description of rungs,
137
+ networks or steps; CODESYS draws them. Existing graphical bodies can be read as
138
+ PLCopenXML but not edited in place yet. CFC isn't supported.
122
139
 
123
140
  ## Live panel
124
141
 
@@ -141,6 +158,78 @@ the browser never opens by itself.
141
158
 
142
159
  [More about the panel](docs/reference.md#live-panel)
143
160
 
161
+ ## HMI screens
162
+
163
+ Ask Claude for an operator screen and it designs one for your program: a
164
+ process diagram with tanks, pumps, fans, valves and flowing pipes, and gauges,
165
+ values, trends, status lights, alarms, buttons, switches and setpoints, all
166
+ bound to your PLC variables.
167
+
168
+ ![The live HMI Claude designed for a pump station, running against CODESYS's simulation: the pump's faceplate switched to manual and started, the pump turning and the pipes flowing, a fault raised on the alarm page, the trend page, and the alarm on the overview](docs/images/hmi-live.gif)
169
+
170
+ - **A whole HMI, not one screen.** Pages (overview, unit, alarms, trends,
171
+ settings) share a header that links to every page and counts the active
172
+ alarms of all pages. `hmi_template` gives Claude a good layout for each kind
173
+ of page to adapt. Panels: 1280x720, 1920x1080, 1024x768 or 800x480.
174
+ - **Faceplates.** Clicking a pump, fan or valve opens its popup: mode switch,
175
+ Start/Stop or Open/Close, Reset, live values and a setpoint.
176
+ - **Pipes connect themselves.** Tanks, pumps, fans, valves and junctions have
177
+ named ports (`T-101.right`, `P-101.in`, `V-102.out`). Claude says what a pipe
178
+ connects, and the toolkit routes it with right angles to meet each symbol
179
+ exactly, in the browser and in CODESYS alike. Unknown symbols or ports are
180
+ refused with the list of valid ones.
181
+ - **Claude checks its own work.** `hmi_screenshot` returns the screen as an
182
+ image, so Claude can see overlaps, empty space or unclear labels and fix
183
+ them before you look.
184
+ - **Live in your browser.** Ask Claude to open the HMI (`open_hmi`). The page
185
+ is served by the toolkit on 127.0.0.1 with a token, like the workspace. While
186
+ CODESYS's simulation runs, it shows live values, pumps spin, pipes flow and
187
+ trends draw. Buttons, switches and setpoints write to the simulation, so you
188
+ can operate your program before any hardware exists.
189
+ - **Stored with the project.** Screens are saved next to the project file as
190
+ `<project>.hmi.json`, so they travel with it and can go into version control.
191
+ - **Dark and light themes,** on a 1280x720 canvas that scales to any window.
192
+
193
+ The HMI writes only into CODESYS's own simulation, like the rest of the
194
+ toolkit. Screenshots use Microsoft Edge or Google Chrome, whichever is
195
+ installed.
196
+
197
+ ### As a native CODESYS visualization
198
+
199
+ `hmi_export_codesys` builds the same screen as a real CODESYS visualization in
200
+ your project. It is an ordinary visualization object, so it goes with the
201
+ application like one you drew yourself (we checked it in CODESYS's simulation,
202
+ not on a controller). It doesn't use CODESYS's stock lamps: cards with gradients, SVG
203
+ pump, fan and valve symbols in an embedded image pool, live values, bars and
204
+ tank levels, colour states, buttons, switches, setpoints and alarm rows that
205
+ appear only while active. A generated program, `PRG_HMI_<screen>`, scales
206
+ values for the bars and levels. Claude gets a picture of the result.
207
+
208
+ A multi-page HMI comes out as one visualization per page with page buttons in
209
+ the header, the first page as the start page of TargetVisu and WebVisu at the
210
+ panel size, pumps and fans that turn while running, faceplates as CODESYS
211
+ dialogs, the pages' alarms in CODESYS's alarm management (Alarm Configuration,
212
+ with timestamps and acknowledge in the PLC), and user groups (Operator,
213
+ Maintenance, Admin) behind a Login button. Users and passwords are yours to add
214
+ in the Visualization Manager.
215
+
216
+ ![The same pump station as a native CODESYS visualization, running in CODESYS's simulation](docs/images/hmi-codesys.png)
217
+
218
+ The alarms are CODESYS's own, not a copy in the HMI: an alarm group with its
219
+ observations, classes and messages, which CODESYS's alarm manager evaluates in
220
+ the PLC. In the simulation, raising the fault made the group report an active
221
+ alarm, and it stayed pending after the fault cleared, until acknowledged, as an
222
+ Error-class alarm should.
223
+
224
+ ![The exported alarms in CODESYS's alarm group editor: a digital observation on PLC_PRG.xHighLevel with class Warning and message "High level T-101 (above 90 %)", and one on PLC_PRG.xFault with class Error and message "Pump P-101 fault"](docs/images/codesys-alarms.png)
225
+
226
+ CODESYS's scripting can't create trend, meter or alarm-table elements, so
227
+ trends show their current values, gauges show a bar, and the alarm page shows a
228
+ row per alarm while it is active (acknowledge it in CODESYS's own alarm table,
229
+ which you can add from the toolbox). Checked on CODESYS V3.5 SP21 in the
230
+ simulation. A visualization needs the `FloatingPointUtils` library in CODESYS's
231
+ library repository; if it's missing, the export says so.
232
+
144
233
  ## Other clients and models
145
234
 
146
235
  The server works with any MCP client, not only Claude. For
@@ -228,10 +317,19 @@ itself.
228
317
  ### Watch it in the CODESYS window
229
318
 
230
319
  By default CODESYS runs headless. With `--show-window` the server starts it with
231
- its normal window, so you can see the project take shape (objects appear in the
232
- tree as the model creates them) in any MCP client.
320
+ its normal window, so you can watch the work in any MCP client: every object the
321
+ model creates or writes opens in its editor tab, with the new code in it.
322
+
323
+ ![CODESYS started with --show-window: the model just created FB_Blink, and it opened in its editor](docs/images/codesys-window.png)
233
324
 
234
- ![CODESYS started with --show-window, after an OpenCode session created PumpDemo with FB_Pump](docs/images/codesys-window.png)
325
+ While the simulation runs, the open editors show live values, as in CODESYS's own
326
+ online mode:
327
+
328
+ ![The same window during the simulation: PLC_PRG shows xEnable and xOn as TRUE](docs/images/codesys-window-sim.png)
329
+
330
+ CODESYS's scripting API has no call for opening an editor, so the toolkit uses
331
+ CODESYS's own (undocumented) frame for it, checked on SP21 and SP22. If a CODESYS
332
+ version doesn't have it, nothing opens and everything else works as before.
235
333
 
236
334
  While the server is connected, the window is for watching: the toolkit's script
237
335
  keeps running in it (that is what lets it answer CODESYS's prompts, such as a
@@ -365,6 +463,8 @@ The persistent-watcher design borrows ideas from
365
463
  [phobicdotno/Codesys-MCP-Master](https://github.com/phobicdotno/Codesys-MCP-Master)
366
464
  (file-queue IPC, version-safe opening). Both are MIT-licensed.
367
465
 
466
+ The [Chinese README](README.zh-CN.md) was reviewed by Zhen Yang (Alfabete-spec).
467
+
368
468
  ## License
369
469
 
370
470
  [MIT](LICENSE)
package/README.zh-CN.md CHANGED
@@ -17,8 +17,10 @@
17
17
 
18
18
  这是一个 [MCP](https://modelcontextprotocol.io)(模型上下文协议)服务器。它在后台保持一个
19
19
  CODESYS 会话,让 AI 助手直接操作你的真实项目:用真正的 CODESYS 编译器编译,在 CODESYS
20
- 自带的仿真中测试,而你可以实时看到代码的变化。它不绑定 Claude:DeepSeek、通义千问(Qwen)、
21
- GLM、MiniMax 等模型通过 OpenCode 等客户端同样可以使用。
20
+ 自带的仿真中测试,而你可以实时看到代码的变化。
21
+
22
+ 工具包支持任何能够通过 MCP 客户端调用工具的 AI 模型。我们用 OpenCode 测试了 DeepSeek V4.1 Flash、
23
+ 通义千问 Qwen 3.6 Plus、GLM 5.3 和 MiniMax M3,均完成了全部步骤(见[已测试的模型](#已测试的模型))。
22
24
 
23
25
  ![Claude 在 CODESYS 中编写液位控制功能块:对话中的实时面板、0 错误编译和 5 项仿真测试全部通过,右侧是同一功能块在工作区中的代码](docs/images/claude-and-codesys.png)
24
26
 
@@ -134,10 +136,57 @@ Cline、Trae、通义灵码、Cursor、Claude Desktop 等使用 `mcpServers` 配
134
136
  - **浏览器中的工作区。** 在其他客户端中,让模型“打开 CODESYS 工作区”(`open_workspace`),
135
137
  同样的界面会在浏览器中打开,只监听本机 127.0.0.1,并带有访问令牌。浏览器不会自动打开。
136
138
  - **CODESYS 窗口。** 启动参数加上 `--show-window`,CODESYS 会以正常窗口运行,而不是在后台
137
- 无界面运行,可以看到模型创建的对象出现在项目树中。工具包不会自动关闭这个窗口。
139
+ 无界面运行。模型创建或修改的每个对象都会在编辑器标签页中打开,可以直接看到新写的代码;
140
+ 仿真运行时,打开的编辑器会显示变量的实时值。工具包不会自动关闭这个窗口。
141
+
142
+ ![使用 --show-window 启动的 CODESYS:模型刚创建的 FB_Blink 已在编辑器中打开](docs/images/codesys-window.png)
138
143
 
139
144
  ![OpenCode 会话结束后在浏览器中打开的工作区:PLC_PRG 的改动,以及每个对象的接受和还原按钮](docs/images/workspace-review.png)
140
145
 
146
+ ## HMI 操作画面
147
+
148
+ 让 Claude 为你的程序设计操作画面:带储罐、泵、风机、阀门和流动管道的工艺流程图,以及仪表盘、
149
+ 数值、趋势图、状态灯、报警、按钮、开关和设定值,全部绑定到 PLC 变量。
150
+
151
+ ![Claude 为泵站设计的实时 HMI,连接 CODESYS 仿真运行:打开泵的面板切换到手动并启动,泵转动、管道流动,在报警页触发故障,趋势页,以及总览页上的报警](docs/images/hmi-live.gif)
152
+
153
+ - **完整的 HMI,而不只是一个画面。** 多个页面(总览、单元、报警、趋势、设置)共用一个页眉,
154
+ 页眉链接到每个页面并统计所有页面的活动报警。`hmi_template` 为每种页面提供良好的布局。
155
+ 面板尺寸:1280x720、1920x1080、1024x768 或 800x480。
156
+ - **操作面板(faceplate)。** 点击泵、风机或阀门会弹出面板:模式开关、启动/停止或开/关、复位、
157
+ 实时数值和设定值。
158
+ - **Claude 会检查自己的设计。** `hmi_screenshot` 把画面作为图片返回给 Claude,它能发现重叠、
159
+ 空白或不清楚的标签并自行修正。
160
+ - **在浏览器中实时运行。** 让 Claude 打开 HMI(`open_hmi`)。页面由工具包在 127.0.0.1 上提供,
161
+ 并带有访问令牌。CODESYS 仿真运行时显示实时数值,泵会转动,管道会流动;按钮、开关和设定值
162
+ 写入仿真,在没有硬件之前就能操作你的程序。
163
+ - **管道自动连接。** 储罐、泵、风机、阀门和三通都有命名接口(如 `T-101.right`、`P-101.in`),Claude 只需说明管道连接哪两个接口,
164
+ 工具包会以直角自动布线,在浏览器和 CODESYS 中都能精确对接。
165
+ - **与项目一起保存。** 画面保存在项目文件旁边的 `<项目名>.hmi.json` 中。
166
+
167
+ HMI 只写入 CODESYS 自带的仿真,不会连接真实控制器。
168
+
169
+ `hmi_export_codesys` 还能把同一个画面生成为项目中的原生 CODESYS 可视化(不用 CODESYS 自带的灯和按钮样式):
170
+ 渐变卡片、嵌入图片池的 SVG 泵/风机/阀门符号、实时数值、液位和棒图、按钮、开关、设定值和报警行,
171
+ 它是普通的可视化对象,随应用程序一起使用(我们在 CODESYS 仿真中验证过,未在真实控制器上测试)。
172
+
173
+ 多页 HMI 会生成为每页一个可视化,页眉中有页面按钮;第一页设为 TargetVisu 和 WebVisu 的起始页;
174
+ 运行中的泵和风机会转动;操作面板生成为 CODESYS 对话框;用户组(Operator、Maintenance、Admin)
175
+ 配有登录按钮(用户和密码由你在 Visualization Manager 中添加)。
176
+
177
+ ![同一个泵站画面,作为原生 CODESYS 可视化在仿真中运行](docs/images/hmi-codesys.png)
178
+
179
+ 报警是 CODESYS 自己的报警,而不是 HMI 中的副本:导出会创建报警配置(Alarm Configuration)中的
180
+ 报警组,包括观察条件、报警类别和报警消息,由 CODESYS 的报警管理器在 PLC 中计算。在仿真中触发
181
+ 故障后,报警组报告一个活动报警;故障消失后它仍保持待确认状态,直到被确认,这正是 Error 类报警
182
+ 应有的行为。
183
+
184
+ ![导出的报警在 CODESYS 报警组编辑器中:PLC_PRG.xHighLevel 的数字观察,类别 Warning,消息 "High level T-101 (above 90 %)";PLC_PRG.xFault 的数字观察,类别 Error,消息 "Pump P-101 fault"](docs/images/codesys-alarms.png)
185
+
186
+ CODESYS 的脚本无法创建趋势、仪表或报警表元素,所以趋势显示当前值,仪表显示为棒图,报警页在
187
+ 报警活动时显示一行(可在 CODESYS 自带的报警表中确认报警,报警表可从工具箱添加)。已在 CODESYS
188
+ V3.5 SP21 的仿真中验证。可视化需要 CODESYS 库存储库中有 `FloatingPointUtils` 库;如果缺少,导出会提示。
189
+
141
190
  ## 可用操作
142
191
 
143
192
  所有操作都通过一个 MCP 工具 `codesys` 完成,每个操作对应一个 action。
@@ -147,18 +196,28 @@ Cline、Trae、通义灵码、Cursor、Claude Desktop 等使用 `mcpServers` 配
147
196
  | --- | --- |
148
197
  | **项目** | `open_project` `create_project` `save_project` `close_project` `codesys_status` |
149
198
  | **读取代码** | `get_project_tree` `read_objects` `search_code` `get_outline` |
150
- | **修改代码** | `write_object` `create_object` `delete_object` `rename_object` |
199
+ | **修改代码** | `write_object` `create_object` `create_graphical` `delete_object` `rename_object` |
151
200
  | **编译** | `compile` |
152
- | **库** | `list_libraries` `add_library` `remove_library` `get_library_api` |
153
- | **任务与 I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` |
201
+ | **库** | `list_libraries` `add_library` `remove_library` `get_library_api` `get_signature` |
202
+ | **代码导航** | `find_references` `rename_symbol` |
203
+ | **任务与 I/O** | `list_tasks` `configure_task` `get_io_list` `get_devices` `find_device` `add_device` |
154
204
  | **改动跟踪** | `checkpoint` `get_changes` `revert_object` |
155
- | **仿真** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` |
205
+ | **仿真** | `codesys_sim_start` `codesys_sim_stop` `codesys_sim_status` `codesys_sim_control` `codesys_sim_cycle` `codesys_sim_read` `codesys_sim_write` `codesys_sim_force` `codesys_sim_unforce` `codesys_sim_test` |
206
+ | **跟踪(Trace)** | `trace_setup` `trace_record` |
207
+ | **调试** | `breakpoint_set` `breakpoint_clear` `debug_status` `debug_step` `debug_continue` |
208
+ | **HMI 画面** | `hmi_save_screen` `hmi_template` `hmi_screenshot` `hmi_export_codesys` `hmi_list` `hmi_delete_screen` `open_hmi` |
156
209
  | **辅助** | `batch` `wait` `help` `open_workspace` |
157
210
 
158
211
  `batch` 可以在一次调用中执行最多 50 个操作,比逐个调用快得多。
159
212
 
160
- 第 2 版只编辑结构化文本。图形化语言(SFC、CFC、LD、FBD)的对象会显示在项目树中,可以以
161
- PLCopenXML 形式读取,但不能编辑。
213
+ 有些操作超出了 CODESYS 脚本 API 文档的范围,使用 IDE 内部的 CODESYS 服务:`get_signature`、
214
+ `find_references`、`rename_symbol`、`trace_setup`、`trace_record`、调试操作、`hmi_export_codesys`
215
+ (包括报警和用户组)以及 `--show-window`。它们属于**实验性功能**:已在 CODESYS V3.5 SP21 和 SP22 上
216
+ 验证(见[更新日志](CHANGELOG.md)),在其他版本上可能提示功能不可用,或无法正常工作。
217
+
218
+ Claude 编写结构化文本,并可用 `create_graphical` 根据梯级、网络或步骤的简单描述创建梯形图(LD)、
219
+ FBD 和 SFC 程序及功能块,由 CODESYS 绘制。已有的图形化代码可以以 PLCopenXML 形式读取,但还不能
220
+ 就地编辑。不支持 CFC。
162
221
 
163
222
  ## 安全
164
223
 
@@ -180,6 +239,10 @@ PLCopenXML 形式读取,但不能编辑。
180
239
 
181
240
  欢迎提交 Issue 和 Pull Request,中文或英文均可。
182
241
 
242
+ ## 致谢
243
+
244
+ 感谢 Zhen Yang(Alfabete-spec)审阅本中文文档。
245
+
183
246
  ## 许可证
184
247
 
185
248
  [MIT](LICENSE)
package/dist/actions.d.ts CHANGED
@@ -8,11 +8,16 @@
8
8
  import type { McpServer } from "@modelcontextprotocol/server";
9
9
  import * as z from "zod/v4";
10
10
  export declare const TOOL_NAME = "codesys";
11
+ export type ActionContent = {
12
+ type: "text";
13
+ text: string;
14
+ } | {
15
+ type: "image";
16
+ data: string;
17
+ mimeType: string;
18
+ };
11
19
  export type ActionResult = {
12
- content: {
13
- type: "text";
14
- text: string;
15
- }[];
20
+ content: ActionContent[];
16
21
  isError?: boolean;
17
22
  };
18
23
  export interface ActionConfig<S extends z.ZodObject = z.ZodObject> {
package/dist/actions.js CHANGED
@@ -57,7 +57,7 @@ function batchAction(actions) {
57
57
  let failed = false;
58
58
  for (const [i, s] of steps.entries()) {
59
59
  const r = await s.action.run(s.args);
60
- out.push(`[${i + 1}/${steps.length}] ${s.name}${r.isError ? " FAILED" : ""}:\n${r.content.map((c) => c.text).join("\n")}`);
60
+ out.push(`[${i + 1}/${steps.length}] ${s.name}${r.isError ? " FAILED" : ""}:\n${r.content.map((c) => (c.type === "text" ? c.text : "(an image: call this action on its own to see it)")).join("\n")}`);
61
61
  failed ||= !!r.isError;
62
62
  if (r.isError && !continueOnError) {
63
63
  if (i + 1 < steps.length)
@@ -1 +1 @@
1
- {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { ActionResult, RegisterAction } from "../actions.js";
2
+ import type { AppContext } from "../tools.js";
3
+ /** Implementation line (1-based) -> CODESYS position, for every statement. */
4
+ export declare function lineMap(impl: string, positions: number[]): Map<number, number>;
5
+ export declare function registerDebugActions(reg: RegisterAction, ctx: AppContext, run: (fn: () => Promise<string>) => Promise<ActionResult>): void;
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Breakpoints and stepping in CODESYS's simulation (watcher/mcp_debug.py).
3
+ * CODESYS addresses statements by position; the low 32 bits of a position are
4
+ * the implementation line plus a per-object offset, so lines map to positions
5
+ * from the first statement's line.
6
+ */
7
+ import * as z from "zod/v4";
8
+ import { currentCodesysSim } from "./simulation.js";
9
+ const low = (p) => p - Math.floor(p / 2 ** 32) * 2 ** 32;
10
+ /** Implementation line (1-based) -> CODESYS position, for every statement. */
11
+ export function lineMap(impl, positions) {
12
+ const lines = impl.split(/\r?\n/);
13
+ const first = lines.findIndex((l) => {
14
+ const t = l.trim();
15
+ return t && !t.startsWith("//") && !t.startsWith("(*");
16
+ });
17
+ const valid = positions.filter((p) => low(p) !== 0xffffffff);
18
+ const out = new Map();
19
+ if (first < 0 || !valid.length)
20
+ return out;
21
+ const base = low(valid[0]) - (first + 1);
22
+ for (const p of valid) {
23
+ const line = low(p) - base;
24
+ if (line >= 1 && line <= lines.length && !out.has(line))
25
+ out.set(line, p);
26
+ }
27
+ return out;
28
+ }
29
+ export function registerDebugActions(reg, ctx, run) {
30
+ const b = ctx.bridge;
31
+ const needSim = () => {
32
+ if (!currentCodesysSim(ctx))
33
+ throw new Error("The simulation isn't running: call codesys_sim_start first. Breakpoints only work in CODESYS's simulation.");
34
+ };
35
+ const where = (s) => {
36
+ if (!/halt/i.test(s.state))
37
+ return `Simulation: ${s.state}.`;
38
+ const at = s.at;
39
+ if (!at?.path)
40
+ return `Simulation: ${s.state} (position unknown).`;
41
+ const map = lineMap(at.implementation ?? "", at.positions ?? []);
42
+ const line = [...map].find(([, p]) => p === at.position)?.[0];
43
+ const code = line ? (at.implementation ?? "").split(/\r?\n/)[line - 1]?.trim() : undefined;
44
+ const end = low(at.position) === 0xffffffff ? " at its end (RETURN)" : "";
45
+ return `Halted in ${at.path}${line ? ` at line ${line}: ${code}` : end} (instance ${at.instance}). Read values with codesys_sim_read, then debug_step or debug_continue.`;
46
+ };
47
+ reg("breakpoint_set", {
48
+ description: "Set a breakpoint in the running simulation at a line of a POU's implementation. The simulation halts there; debug_status shows where, codesys_sim_read reads values, debug_step steps, debug_continue goes on. For a function block give the instance, e.g. 'PLC_PRG.fbPump'.",
49
+ inputSchema: z.object({
50
+ path: z.string().describe("POU, e.g. 'FB_Pump' or 'PLC_PRG'"),
51
+ line: z.number().int().min(1).describe("Line of the implementation (1 = first line)"),
52
+ instance: z.string().optional().describe("Instance path for a function block, e.g. 'PLC_PRG.fbPump' (a program is its own instance)"),
53
+ }),
54
+ }, async ({ path, line, instance }) => run(async () => {
55
+ needSim();
56
+ const p = await b.call("debug.positions", { path });
57
+ const map = lineMap(p.implementation, p.positions);
58
+ const lines = [...map.keys()].sort((x, y) => x - y);
59
+ const at = lines.find((l) => l >= line);
60
+ if (at === undefined)
61
+ throw new Error(`No statement at or after line ${line} of ${p.path}. Statement lines: ${lines.join(", ")}.`);
62
+ const inst = instance ?? p.path.split("/").pop();
63
+ await b.call("debug.set", { path, position: map.get(at), instance: inst });
64
+ const code = p.implementation.split(/\r?\n/)[at - 1]?.trim();
65
+ return `Breakpoint at ${p.path} line ${at}${at !== line ? ` (the first statement at or after line ${line})` : ""}: ${code} (instance ${inst}).`;
66
+ }));
67
+ reg("breakpoint_clear", { description: "Remove all breakpoints (the simulation then keeps running after debug_continue).", inputSchema: z.object({}) }, async () => run(async () => {
68
+ needSim();
69
+ const r = await b.call("debug.clear", {});
70
+ return r.cleared.length ? `Removed ${r.cleared.length} breakpoint(s).` : "There were no breakpoints.";
71
+ }));
72
+ reg("debug_status", { description: "Whether the simulation is running or halted at a breakpoint, and where (POU, line, code).", inputSchema: z.object({}) }, async () => run(async () => {
73
+ needSim();
74
+ return where(await b.call("debug.status", {}));
75
+ }));
76
+ reg("debug_step", {
77
+ description: "Step while halted: over (next statement), into (into a called POU), out (back to the caller).",
78
+ inputSchema: z.object({ kind: z.enum(["over", "into", "out"]).default("over") }),
79
+ }, async ({ kind }) => run(async () => {
80
+ needSim();
81
+ return where(await b.call("debug.step", { kind }));
82
+ }));
83
+ reg("debug_continue", { description: "Continue running after a halt (it halts again at the next breakpoint hit).", inputSchema: z.object({}) }, async () => run(async () => {
84
+ needSim();
85
+ const r = await b.call("debug.continue", {});
86
+ return `Simulation: ${r.state}.`;
87
+ }));
88
+ }
89
+ //# sourceMappingURL=debug.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"debug.js","sourceRoot":"","sources":["../../src/codesys/debug.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ActionResult, RegisterAction } from "../actions.js";
2
+ import type { AppContext } from "../tools.js";
3
+ export declare function registerDeviceActions(reg: RegisterAction, ctx: AppContext, run: (fn: () => Promise<string>) => Promise<ActionResult>): void;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Devices from CODESYS's device repository: find installed device descriptions
3
+ * (fieldbus masters and slaves, I/O modules) and add them to the device tree
4
+ * (watcher/mcp_devices.py). Offline: nothing goes online.
5
+ */
6
+ import * as z from "zod/v4";
7
+ export function registerDeviceActions(reg, ctx, run) {
8
+ const b = ctx.bridge;
9
+ reg("find_device", {
10
+ description: "Search the device descriptions installed in CODESYS (fieldbus masters and slaves such as Modbus TCP, EtherCAT, CANopen, PROFINET; I/O modules; drives) by name. Returns type, id and version to pass to add_device.",
11
+ inputSchema: z.object({ text: z.string().describe("Part of the device name, e.g. 'Modbus TCP', 'EtherCAT Master', 'CANopen'"), limit: z.number().int().min(1).max(100).default(30) }),
12
+ }, async ({ text, limit }) => run(async () => {
13
+ const r = await b.call("devices.search", { text, limit }, { timeoutMs: 120_000 });
14
+ if (!r.devices.length)
15
+ return `No installed device description matches '${text}'. Install it with the CODESYS Installer or Tools > Device Repository.`;
16
+ return [
17
+ `${r.devices.length}${r.more ? "+" : ""} device(s) matching '${text}':`,
18
+ ...r.devices.map((d) => `- ${d.name} (${d.vendor}${d.version ? `, ${d.version}` : ""}) type=${d.type} id='${d.id}' version='${d.version}'${d.description ? `: ${d.description}` : ""}`),
19
+ ].join("\n");
20
+ }));
21
+ reg("add_device", {
22
+ description: "Add a device from the repository to the device tree, under a device: the controller (its name from get_devices, e.g. '/Device' or '/PLCWinNT') for an Ethernet adapter or bus interface, the adapter for a fieldbus master, the master for its slaves. Use type, id and version from find_device. 'plug' fills a slot of a device with fixed slots. Then map its I/O channels (get_devices shows them) and compile.",
23
+ inputSchema: z.object({
24
+ parent: z.string().describe("Device to add under, e.g. '/PLCWinNT' or '/PLCWinNT/Ethernet'"),
25
+ name: z.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).describe("Name of the new device, e.g. 'Modbus_TCP_Master'"),
26
+ type: z.number().int(),
27
+ id: z.string(),
28
+ version: z.string(),
29
+ module: z.string().optional(),
30
+ how: z.enum(["add", "insert", "plug"]).default("add"),
31
+ index: z.number().int().optional().describe("Position for insert"),
32
+ }),
33
+ }, async (a) => run(async () => {
34
+ const r = await b.call("devices.add", { ...a, save: ctx.autosave }, { timeoutMs: 120_000 });
35
+ return `Added ${a.name} at ${r.path}. Call get_devices to see its I/O channels, and compile.`;
36
+ }));
37
+ }
38
+ //# sourceMappingURL=device-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-tools.js","sourceRoot":"","sources":["../../src/codesys/device-tools.ts"],"names":[],"mappings":"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"}