@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.
- package/.claude/settings.local.json +23 -0
- package/CHANGELOG.md +32 -26
- package/CLAUDE.md +26 -0
- package/CONTRIBUTING.md +72 -72
- package/LICENSE +21 -21
- package/README.md +152 -145
- package/README.md.enhanced +155 -155
- package/codesys-mcp-toolkit-1.2.0.tgz +0 -0
- package/dist/codesys_interop.js +29 -2
- package/dist/server.js +124 -11
- package/dist/sessionManager.js +401 -0
- package/docs/index.md +26 -26
- package/docs/installation.md +84 -84
- package/docs/session_management.md +84 -0
- package/examples/README.md +78 -78
- package/examples/sample_config.json +32 -32
- package/package.json +50 -48
- package/scriptDoc.txt +8679 -8679
package/README.md.enhanced
CHANGED
|
@@ -1,155 +1,155 @@
|
|
|
1
|
-
# @codesys/mcp-toolkit
|
|
2
|
-
|
|
3
|
-

|
|
4
|
-

|
|
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
|
+

|
|
4
|
+

|
|
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
|
package/dist/codesys_interop.js
CHANGED
|
@@ -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 = ';'
|
|
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 ---
|