@codesys/mcp-toolkit 1.1.4 → 1.2.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.
@@ -1,155 +1,155 @@
1
- # @codesys/mcp-toolkit
2
-
3
- ![npm](https://img.shields.io/npm/v/@codesys/mcp-toolkit)
4
- ![License](https://img.shields.io/github/license/yourusername/codesys-mcp-toolkit)
5
-
6
- A Model Context Protocol (MCP) server for CODESYS V3 programming environments. This toolkit enables seamless interaction between MCP clients (like Claude Desktop) and CODESYS, allowing automation of project management, POU creation, code editing, and compilation tasks.
7
-
8
- <p align="center">
9
- <img src="https://github.com/yourusername/codesys-mcp-toolkit/raw/main/docs/assets/diagram.png" alt="CODESYS MCP Toolkit Architecture" width="600">
10
- </p>
11
-
12
- ## 🌟 Features
13
-
14
- - **Project Management**
15
- - Open existing CODESYS projects
16
- - Create new projects from templates
17
- - Save project changes
18
-
19
- - **POU Management**
20
- - Create Programs, Function Blocks, and Functions
21
- - Set declaration and implementation code
22
- - Create properties and methods for Function Blocks
23
- - Compile projects
24
-
25
- - **MCP Resources**
26
- - `codesys://project/status`: Check scripting status and project state
27
- - `codesys://project/{+project_path}/structure`: Retrieve project structure
28
- - `codesys://project/{+project_path}/pou/{+pou_path}/code`: Read POU code
29
-
30
- - **MCP Tools**
31
- - `open_project`: Open specified CODESYS project
32
- - `create_project`: Create new CODESYS project
33
- - `save_project`: Save currently open project
34
- - `create_pou`: Create new Program, Function Block, or Function
35
- - `set_pou_code`: Update code for a specified POU
36
- - `create_property`: Create property in a Function Block
37
- - `create_method`: Create method in a Function Block
38
- - `compile_project`: Compile the open project
39
-
40
- ## 📋 Prerequisites
41
-
42
- - **CODESYS V3**: A working CODESYS V3 installation (tested with 3.5 SP21) with **Scripting Engine** component enabled
43
- - **Node.js**: Version 18 or later required
44
- - **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
45
-
46
- ## 🚀 Installation
47
-
48
- ### Option 1: Install from npm (Recommended)
49
-
50
- ```bash
51
- npm install -g @codesys/mcp-toolkit
52
- ```
53
-
54
- This installs the package globally, making the `codesys-mcp-toolkit` command available in your terminal.
55
-
56
- ### Option 2: Install from Source
57
-
58
- ```bash
59
- # Clone the repository
60
- git clone https://github.com/yourusername/codesys-mcp-toolkit.git
61
- cd codesys-mcp-toolkit
62
-
63
- # Install dependencies
64
- npm install
65
-
66
- # Build the project
67
- npm run build
68
-
69
- # Install globally
70
- npm install -g .
71
- ```
72
-
73
- ## 🔧 Configuration
74
-
75
- ### Claude Desktop Configuration
76
-
77
- 1. Locate your Claude Desktop configuration file:
78
- - Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
79
-
80
- 2. Add the CODESYS MCP server entry:
81
-
82
- ```json
83
- {
84
- "mcpServers": {
85
- "codesys_local": {
86
- "command": "npx",
87
- "args": [
88
- "-y",
89
- "@codesys/mcp-toolkit",
90
- "--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
91
- "--codesys-profile", "CODESYS V3.5 SP21"
92
- ]
93
- }
94
- }
95
- }
96
- ```
97
-
98
- 3. Customize the paths to match your CODESYS installation:
99
- - `--codesys-path`: Path to your CODESYS.exe
100
- - `--codesys-profile`: Your CODESYS profile name
101
-
102
- 4. Restart Claude Desktop to apply the changes
103
-
104
- ## 🛠️ Usage Examples
105
-
106
- ### Creating a Function Block with Properties
107
-
108
- ```
109
- Ask Claude: "Using the CODESYS Local server, please create a Motor Controller function block with Start and Stop methods, plus CurrentSpeed property."
110
- ```
111
-
112
- Claude will execute these MCP tool calls:
113
- 1. `create_pou` to create the MotorController Function Block
114
- 2. `create_property` to add the CurrentSpeed property
115
- 3. `create_method` to add Start and Stop methods
116
- 4. `set_pou_code` to implement each method and property
117
-
118
- ### Opening and Compiling a Project
119
-
120
- ```
121
- Ask Claude: "Can you open the project at C:/MyProjects/TestProject.project using CODESYS Local and compile it?"
122
- ```
123
-
124
- Claude will:
125
- 1. Use `open_project` to open the specified file
126
- 2. Use `compile_project` to build the application
127
-
128
- ## 🔍 Troubleshooting
129
-
130
- ### Common Issues
131
-
132
- - **Connection Failures**: Check Claude Desktop logs for error messages
133
- - **Path Issues**: Ensure CODESYS executable path is correct
134
- - **Profile Mismatch**: Verify profile name matches exactly
135
- - **Permission Problems**: Ensure Claude has appropriate permissions
136
- - **CODESYS Already Running**: Close other CODESYS instances
137
-
138
- ### Debug Logs
139
-
140
- Check logs at:
141
- - Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\logs\`
142
-
143
- ## 🤝 Contributing
144
-
145
- Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
146
-
147
- ## 📝 License
148
-
149
- This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
150
-
151
- ## 🙏 Acknowledgements
152
-
153
- - The [CODESYS](https://www.codesys.com/) team for their scripting engine
154
- - [Model Context Protocol](https://github.com/m-ld/model-context-protocol) project
155
- - All contributors who have helped improve this toolkit
1
+ # @codesys/mcp-toolkit
2
+
3
+ ![npm](https://img.shields.io/npm/v/@codesys/mcp-toolkit)
4
+ ![License](https://img.shields.io/github/license/yourusername/codesys-mcp-toolkit)
5
+
6
+ A Model Context Protocol (MCP) server for CODESYS V3 programming environments. This toolkit enables seamless interaction between MCP clients (like Claude Desktop) and CODESYS, allowing automation of project management, POU creation, code editing, and compilation tasks.
7
+
8
+ <p align="center">
9
+ <img src="https://github.com/yourusername/codesys-mcp-toolkit/raw/main/docs/assets/diagram.png" alt="CODESYS MCP Toolkit Architecture" width="600">
10
+ </p>
11
+
12
+ ## 🌟 Features
13
+
14
+ - **Project Management**
15
+ - Open existing CODESYS projects
16
+ - Create new projects from templates
17
+ - Save project changes
18
+
19
+ - **POU Management**
20
+ - Create Programs, Function Blocks, and Functions
21
+ - Set declaration and implementation code
22
+ - Create properties and methods for Function Blocks
23
+ - Compile projects
24
+
25
+ - **MCP Resources**
26
+ - `codesys://project/status`: Check scripting status and project state
27
+ - `codesys://project/{+project_path}/structure`: Retrieve project structure
28
+ - `codesys://project/{+project_path}/pou/{+pou_path}/code`: Read POU code
29
+
30
+ - **MCP Tools**
31
+ - `open_project`: Open specified CODESYS project
32
+ - `create_project`: Create new CODESYS project
33
+ - `save_project`: Save currently open project
34
+ - `create_pou`: Create new Program, Function Block, or Function
35
+ - `set_pou_code`: Update code for a specified POU
36
+ - `create_property`: Create property in a Function Block
37
+ - `create_method`: Create method in a Function Block
38
+ - `compile_project`: Compile the open project
39
+
40
+ ## 📋 Prerequisites
41
+
42
+ - **CODESYS V3**: A working CODESYS V3 installation (tested with 3.5 SP21) with **Scripting Engine** component enabled
43
+ - **Node.js**: Version 18 or later required
44
+ - **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
45
+
46
+ ## 🚀 Installation
47
+
48
+ ### Option 1: Install from npm (Recommended)
49
+
50
+ ```bash
51
+ npm install -g @codesys/mcp-toolkit
52
+ ```
53
+
54
+ This installs the package globally, making the `codesys-mcp-toolkit` command available in your terminal.
55
+
56
+ ### Option 2: Install from Source
57
+
58
+ ```bash
59
+ # Clone the repository
60
+ git clone https://github.com/yourusername/codesys-mcp-toolkit.git
61
+ cd codesys-mcp-toolkit
62
+
63
+ # Install dependencies
64
+ npm install
65
+
66
+ # Build the project
67
+ npm run build
68
+
69
+ # Install globally
70
+ npm install -g .
71
+ ```
72
+
73
+ ## 🔧 Configuration
74
+
75
+ ### Claude Desktop Configuration
76
+
77
+ 1. Locate your Claude Desktop configuration file:
78
+ - Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
79
+
80
+ 2. Add the CODESYS MCP server entry:
81
+
82
+ ```json
83
+ {
84
+ "mcpServers": {
85
+ "codesys_local": {
86
+ "command": "npx",
87
+ "args": [
88
+ "-y",
89
+ "@codesys/mcp-toolkit",
90
+ "--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
91
+ "--codesys-profile", "CODESYS V3.5 SP21"
92
+ ]
93
+ }
94
+ }
95
+ }
96
+ ```
97
+
98
+ 3. Customize the paths to match your CODESYS installation:
99
+ - `--codesys-path`: Path to your CODESYS.exe
100
+ - `--codesys-profile`: Your CODESYS profile name
101
+
102
+ 4. Restart Claude Desktop to apply the changes
103
+
104
+ ## 🛠️ Usage Examples
105
+
106
+ ### Creating a Function Block with Properties
107
+
108
+ ```
109
+ Ask Claude: "Using the CODESYS Local server, please create a Motor Controller function block with Start and Stop methods, plus CurrentSpeed property."
110
+ ```
111
+
112
+ Claude will execute these MCP tool calls:
113
+ 1. `create_pou` to create the MotorController Function Block
114
+ 2. `create_property` to add the CurrentSpeed property
115
+ 3. `create_method` to add Start and Stop methods
116
+ 4. `set_pou_code` to implement each method and property
117
+
118
+ ### Opening and Compiling a Project
119
+
120
+ ```
121
+ Ask Claude: "Can you open the project at C:/MyProjects/TestProject.project using CODESYS Local and compile it?"
122
+ ```
123
+
124
+ Claude will:
125
+ 1. Use `open_project` to open the specified file
126
+ 2. Use `compile_project` to build the application
127
+
128
+ ## 🔍 Troubleshooting
129
+
130
+ ### Common Issues
131
+
132
+ - **Connection Failures**: Check Claude Desktop logs for error messages
133
+ - **Path Issues**: Ensure CODESYS executable path is correct
134
+ - **Profile Mismatch**: Verify profile name matches exactly
135
+ - **Permission Problems**: Ensure Claude has appropriate permissions
136
+ - **CODESYS Already Running**: Close other CODESYS instances
137
+
138
+ ### Debug Logs
139
+
140
+ Check logs at:
141
+ - Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\logs\`
142
+
143
+ ## 🤝 Contributing
144
+
145
+ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
146
+
147
+ ## 📝 License
148
+
149
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
150
+
151
+ ## 🙏 Acknowledgements
152
+
153
+ - The [CODESYS](https://www.codesys.com/) team for their scripting engine
154
+ - [Model Context Protocol](https://github.com/m-ld/model-context-protocol) project
155
+ - All contributors who have helped improve this toolkit
Binary file
@@ -7,6 +7,7 @@
7
7
  * - Creating temporary Python script files
8
8
  * - Executing them via CODESYS's scripting engine
9
9
  * - Capturing and processing results
10
+ * - Supporting both one-off script execution and persistent sessions
10
11
  *
11
12
  * IMPORTANT: Path handling for Windows is critical - paths with spaces require
12
13
  * special handling to avoid the 'C:\Program' not recognized error.
@@ -60,6 +61,8 @@ const promises_1 = require("fs/promises");
60
61
  const path = __importStar(require("path"));
61
62
  const os = __importStar(require("os"));
62
63
  const fs = __importStar(require("fs")); // Import fs for existsSync check
64
+ // Optional import for session manager
65
+ const sessionManager_1 = require("./sessionManager");
63
66
  // Define expected success/error markers from the Python scripts
64
67
  const SCRIPT_SUCCESS_MARKER = 'SCRIPT_SUCCESS';
65
68
  const SCRIPT_ERROR_MARKER = 'SCRIPT_ERROR';
@@ -69,12 +72,13 @@ const SCRIPT_ERROR_MARKER = 'SCRIPT_ERROR';
69
72
  * @param scriptContent The Python script code to execute.
70
73
  * @param codesysExePath The full path to the CODESYS.exe executable (can contain spaces).
71
74
  * @param codesysProfileName The name of the CODESYS profile to use for scripting.
75
+ * @param sessionManager Optional session manager for persistent session execution
72
76
  * @returns A promise resolving to an object containing the success status and the script's output.
73
77
  *
74
78
  * NOTE: Using shell: true with careful command string quoting to handle
75
79
  * CODESYS argument parsing quirks when launched non-interactively.
76
80
  */
77
- function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName) {
81
+ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName, sessionManager) {
78
82
  return __awaiter(this, void 0, void 0, function* () {
79
83
  // --- Pre-checks ---
80
84
  if (!codesysExePath)
@@ -84,6 +88,29 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
84
88
  if (!fs.existsSync(codesysExePath))
85
89
  throw new Error(`CODESYS executable not found at provided path: ${codesysExePath}`);
86
90
  // --- End Pre-checks ---
91
+ // --- Check if we should use the persistent session ---
92
+ if (sessionManager) {
93
+ const sessionState = sessionManager.getState();
94
+ if (sessionState === sessionManager_1.SessionState.RUNNING || sessionState === sessionManager_1.SessionState.BUSY) {
95
+ process.stderr.write(`INTEROP: Using persistent session for script execution\n`);
96
+ try {
97
+ const result = yield sessionManager.executeScript(scriptContent);
98
+ return {
99
+ success: result.success,
100
+ output: result.output
101
+ };
102
+ }
103
+ catch (error) {
104
+ process.stderr.write(`INTEROP: Error executing script in persistent session: ${error.message}\n`);
105
+ process.stderr.write(`INTEROP: Falling back to one-time execution mode\n`);
106
+ // Continue with the non-persistent approach as fallback
107
+ }
108
+ }
109
+ else {
110
+ process.stderr.write(`INTEROP: Session not in RUNNING/BUSY state (current: ${sessionState}). Using one-time execution.\n`);
111
+ }
112
+ }
113
+ // --- Standard one-time script execution ---
87
114
  const tempDir = os.tmpdir();
88
115
  const tempFileName = `codesys_script_${Date.now()}_${Math.random().toString(36).substring(2, 9)}.py`;
89
116
  const tempFilePath = path.join(tempDir, tempFileName); // Path module uses OS-specific separators ('\' on Windows)
@@ -118,7 +145,7 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
118
145
  process.stderr.write(`INTEROP ENV: Forcing CWD for spawn: ${codesysDir}\n`); // Re-enabled CWD change
119
146
  // --- Create modified environment (Re-enabled) ---
120
147
  const spawnEnv = Object.assign({}, process.env);
121
- const pathSeparator = ';'; // Windows
148
+ const pathSeparator = os.platform() === 'win32' ? ';' : ':';
122
149
  const originalPath = spawnEnv.PATH || '';
123
150
  spawnEnv.PATH = `${codesysDir}${pathSeparator}${originalPath}`; // Prepend CODESYS dir to PATH
124
151
  process.stderr.write(`INTEROP ENV: MODIFIED PATH for spawn (prepended): ${spawnEnv.PATH.substring(0, 100)}...\n`); // Re-enabled ENV change
package/dist/server.js CHANGED
@@ -67,6 +67,7 @@ const codesys_interop_1 = require("./codesys_interop");
67
67
  const path = __importStar(require("path"));
68
68
  const promises_1 = require("fs/promises");
69
69
  const scriptLoader_1 = require("./scriptLoader");
70
+ const sessionManager_1 = require("./sessionManager");
70
71
  // --- Wrap server logic in an exported function ---
71
72
  function startMcpServer(config) {
72
73
  return __awaiter(this, void 0, void 0, function* () {
@@ -113,6 +114,10 @@ function startMcpServer(config) {
113
114
  });
114
115
  }
115
116
  // --- End Helper Function ---
117
+ // --- Initialize Session Manager ---
118
+ const sessionManager = new sessionManager_1.CodesysSessionManager(codesysExePath, codesysProfileName);
119
+ console.error('SERVER.TS: Session manager initialized');
120
+ // --- End Session Manager Initialization ---
116
121
  // --- Preload script templates ---
117
122
  try {
118
123
  yield (0, scriptLoader_1.preloadAllScriptTemplates)();
@@ -145,7 +150,7 @@ function startMcpServer(config) {
145
150
  console.error(`SERVER.TS Resource request: ${uri.href}`);
146
151
  try {
147
152
  const scriptContent = yield (0, scriptLoader_1.loadScriptTemplate)('check_status');
148
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
153
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
149
154
  const outputLines = result.output.split(/[\r\n]+/).filter(line => line.trim());
150
155
  const statusData = {};
151
156
  outputLines.forEach(line => {
@@ -191,7 +196,7 @@ function startMcpServer(config) {
191
196
  const scriptContent = (0, scriptLoader_1.interpolateScript)(combinedScript, {
192
197
  'PROJECT_FILE_PATH': absoluteProjPath.replace(/\\/g, '\\\\')
193
198
  });
194
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
199
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
195
200
  let structureText = `Error retrieving structure for ${absoluteProjPath}.\n\n${result.output}`;
196
201
  let isError = !result.success;
197
202
  if (result.success && result.output.includes("SCRIPT_SUCCESS")) {
@@ -248,7 +253,7 @@ function startMcpServer(config) {
248
253
  'PROJECT_FILE_PATH': absoluteProjPath.replace(/\\/g, '\\\\'),
249
254
  'POU_FULL_PATH': sanitizedPouPath
250
255
  });
251
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
256
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
252
257
  let codeText = `Error retrieving code for object '${sanitizedPouPath}' in project '${absoluteProjPath}'.\n\n${result.output}`;
253
258
  let isError = !result.success;
254
259
  if (result.success && result.output.includes("SCRIPT_SUCCESS")) {
@@ -303,7 +308,7 @@ function startMcpServer(config) {
303
308
  const scriptContent = (0, scriptLoader_1.interpolateScript)(combinedScript, {
304
309
  'PROJECT_FILE_PATH': absPath.replace(/\\/g, '\\\\')
305
310
  });
306
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
311
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
307
312
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
308
313
  return {
309
314
  content: [{
@@ -372,7 +377,7 @@ function startMcpServer(config) {
372
377
  'TEMPLATE_PROJECT_PATH': templatePath.replace(/\\/g, '\\\\')
373
378
  });
374
379
  console.error(">>> create_project (copy-then-open): PREPARED SCRIPT:", scriptContent.substring(0, 500) + "...");
375
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
380
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
376
381
  console.error(">>> create_project (copy-then-open): EXECUTION RESULT:", JSON.stringify(result));
377
382
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
378
383
  return {
@@ -405,7 +410,7 @@ function startMcpServer(config) {
405
410
  const scriptContent = (0, scriptLoader_1.interpolateScript)(combinedScript, {
406
411
  'PROJECT_FILE_PATH': absPath.replace(/\\/g, '\\\\')
407
412
  });
408
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
413
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
409
414
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
410
415
  return {
411
416
  content: [{
@@ -449,7 +454,7 @@ function startMcpServer(config) {
449
454
  'PARENT_PATH': sanParentPath
450
455
  });
451
456
  console.error(">>> create_pou: PREPARED SCRIPT:", scriptContent.substring(0, 500) + "...");
452
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
457
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
453
458
  console.error(">>> create_pou: EXECUTION RESULT:", JSON.stringify(result));
454
459
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
455
460
  return {
@@ -500,7 +505,7 @@ function startMcpServer(config) {
500
505
  'IMPLEMENTATION_CONTENT': sanImplCode
501
506
  });
502
507
  console.error(">>> set_pou_code: PREPARED SCRIPT:", scriptContent.substring(0, 500) + "...");
503
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
508
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
504
509
  console.error(">>> set_pou_code: EXECUTION RESULT:", JSON.stringify(result));
505
510
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
506
511
  return {
@@ -550,7 +555,7 @@ function startMcpServer(config) {
550
555
  'PROPERTY_TYPE': sanPropType
551
556
  });
552
557
  console.error(">>> create_property: PREPARED SCRIPT:", scriptContent.substring(0, 500) + "...");
553
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
558
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
554
559
  console.error(">>> create_property: EXECUTION RESULT:", JSON.stringify(result));
555
560
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
556
561
  return {
@@ -600,7 +605,7 @@ function startMcpServer(config) {
600
605
  'RETURN_TYPE': sanReturnType
601
606
  });
602
607
  console.error(">>> create_method: PREPARED SCRIPT:", scriptContent.substring(0, 500) + "...");
603
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
608
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
604
609
  console.error(">>> create_method: EXECUTION RESULT:", JSON.stringify(result));
605
610
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
606
611
  return {
@@ -633,7 +638,7 @@ function startMcpServer(config) {
633
638
  const scriptContent = (0, scriptLoader_1.interpolateScript)(combinedScript, {
634
639
  'PROJECT_FILE_PATH': absPath.replace(/\\/g, '\\\\')
635
640
  });
636
- const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName);
641
+ const result = yield (0, codesys_interop_1.executeCodesysScript)(scriptContent, codesysExePath, codesysProfileName, sessionManager);
637
642
  const success = result.success && result.output.includes("SCRIPT_SUCCESS");
638
643
  // Check for actual compile errors in the output log
639
644
  const hasCompileErrors = result.output.includes("Compile complete --") && !/ 0 error\(s\),/.test(result.output);
@@ -658,6 +663,114 @@ function startMcpServer(config) {
658
663
  };
659
664
  }
660
665
  }));
666
+ // --- Session Management Tools ---
667
+ server.tool("start_session", "Starts a persistent CODESYS session for improved performance with multiple operations", {}, () => __awaiter(this, void 0, void 0, function* () {
668
+ console.error("Tool call: start_session");
669
+ try {
670
+ const currentState = sessionManager.getState();
671
+ if (currentState === sessionManager_1.SessionState.RUNNING || currentState === sessionManager_1.SessionState.BUSY) {
672
+ return {
673
+ content: [{
674
+ type: "text",
675
+ text: "CODESYS session is already running"
676
+ }],
677
+ isError: false
678
+ };
679
+ }
680
+ if (currentState === sessionManager_1.SessionState.STARTING) {
681
+ return {
682
+ content: [{
683
+ type: "text",
684
+ text: "CODESYS session is already starting"
685
+ }],
686
+ isError: false
687
+ };
688
+ }
689
+ yield sessionManager.startSession();
690
+ return {
691
+ content: [{
692
+ type: "text",
693
+ text: "CODESYS session started successfully"
694
+ }],
695
+ isError: false
696
+ };
697
+ }
698
+ catch (error) {
699
+ console.error(`Error starting session: ${error.message}`);
700
+ return {
701
+ content: [{
702
+ type: "text",
703
+ text: `Failed to start CODESYS session: ${error.message}`
704
+ }],
705
+ isError: true
706
+ };
707
+ }
708
+ }));
709
+ server.tool("stop_session", "Stops the persistent CODESYS session", {}, () => __awaiter(this, void 0, void 0, function* () {
710
+ console.error("Tool call: stop_session");
711
+ try {
712
+ const currentState = sessionManager.getState();
713
+ if (currentState === sessionManager_1.SessionState.STOPPED) {
714
+ return {
715
+ content: [{
716
+ type: "text",
717
+ text: "CODESYS session is already stopped"
718
+ }],
719
+ isError: false
720
+ };
721
+ }
722
+ if (currentState === sessionManager_1.SessionState.STOPPING) {
723
+ return {
724
+ content: [{
725
+ type: "text",
726
+ text: "CODESYS session is already stopping"
727
+ }],
728
+ isError: false
729
+ };
730
+ }
731
+ yield sessionManager.stopSession();
732
+ return {
733
+ content: [{
734
+ type: "text",
735
+ text: "CODESYS session stopped successfully"
736
+ }],
737
+ isError: false
738
+ };
739
+ }
740
+ catch (error) {
741
+ console.error(`Error stopping session: ${error.message}`);
742
+ return {
743
+ content: [{
744
+ type: "text",
745
+ text: `Failed to stop CODESYS session: ${error.message}`
746
+ }],
747
+ isError: true
748
+ };
749
+ }
750
+ }));
751
+ server.tool("session_status", "Returns the status of the CODESYS session", {}, () => __awaiter(this, void 0, void 0, function* () {
752
+ console.error("Tool call: session_status");
753
+ try {
754
+ const state = sessionManager.getState();
755
+ return {
756
+ content: [{
757
+ type: "text",
758
+ text: `CODESYS session status: ${state}`
759
+ }],
760
+ isError: false
761
+ };
762
+ }
763
+ catch (error) {
764
+ console.error(`Error getting session status: ${error.message}`);
765
+ return {
766
+ content: [{
767
+ type: "text",
768
+ text: `Failed to get CODESYS session status: ${error.message}`
769
+ }],
770
+ isError: true
771
+ };
772
+ }
773
+ }));
661
774
  // --- End Tools ---
662
775
  console.error("SERVER.TS: Resources and Tools defined.");
663
776
  // --- End MCP Resources / Tools Definitions ---