@codesys/mcp-toolkit 1.0.0 → 1.0.1
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/CHANGELOG.md +26 -0
- package/CONTRIBUTING.md +72 -0
- package/README.md +228 -97
- package/README.md.enhanced +155 -0
- package/dist/codesys_interop - Copy.js +180 -0
- package/dist/codesys_interop.js +47 -53
- package/docs/configuration.md +119 -0
- package/docs/index.md +26 -0
- package/docs/installation.md +84 -0
- package/examples/README.md +78 -0
- package/examples/sample_config.json +32 -0
- package/package.json +4 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2025-04-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of the MCP server for CODESYS
|
|
12
|
+
- Command-line interface with configuration options
|
|
13
|
+
- Project management functionality:
|
|
14
|
+
- Opening existing CODESYS projects
|
|
15
|
+
- Creating new CODESYS projects
|
|
16
|
+
- Saving projects
|
|
17
|
+
- POU (Program Organization Unit) management:
|
|
18
|
+
- Creating POUs (Programs, Function Blocks, Functions)
|
|
19
|
+
- Setting POU code (declaration and implementation)
|
|
20
|
+
- Creating properties and methods for Function Blocks
|
|
21
|
+
- Project compilation support
|
|
22
|
+
- Resources for querying:
|
|
23
|
+
- Project status
|
|
24
|
+
- Project structure
|
|
25
|
+
- POU code
|
|
26
|
+
- Documentation for installation and usage
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Contributing to @codesys/mcp-toolkit
|
|
2
|
+
|
|
3
|
+
Thank you for considering contributing to the CODESYS MCP Toolkit! This document provides guidelines and steps for contributing.
|
|
4
|
+
|
|
5
|
+
## Code of Conduct
|
|
6
|
+
|
|
7
|
+
Please be respectful and considerate of others when contributing to this project. We aim to foster an inclusive and welcoming community.
|
|
8
|
+
|
|
9
|
+
## How Can I Contribute?
|
|
10
|
+
|
|
11
|
+
### Reporting Bugs
|
|
12
|
+
|
|
13
|
+
Bug reports help improve the project! When reporting bugs:
|
|
14
|
+
|
|
15
|
+
1. Check if the bug has already been reported
|
|
16
|
+
2. Use the bug report template
|
|
17
|
+
3. Include detailed steps to reproduce the issue
|
|
18
|
+
4. Describe the expected vs. actual behavior
|
|
19
|
+
5. Include screenshots if applicable
|
|
20
|
+
6. Provide environment details (OS, Node.js version, etc.)
|
|
21
|
+
|
|
22
|
+
### Suggesting Features
|
|
23
|
+
|
|
24
|
+
We welcome feature suggestions! When suggesting features:
|
|
25
|
+
|
|
26
|
+
1. Describe the problem your feature would solve
|
|
27
|
+
2. Explain how your feature would work
|
|
28
|
+
3. Consider potential alternatives
|
|
29
|
+
4. Provide examples of similar features in other projects (if applicable)
|
|
30
|
+
|
|
31
|
+
### Pull Requests
|
|
32
|
+
|
|
33
|
+
1. Fork the repository
|
|
34
|
+
2. Create a feature branch (`git checkout -b feature/amazing-feature`)
|
|
35
|
+
3. Make your changes
|
|
36
|
+
4. Run tests and ensure they pass
|
|
37
|
+
5. Commit your changes (`git commit -m 'Add amazing feature'`)
|
|
38
|
+
6. Push to your branch (`git push origin feature/amazing-feature`)
|
|
39
|
+
7. Open a Pull Request
|
|
40
|
+
|
|
41
|
+
## Development Setup
|
|
42
|
+
|
|
43
|
+
1. Clone the repository
|
|
44
|
+
```bash
|
|
45
|
+
git clone https://github.com/yourusername/codesys-mcp-toolkit.git
|
|
46
|
+
cd codesys-mcp-toolkit
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
2. Install dependencies
|
|
50
|
+
```bash
|
|
51
|
+
npm install
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
3. Build the project
|
|
55
|
+
```bash
|
|
56
|
+
npm run build
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Style Guidelines
|
|
60
|
+
|
|
61
|
+
- Follow existing code formatting patterns
|
|
62
|
+
- Use meaningful variable and function names
|
|
63
|
+
- Add comments where necessary to explain complex logic
|
|
64
|
+
- Update documentation when changing functionality
|
|
65
|
+
|
|
66
|
+
## Testing
|
|
67
|
+
|
|
68
|
+
- Add tests for new features
|
|
69
|
+
- Ensure all tests pass before submitting a PR
|
|
70
|
+
- Consider edge cases in your tests
|
|
71
|
+
|
|
72
|
+
Thank you for contributing!
|
package/README.md
CHANGED
|
@@ -1,30 +1,45 @@
|
|
|
1
1
|
# @codesys/mcp-toolkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+

|
|
4
|
+

|
|
4
5
|
|
|
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.
|
|
6
7
|
|
|
7
|
-
|
|
8
|
+
## 🌟 Features
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* **Tools:**
|
|
14
|
-
* `open_project`: Opens a specified CODESYS project file (`.project`).
|
|
15
|
-
* `create_project`: Creates a new CODESYS project file (`.project`), optionally from a template.
|
|
16
|
-
* `save_project`: Saves the currently open CODESYS project.
|
|
17
|
-
* `create_pou`: Creates a new POU (Program, Function Block, Function) with a specified language under a parent object in the project tree.
|
|
18
|
-
* `add_code`: Sets the implementation code for a specified POU.
|
|
19
|
-
* `compile_project`: Initiates the compilation of the open project.
|
|
10
|
+
- **Project Management**
|
|
11
|
+
- Open existing CODESYS projects
|
|
12
|
+
- Create new projects from templates
|
|
13
|
+
- Save project changes
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
- **POU Management**
|
|
16
|
+
- Create Programs, Function Blocks, and Functions
|
|
17
|
+
- Set declaration and implementation code
|
|
18
|
+
- Create properties and methods for Function Blocks
|
|
19
|
+
- Compile projects
|
|
22
20
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
- **MCP Resources**
|
|
22
|
+
- `codesys://project/status`: Check scripting status and project state
|
|
23
|
+
- `codesys://project/{+project_path}/structure`: Retrieve project structure
|
|
24
|
+
- `codesys://project/{+project_path}/pou/{+pou_path}/code`: Read POU code
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
- **MCP Tools**
|
|
27
|
+
- `open_project`: Open specified CODESYS project
|
|
28
|
+
- `create_project`: Create new CODESYS project
|
|
29
|
+
- `save_project`: Save currently open project
|
|
30
|
+
- `create_pou`: Create new Program, Function Block, or Function
|
|
31
|
+
- `set_pou_code`: Update code for a specified POU
|
|
32
|
+
- `create_property`: Create property in a Function Block
|
|
33
|
+
- `create_method`: Create method in a Function Block
|
|
34
|
+
- `compile_project`: Compile the open project
|
|
35
|
+
|
|
36
|
+
## 📋 Prerequisites
|
|
37
|
+
|
|
38
|
+
- **CODESYS V3**: A working CODESYS V3 installation (tested with 3.5 SP21) with **Scripting Engine** component enabled
|
|
39
|
+
- **Node.js**: Version 18 or later required
|
|
40
|
+
- **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
|
|
41
|
+
|
|
42
|
+
## 🚀 Installation
|
|
28
43
|
|
|
29
44
|
### Option 1: Install from npm (Recommended)
|
|
30
45
|
|
|
@@ -32,92 +47,208 @@ Currently implemented features:
|
|
|
32
47
|
npm install -g @codesys/mcp-toolkit
|
|
33
48
|
```
|
|
34
49
|
|
|
35
|
-
This
|
|
50
|
+
This installs the package globally, making the `codesys-mcp-toolkit` command available in your terminal.
|
|
36
51
|
|
|
37
52
|
### Option 2: Install from Source
|
|
38
53
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
```bash
|
|
55
|
+
# Clone the repository
|
|
56
|
+
git clone https://github.com/johannesPettersson80/codesys-mcp-toolkit.git
|
|
57
|
+
cd codesys-mcp-toolkit
|
|
58
|
+
|
|
59
|
+
# Install dependencies
|
|
60
|
+
npm install
|
|
61
|
+
|
|
62
|
+
# Build the project
|
|
63
|
+
npm run build
|
|
64
|
+
|
|
65
|
+
# Install globally
|
|
66
|
+
npm install -g .
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## 🔧 Configuration
|
|
70
|
+
|
|
71
|
+
### Claude Desktop Configuration
|
|
72
|
+
|
|
73
|
+
1. Locate your Claude Desktop configuration file:
|
|
74
|
+
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
|
|
75
|
+
|
|
76
|
+
2. Add the CODESYS MCP server entry:
|
|
77
|
+
|
|
78
|
+
```json
|
|
79
|
+
{
|
|
80
|
+
"mcpServers": {
|
|
81
|
+
"codesys_local": {
|
|
82
|
+
"command": "npx",
|
|
83
|
+
"args": [
|
|
84
|
+
"-y",
|
|
85
|
+
"@codesys/mcp-toolkit",
|
|
86
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
87
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
88
|
+
]
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
3. Customize the paths to match your CODESYS installation:
|
|
95
|
+
- `--codesys-path`: Path to your CODESYS.exe
|
|
96
|
+
- `--codesys-profile`: Your CODESYS profile name
|
|
97
|
+
|
|
98
|
+
4. Restart Claude Desktop to apply the changes
|
|
99
|
+
|
|
100
|
+
## 🛠️ Usage Examples
|
|
101
|
+
|
|
102
|
+
### Creating a Function Block with Properties
|
|
103
|
+
|
|
104
|
+
```
|
|
105
|
+
Ask Claude: "Using the CODESYS Local server, please create a Motor Controller function block with Start and Stop methods, plus CurrentSpeed property."
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Claude will execute these MCP tool calls:
|
|
109
|
+
1. `create_pou` to create the MotorController Function Block
|
|
110
|
+
2. `create_property` to add the CurrentSpeed property
|
|
111
|
+
3. `create_method` to add Start and Stop methods
|
|
112
|
+
4. `set_pou_code` to implement each method and property
|
|
113
|
+
|
|
114
|
+
### Opening and Compiling a Project
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
Ask Claude: "Can you open the project at C:/MyProjects/TestProject.project using CODESYS Local and compile it?"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Claude will:
|
|
121
|
+
1. Use `open_project` to open the specified file
|
|
122
|
+
2. Use `compile_project` to build the application
|
|
123
|
+
|
|
124
|
+
## 🔍 Troubleshooting
|
|
125
|
+
|
|
126
|
+
### Common Issues
|
|
127
|
+
|
|
128
|
+
- **Connection Failures**: Check Claude Desktop logs for error messages
|
|
129
|
+
- **Path Issues**: Ensure CODESYS executable path is correct
|
|
130
|
+
- **Profile Mismatch**: Verify profile name matches exactly
|
|
131
|
+
- **Permission Problems**: Ensure Claude has appropriate permissions
|
|
132
|
+
- **CODESYS Already Running**: Close other CODESYS instances
|
|
133
|
+
|
|
134
|
+
### Debug Logs
|
|
135
|
+
|
|
136
|
+
Check logs at:
|
|
137
|
+
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\logs\`
|
|
138
|
+
|
|
139
|
+
## 📖 Detailed OOP Workflow Guide
|
|
140
|
+
|
|
141
|
+
When creating object-oriented structures with this toolkit, follow this step-by-step workflow for best results:
|
|
142
|
+
|
|
143
|
+
### Creating Function Blocks with Properties and Methods
|
|
144
|
+
|
|
145
|
+
1. **Create the Function Block**
|
|
146
|
+
```
|
|
147
|
+
create_pou(
|
|
148
|
+
projectFilePath: "path/to/project.project",
|
|
149
|
+
name: "PumpController",
|
|
150
|
+
type: "FunctionBlock",
|
|
151
|
+
language: "ST",
|
|
152
|
+
parentPath: "Application"
|
|
153
|
+
)
|
|
43
154
|
```
|
|
44
155
|
|
|
45
|
-
2. **
|
|
46
|
-
```
|
|
47
|
-
|
|
156
|
+
2. **Create Properties**
|
|
157
|
+
```
|
|
158
|
+
create_property(
|
|
159
|
+
projectFilePath: "path/to/project.project",
|
|
160
|
+
parentPouPath: "Application/PumpController",
|
|
161
|
+
propertyName: "SpeedSetpoint",
|
|
162
|
+
propertyType: "INT"
|
|
163
|
+
)
|
|
48
164
|
```
|
|
49
165
|
|
|
50
|
-
3. **
|
|
51
|
-
```
|
|
52
|
-
|
|
166
|
+
3. **Create Methods**
|
|
167
|
+
```
|
|
168
|
+
create_method(
|
|
169
|
+
projectFilePath: "path/to/project.project",
|
|
170
|
+
parentPouPath: "Application/PumpController",
|
|
171
|
+
methodName: "Start",
|
|
172
|
+
returnType: "" // Empty for no return value
|
|
173
|
+
)
|
|
53
174
|
```
|
|
54
175
|
|
|
55
|
-
4. **
|
|
56
|
-
```
|
|
57
|
-
|
|
176
|
+
4. **Implement Methods**
|
|
177
|
+
```
|
|
178
|
+
set_pou_code(
|
|
179
|
+
projectFilePath: "path/to/project.project",
|
|
180
|
+
pouPath: "Application/PumpController/Start",
|
|
181
|
+
implementationCode: "isRunning := TRUE;"
|
|
182
|
+
)
|
|
58
183
|
```
|
|
59
184
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
185
|
+
5. **Declare Backing Variables**
|
|
186
|
+
```
|
|
187
|
+
set_pou_code(
|
|
188
|
+
projectFilePath: "path/to/project.project",
|
|
189
|
+
pouPath: "Application/PumpController",
|
|
190
|
+
declarationCode: "VAR PRIVATE\n _speedSetpoint : INT;\n _isRunning : BOOL;\nEND_VAR"
|
|
191
|
+
)
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
6. **Implement Property Accessors**
|
|
195
|
+
- For GET accessor:
|
|
196
|
+
```
|
|
197
|
+
set_pou_code(
|
|
198
|
+
projectFilePath: "path/to/project.project",
|
|
199
|
+
pouPath: "Application/PumpController/SpeedSetpoint/Get",
|
|
200
|
+
implementationCode: "SpeedSetpoint := _speedSetpoint;"
|
|
201
|
+
)
|
|
202
|
+
```
|
|
203
|
+
- For SET accessor:
|
|
204
|
+
```
|
|
205
|
+
set_pou_code(
|
|
206
|
+
projectFilePath: "path/to/project.project",
|
|
207
|
+
pouPath: "Application/PumpController/SpeedSetpoint/Set",
|
|
208
|
+
implementationCode: "_speedSetpoint := SpeedSetpoint;"
|
|
209
|
+
)
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
7. **Save Project**
|
|
213
|
+
```
|
|
214
|
+
save_project(
|
|
215
|
+
projectFilePath: "path/to/project.project"
|
|
216
|
+
)
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Important Path Usage Notes
|
|
220
|
+
|
|
221
|
+
- Use forward slashes (`/`) in all object paths
|
|
222
|
+
- Ensure paths are precise and target the specific object
|
|
223
|
+
- For property accessors, always specify the full path including `/Get` or `/Set`
|
|
224
|
+
|
|
225
|
+
### CODESYS Naming Conventions
|
|
226
|
+
|
|
227
|
+
- **POUs** (Programs, FBs, Functions): PascalCase (e.g., `MotorControl`)
|
|
228
|
+
- **Interfaces**: PascalCase with I_ prefix (e.g., `I_AxisCommands`)
|
|
229
|
+
- **DUTs** (Structs, Enums): PascalCase (e.g., `MachineState`, `E_OperationMode`)
|
|
230
|
+
- **Variables**: camelCase (e.g., `motorSpeed`)
|
|
231
|
+
- **Backing variables**: camelCase with _ prefix (e.g., `_speedSetpoint`)
|
|
232
|
+
- **Constants**: UPPER_SNAKE_CASE (e.g., `MAX_RPM`)
|
|
233
|
+
- **Properties & Methods**: PascalCase with descriptive names
|
|
234
|
+
|
|
235
|
+
### Recommended Property Naming
|
|
236
|
+
|
|
237
|
+
- Control values: Add `Setpoint` suffix (e.g., `SpeedSetpoint`)
|
|
238
|
+
- Measured values: Add `Actual` suffix (e.g., `TemperatureActual`)
|
|
239
|
+
- Status indicators: Use `Is` or `Has` prefix (e.g., `IsRunning`, `HasError`)
|
|
240
|
+
- Configuration: Use descriptive prefixes (e.g., `MaxSpeed`, `MinPressure`)
|
|
241
|
+
|
|
242
|
+
## 🤝 Contributing
|
|
243
|
+
|
|
244
|
+
Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.
|
|
245
|
+
|
|
246
|
+
## 📝 License
|
|
247
|
+
|
|
248
|
+
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
249
|
+
|
|
250
|
+
## 🙏 Acknowledgements
|
|
251
|
+
|
|
252
|
+
- The [CODESYS](https://www.codesys.com/) team for their scripting engine
|
|
253
|
+
- [Model Context Protocol](https://github.com/m-ld/model-context-protocol) project
|
|
254
|
+
- All contributors who have helped improve this toolkit
|
|
@@ -0,0 +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
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
36
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
37
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
38
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
39
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
40
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
41
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
42
|
+
});
|
|
43
|
+
};
|
|
44
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
|
+
exports.executeCodesysScript = executeCodesysScript;
|
|
46
|
+
const child_process_1 = require("child_process");
|
|
47
|
+
const promises_1 = require("fs/promises");
|
|
48
|
+
const path = __importStar(require("path"));
|
|
49
|
+
const os = __importStar(require("os"));
|
|
50
|
+
// Define expected success/error markers from the Python scripts
|
|
51
|
+
const SCRIPT_SUCCESS_MARKER = 'SCRIPT_SUCCESS';
|
|
52
|
+
const SCRIPT_ERROR_MARKER = 'SCRIPT_ERROR';
|
|
53
|
+
/**
|
|
54
|
+
* Executes a CODESYS Python script using the command line interface.
|
|
55
|
+
*
|
|
56
|
+
* @param scriptContent The Python script code to execute.
|
|
57
|
+
* @param codesysExePath The full path to the CODESYS.exe executable.
|
|
58
|
+
* @param codesysProfileName The name of the CODESYS profile to use for scripting.
|
|
59
|
+
* @returns A promise resolving to an object containing the success status and the script's output.
|
|
60
|
+
*/
|
|
61
|
+
function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName) {
|
|
62
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
63
|
+
// Validate arguments passed to the function
|
|
64
|
+
if (!codesysExePath) {
|
|
65
|
+
throw new Error('CODESYS executable path was not provided to executeCodesysScript.');
|
|
66
|
+
}
|
|
67
|
+
if (!codesysProfileName) {
|
|
68
|
+
throw new Error('CODESYS profile name was not provided to executeCodesysScript.');
|
|
69
|
+
}
|
|
70
|
+
// Create a temporary file for the script
|
|
71
|
+
const tempDir = os.tmpdir();
|
|
72
|
+
const tempFileName = `codesys_script_${Date.now()}_${Math.random().toString(36).substring(7)}.py`;
|
|
73
|
+
const tempFilePath = path.join(tempDir, tempFileName);
|
|
74
|
+
let output = '';
|
|
75
|
+
let success = false;
|
|
76
|
+
try {
|
|
77
|
+
// Normalize line endings to LF (\n)
|
|
78
|
+
const normalizedScriptContent = scriptContent.replace(/\r\n/g, '\n');
|
|
79
|
+
// Write the script content to the temporary file using latin1 encoding
|
|
80
|
+
yield (0, promises_1.writeFile)(tempFilePath, normalizedScriptContent, 'latin1'); // Explicitly use latin1
|
|
81
|
+
process.stderr.write(`Temporary script written to: ${tempFilePath} with latin1 encoding and LF line endings\n`); // Use process.stderr
|
|
82
|
+
// Add --additionalfolder argument
|
|
83
|
+
const additionalFolderPath = "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\AdditionalFolders\\Default"; // Assuming Default instance
|
|
84
|
+
// Fix: Use shell:true and pass the entire command as a single string without additionalfolder
|
|
85
|
+
const commandWithArgs = `"${codesysExePath}" --profile="${codesysProfileName}" --noUI --runscript="${tempFilePath}"`;
|
|
86
|
+
process.stderr.write(`Executing: ${commandWithArgs}\n`); // Log the command string
|
|
87
|
+
// Spawn the CODESYS process using shell:true for proper argument handling
|
|
88
|
+
const codesysProcess = (0, child_process_1.spawn)(commandWithArgs, {
|
|
89
|
+
stdio: ['ignore', 'pipe', 'pipe'], // Ignore stdin, pipe stdout and stderr
|
|
90
|
+
shell: true // Use shell to handle the command string properly
|
|
91
|
+
});
|
|
92
|
+
// Capture stdout
|
|
93
|
+
codesysProcess.stdout.on('data', (data) => {
|
|
94
|
+
const chunk = data.toString();
|
|
95
|
+
// console.error('CODESYS stdout:', chunk); // Optional: Original debug log
|
|
96
|
+
output += chunk;
|
|
97
|
+
});
|
|
98
|
+
// Capture stderr
|
|
99
|
+
codesysProcess.stderr.on('data', (data) => {
|
|
100
|
+
const chunk = data.toString();
|
|
101
|
+
process.stderr.write(`CODESYS stderr: ${chunk}\n`); // Use process.stderr
|
|
102
|
+
output += chunk; // Include stderr in the output for debugging
|
|
103
|
+
});
|
|
104
|
+
// Wait for the process to exit with a timeout
|
|
105
|
+
const exitCode = yield new Promise((resolve, reject) => {
|
|
106
|
+
// Add timeout handling
|
|
107
|
+
const timeoutMs = 30000; // 30 seconds
|
|
108
|
+
const timeout = setTimeout(() => {
|
|
109
|
+
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms\n`);
|
|
110
|
+
// Force resolve with 0 to proceed with parsing output collected so far
|
|
111
|
+
codesysProcess.kill();
|
|
112
|
+
resolve(0);
|
|
113
|
+
}, timeoutMs);
|
|
114
|
+
codesysProcess.on('close', (code) => {
|
|
115
|
+
clearTimeout(timeout);
|
|
116
|
+
resolve(code !== null && code !== void 0 ? code : 0);
|
|
117
|
+
});
|
|
118
|
+
codesysProcess.on('error', (err) => {
|
|
119
|
+
clearTimeout(timeout);
|
|
120
|
+
// Error starting the process itself (e.g., command not found)
|
|
121
|
+
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`); // Use process.stderr
|
|
122
|
+
reject(err);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`); // Use process.stderr
|
|
126
|
+
// Determine success based on exit code and output markers
|
|
127
|
+
// Note: CODESYS scripting might return exit code 0 even if the script had logical errors.
|
|
128
|
+
// Relying on specific output markers is more robust.
|
|
129
|
+
if (output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
130
|
+
success = true;
|
|
131
|
+
}
|
|
132
|
+
else if (output.includes(SCRIPT_ERROR_MARKER)) {
|
|
133
|
+
success = false;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
// If no markers found, fall back to exit code (less reliable)
|
|
137
|
+
success = exitCode === 0;
|
|
138
|
+
if (!success) {
|
|
139
|
+
// Append the specific CODESYS error if available and no other marker found
|
|
140
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
141
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}. Check CODESYS stderr output above for details.`;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}.`;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
// If exit code is 0 but no success marker, treat as potential issue or simple script
|
|
149
|
+
console.error("Warning: CODESYS script finished with exit code 0 but no SCRIPT_SUCCESS marker found."); // Log warning to stderr
|
|
150
|
+
// Optionally, you could treat this as success or failure depending on requirements
|
|
151
|
+
// For now, let's assume success if exit code is 0 and no error marker.
|
|
152
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
153
|
+
success = true;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
process.stderr.write(`Error executing CODESYS script: ${error}\n`); // Use process.stderr
|
|
160
|
+
output += `\nSCRIPT_ERROR: Failed to execute script process. ${error.message}`;
|
|
161
|
+
success = false;
|
|
162
|
+
}
|
|
163
|
+
finally {
|
|
164
|
+
// Clean up the temporary file
|
|
165
|
+
try {
|
|
166
|
+
yield (0, promises_1.unlink)(tempFilePath);
|
|
167
|
+
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`); // Use process.stderr
|
|
168
|
+
}
|
|
169
|
+
catch (cleanupError) {
|
|
170
|
+
process.stderr.write(`Failed to delete temporary script file ${tempFilePath}: ${cleanupError}\n`); // Use process.stderr
|
|
171
|
+
// Don't overwrite the original error if cleanup fails
|
|
172
|
+
if (success) { // Only add cleanup error if the main process didn't already fail
|
|
173
|
+
output += `\nWARNING: Failed to delete temporary script file ${tempFilePath}. ${cleanupError.message}`;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
process.stderr.write(`Final script output received:\n---\n${output}\n---\n`); // Use process.stderr
|
|
178
|
+
return { success, output }; // Revert return object
|
|
179
|
+
});
|
|
180
|
+
}
|
package/dist/codesys_interop.js
CHANGED
|
@@ -73,90 +73,85 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
73
73
|
const tempFilePath = path.join(tempDir, tempFileName);
|
|
74
74
|
let output = '';
|
|
75
75
|
let success = false;
|
|
76
|
+
// Define timeout duration *before* the promise
|
|
77
|
+
const timeoutMs = 60000; // Increased timeout to 60 seconds (accessible below)
|
|
76
78
|
try {
|
|
77
79
|
// Normalize line endings to LF (\n)
|
|
78
80
|
const normalizedScriptContent = scriptContent.replace(/\r\n/g, '\n');
|
|
79
81
|
// Write the script content to the temporary file using latin1 encoding
|
|
80
82
|
yield (0, promises_1.writeFile)(tempFilePath, normalizedScriptContent, 'latin1'); // Explicitly use latin1
|
|
81
|
-
process.stderr.write(`Temporary script written to: ${tempFilePath} with latin1 encoding and LF line endings\n`);
|
|
82
|
-
//
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
83
|
+
process.stderr.write(`Temporary script written to: ${tempFilePath} with latin1 encoding and LF line endings\n`);
|
|
84
|
+
// Arguments for CODESYS.exe
|
|
85
|
+
const argsArray = [
|
|
86
|
+
`--profile=${codesysProfileName}`,
|
|
87
|
+
`--noUI`,
|
|
88
|
+
`--runscript=${tempFilePath}`
|
|
89
|
+
];
|
|
90
|
+
process.stderr.write(`Executing: "${codesysExePath}" with args: ${JSON.stringify(argsArray)}\n`);
|
|
91
|
+
// Spawn the CODESYS process WITHOUT shell:true for the main command
|
|
92
|
+
const codesysProcess = (0, child_process_1.spawn)(codesysExePath, argsArray, {
|
|
93
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
94
|
+
shell: false
|
|
91
95
|
});
|
|
92
|
-
// Capture stdout
|
|
96
|
+
// Capture stdout & stderr
|
|
93
97
|
codesysProcess.stdout.on('data', (data) => {
|
|
94
98
|
const chunk = data.toString();
|
|
95
|
-
// console.error('CODESYS stdout:', chunk); // Optional: Original debug log
|
|
96
99
|
output += chunk;
|
|
97
100
|
});
|
|
98
|
-
// Capture stderr
|
|
99
101
|
codesysProcess.stderr.on('data', (data) => {
|
|
100
102
|
const chunk = data.toString();
|
|
101
|
-
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
102
|
-
output += chunk;
|
|
103
|
+
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
104
|
+
output += chunk;
|
|
103
105
|
});
|
|
104
106
|
// Wait for the process to exit with a timeout
|
|
105
107
|
const exitCode = yield new Promise((resolve, reject) => {
|
|
106
|
-
//
|
|
107
|
-
const timeoutMs = 30000; // 30 seconds
|
|
108
|
+
// Note: timeoutMs is now defined in the outer scope
|
|
108
109
|
const timeout = setTimeout(() => {
|
|
109
|
-
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
110
|
+
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms. Killing process.\n`);
|
|
111
|
+
codesysProcess.kill('SIGTERM');
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
if (!codesysProcess.killed) {
|
|
114
|
+
process.stderr.write('Force killing CODESYS process after timeout.\n');
|
|
115
|
+
codesysProcess.kill('SIGKILL');
|
|
116
|
+
}
|
|
117
|
+
}, 2000);
|
|
118
|
+
resolve(999); // Use a distinct code for timeout
|
|
119
|
+
}, timeoutMs); // Use timeoutMs here
|
|
114
120
|
codesysProcess.on('close', (code) => {
|
|
115
121
|
clearTimeout(timeout);
|
|
116
122
|
resolve(code !== null && code !== void 0 ? code : 0);
|
|
117
123
|
});
|
|
118
124
|
codesysProcess.on('error', (err) => {
|
|
119
125
|
clearTimeout(timeout);
|
|
120
|
-
|
|
121
|
-
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`); // Use process.stderr
|
|
126
|
+
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`);
|
|
122
127
|
reject(err);
|
|
123
128
|
});
|
|
124
129
|
});
|
|
125
|
-
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
130
|
+
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
126
131
|
// Determine success based on exit code and output markers
|
|
127
|
-
// Note: CODESYS scripting might return exit code 0 even if the script had logical errors.
|
|
128
|
-
// Relying on specific output markers is more robust.
|
|
129
132
|
if (output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
130
133
|
success = true;
|
|
131
134
|
}
|
|
132
135
|
else if (output.includes(SCRIPT_ERROR_MARKER)) {
|
|
133
136
|
success = false;
|
|
134
137
|
}
|
|
135
|
-
else {
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}. Check CODESYS stderr output above for details.`;
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
output += `\nSCRIPT_ERROR: Process exited with non-zero code ${exitCode}.`;
|
|
145
|
-
}
|
|
138
|
+
else if (exitCode !== 0) {
|
|
139
|
+
success = false;
|
|
140
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
141
|
+
// Use timeoutMs from outer scope here - NOW IT WORKS!
|
|
142
|
+
const exitReason = exitCode === 999 ? `due to timeout (${timeoutMs}ms)` : `with non-zero code ${exitCode}`;
|
|
143
|
+
output += `\nSCRIPT_ERROR: Process exited ${exitReason}. Check CODESYS stderr output above for details.`;
|
|
146
144
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
// For now, let's assume success if exit code is 0 and no error marker.
|
|
152
|
-
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
153
|
-
success = true;
|
|
154
|
-
}
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
if (!output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
148
|
+
process.stderr.write("Warning: CODESYS script finished with exit code 0 but no SCRIPT_SUCCESS marker found.\n");
|
|
155
149
|
}
|
|
150
|
+
success = true;
|
|
156
151
|
}
|
|
157
152
|
}
|
|
158
153
|
catch (error) {
|
|
159
|
-
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
154
|
+
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
160
155
|
output += `\nSCRIPT_ERROR: Failed to execute script process. ${error.message}`;
|
|
161
156
|
success = false;
|
|
162
157
|
}
|
|
@@ -164,17 +159,16 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
164
159
|
// Clean up the temporary file
|
|
165
160
|
try {
|
|
166
161
|
yield (0, promises_1.unlink)(tempFilePath);
|
|
167
|
-
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
162
|
+
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
168
163
|
}
|
|
169
164
|
catch (cleanupError) {
|
|
170
|
-
process.stderr.write(`Failed to delete temporary script file ${tempFilePath}: ${cleanupError}\n`);
|
|
171
|
-
|
|
172
|
-
if (success) { // Only add cleanup error if the main process didn't already fail
|
|
165
|
+
process.stderr.write(`Warning: Failed to delete temporary script file ${tempFilePath}: ${cleanupError.message}\n`);
|
|
166
|
+
if (success) {
|
|
173
167
|
output += `\nWARNING: Failed to delete temporary script file ${tempFilePath}. ${cleanupError.message}`;
|
|
174
168
|
}
|
|
175
169
|
}
|
|
176
170
|
}
|
|
177
|
-
process.stderr.write(`Final script output received:\n---\n${output}\n---\n`);
|
|
178
|
-
return { success, output };
|
|
171
|
+
// process.stderr.write(`Final script output received:\n---\n${output}\n---\n`);
|
|
172
|
+
return { success, output };
|
|
179
173
|
});
|
|
180
174
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# Configuration Guide
|
|
2
|
+
|
|
3
|
+
This guide explains how to configure the CODESYS MCP Toolkit with MCP clients.
|
|
4
|
+
|
|
5
|
+
## Claude Desktop Configuration
|
|
6
|
+
|
|
7
|
+
Claude Desktop is a popular MCP client that can use the CODESYS MCP Toolkit.
|
|
8
|
+
|
|
9
|
+
### Finding the Configuration File
|
|
10
|
+
|
|
11
|
+
The configuration file is located at:
|
|
12
|
+
- Windows: `C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
|
|
13
|
+
- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
14
|
+
|
|
15
|
+
### Adding the CODESYS MCP Server Entry
|
|
16
|
+
|
|
17
|
+
Edit the configuration file and add the CODESYS MCP server to the `mcpServers` object:
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"codesys_local": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": [
|
|
25
|
+
"-y",
|
|
26
|
+
"@codesys/mcp-toolkit",
|
|
27
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
28
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Configuration Parameters
|
|
36
|
+
|
|
37
|
+
- `command`: Use `npx` to execute the package
|
|
38
|
+
- `args`: Array of arguments
|
|
39
|
+
- `-y`: Automatically accept npm install prompts
|
|
40
|
+
- `@codesys/mcp-toolkit`: The package name
|
|
41
|
+
- `--codesys-path`: Path to your CODESYS.exe
|
|
42
|
+
- `--codesys-profile`: Your CODESYS profile name
|
|
43
|
+
|
|
44
|
+
### Customizing for Your Environment
|
|
45
|
+
|
|
46
|
+
You must customize:
|
|
47
|
+
1. `--codesys-path`: Set to the actual path of your CODESYS executable
|
|
48
|
+
2. `--codesys-profile`: Set to the exact name of your CODESYS profile
|
|
49
|
+
|
|
50
|
+
**Important Notes:**
|
|
51
|
+
- Use double backslashes (`\\`) in Windows paths in JSON
|
|
52
|
+
- The profile name must match exactly what appears in CODESYS
|
|
53
|
+
|
|
54
|
+
### Applying Changes
|
|
55
|
+
|
|
56
|
+
After modifying the configuration:
|
|
57
|
+
1. Save the file
|
|
58
|
+
2. Restart Claude Desktop completely
|
|
59
|
+
3. Claude should now have access to the CODESYS MCP server
|
|
60
|
+
|
|
61
|
+
## Command-Line Options
|
|
62
|
+
|
|
63
|
+
When using the toolkit directly, the following options are available:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Usage: codesys-mcp-toolkit [options]
|
|
67
|
+
|
|
68
|
+
Options:
|
|
69
|
+
-V, --version output the version number
|
|
70
|
+
-e, --codesys-path <path> Path to CODESYS executable
|
|
71
|
+
-p, --codesys-profile <profile> CODESYS profile name
|
|
72
|
+
-h, --help display help for command
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Verifying Configuration
|
|
76
|
+
|
|
77
|
+
To verify your configuration:
|
|
78
|
+
|
|
79
|
+
1. In Claude Desktop, ask:
|
|
80
|
+
```
|
|
81
|
+
Can you please check the status of the CODESYS Local server?
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
2. Claude should use the `project-status` resource and return information about the CODESYS server connection.
|
|
85
|
+
|
|
86
|
+
## Multiple CODESYS Installations
|
|
87
|
+
|
|
88
|
+
If you have multiple CODESYS installations, you can create multiple server entries with different names:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"mcpServers": {
|
|
93
|
+
"codesys_3_5_21": {
|
|
94
|
+
"command": "npx",
|
|
95
|
+
"args": [
|
|
96
|
+
"-y",
|
|
97
|
+
"@codesys/mcp-toolkit",
|
|
98
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
99
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
"codesys_3_5_19": {
|
|
103
|
+
"command": "npx",
|
|
104
|
+
"args": [
|
|
105
|
+
"-y",
|
|
106
|
+
"@codesys/mcp-toolkit",
|
|
107
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.19.0\\CODESYS\\Common\\CODESYS.exe",
|
|
108
|
+
"--codesys-profile", "CODESYS V3.5 SP19"
|
|
109
|
+
]
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Next Steps
|
|
116
|
+
|
|
117
|
+
- Try some [basic examples](examples.md)
|
|
118
|
+
- Learn about the [available tools and resources](api.md)
|
|
119
|
+
- Check the [troubleshooting guide](troubleshooting.md) if you encounter issues
|
package/docs/index.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# CODESYS MCP Toolkit Documentation
|
|
2
|
+
|
|
3
|
+
Welcome to the documentation for the CODESYS MCP Toolkit!
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The CODESYS MCP Toolkit provides a bridge between Model Context Protocol (MCP) clients and CODESYS V3 programming environments. This toolkit enables seamless interaction for automating project management, POU creation, code editing, and compilation tasks.
|
|
8
|
+
|
|
9
|
+
## Components
|
|
10
|
+
|
|
11
|
+
- **MCP Server**: Core component that handles MCP protocol communication
|
|
12
|
+
- **CODESYS Script Integration**: Interface with CODESYS scripting engine
|
|
13
|
+
- **Command-Line Interface**: For direct usage and configuration
|
|
14
|
+
|
|
15
|
+
## Getting Started
|
|
16
|
+
|
|
17
|
+
- [Installation](installation.md)
|
|
18
|
+
- [Configuration](configuration.md)
|
|
19
|
+
- [Usage Examples](examples.md)
|
|
20
|
+
- [API Reference](api.md)
|
|
21
|
+
|
|
22
|
+
## Advanced Topics
|
|
23
|
+
|
|
24
|
+
- [Contributing Guidelines](../CONTRIBUTING.md)
|
|
25
|
+
- [Troubleshooting](troubleshooting.md)
|
|
26
|
+
- [Custom Extensions](extensions.md)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Installation Guide
|
|
2
|
+
|
|
3
|
+
This guide covers how to install the CODESYS MCP Toolkit on your system.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
Before installing, ensure you have:
|
|
8
|
+
|
|
9
|
+
1. **Node.js**: Version 18 or later
|
|
10
|
+
- Download from [nodejs.org](https://nodejs.org/)
|
|
11
|
+
- Verify installation with `node --version`
|
|
12
|
+
|
|
13
|
+
2. **CODESYS V3**: A working CODESYS V3 installation
|
|
14
|
+
- Tested with version 3.5 SP21
|
|
15
|
+
- Must have the **Scripting Engine** component enabled
|
|
16
|
+
- Verify by opening CODESYS and checking if scripting commands are available
|
|
17
|
+
|
|
18
|
+
3. **MCP Client**: An MCP-enabled application (e.g., Claude Desktop)
|
|
19
|
+
|
|
20
|
+
## Installation Methods
|
|
21
|
+
|
|
22
|
+
### Method 1: Install from npm (Recommended)
|
|
23
|
+
|
|
24
|
+
The simplest way to install is directly from npm:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
npm install -g @codesys/mcp-toolkit
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
This installs the package globally on your system, making the `codesys-mcp-toolkit` command available in your terminal.
|
|
31
|
+
|
|
32
|
+
Verify the installation by running:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
codesys-mcp-toolkit --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
### Method 2: Install from Source
|
|
39
|
+
|
|
40
|
+
For development or to get the latest unreleased changes:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
# Clone the repository
|
|
44
|
+
git clone https://github.com/yourusername/codesys-mcp-toolkit.git
|
|
45
|
+
cd codesys-mcp-toolkit
|
|
46
|
+
|
|
47
|
+
# Install dependencies
|
|
48
|
+
npm install
|
|
49
|
+
|
|
50
|
+
# Build the project
|
|
51
|
+
npm run build
|
|
52
|
+
|
|
53
|
+
# Install globally
|
|
54
|
+
npm install -g .
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Verify the installation using the same command as above.
|
|
58
|
+
|
|
59
|
+
## Next Steps
|
|
60
|
+
|
|
61
|
+
After installation:
|
|
62
|
+
|
|
63
|
+
1. [Configure your MCP client](configuration.md) to use the CODESYS MCP Toolkit
|
|
64
|
+
2. Try some [basic examples](examples.md)
|
|
65
|
+
3. Learn about the [available tools and resources](api.md)
|
|
66
|
+
|
|
67
|
+
## Troubleshooting Installation Issues
|
|
68
|
+
|
|
69
|
+
### Common Issues
|
|
70
|
+
|
|
71
|
+
- **Permission errors**: You may need to run npm with administrative privileges
|
|
72
|
+
```bash
|
|
73
|
+
sudo npm install -g @codesys/mcp-toolkit # On Linux/macOS
|
|
74
|
+
# or use PowerShell as Administrator on Windows
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- **Path issues**: Ensure the npm global bin directory is in your PATH
|
|
78
|
+
|
|
79
|
+
- **Node.js version**: Verify you have Node.js 18 or later
|
|
80
|
+
```bash
|
|
81
|
+
node --version
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
If you encounter other issues, please check the [troubleshooting guide](troubleshooting.md) or [open an issue](https://github.com/yourusername/codesys-mcp-toolkit/issues) on GitHub.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# CODESYS MCP Toolkit Examples
|
|
2
|
+
|
|
3
|
+
This directory contains examples of how to use the CODESYS MCP toolkit effectively.
|
|
4
|
+
|
|
5
|
+
## Example Configuration Files
|
|
6
|
+
|
|
7
|
+
### Basic MCP Configuration
|
|
8
|
+
|
|
9
|
+
`claude_desktop_config.json` - Example configuration for Claude Desktop:
|
|
10
|
+
|
|
11
|
+
```json
|
|
12
|
+
{
|
|
13
|
+
"mcpServers": {
|
|
14
|
+
"codesys_local": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": [
|
|
17
|
+
"-y",
|
|
18
|
+
"@codesys/mcp-toolkit",
|
|
19
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
20
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Example Prompts
|
|
28
|
+
|
|
29
|
+
Here are some example prompts you can use with Claude Desktop:
|
|
30
|
+
|
|
31
|
+
### Create a Motor Controller Function Block
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
Using the CODESYS Local server, please create a MotorController function block with the following:
|
|
35
|
+
|
|
36
|
+
1. Properties:
|
|
37
|
+
- SpeedSetpoint (INT)
|
|
38
|
+
- ActualSpeed (INT)
|
|
39
|
+
- IsRunning (BOOL)
|
|
40
|
+
|
|
41
|
+
2. Methods:
|
|
42
|
+
- Start() - Sets IsRunning to TRUE
|
|
43
|
+
- Stop() - Sets IsRunning to FALSE
|
|
44
|
+
- SetSpeed(speed: INT) - Sets SpeedSetpoint to the given value
|
|
45
|
+
|
|
46
|
+
Create this in a new project at C:/MyProjects/MotorControl.project
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Open and Analyze an Existing Project
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Using the CODESYS Local server, please open the project at C:/MyProjects/ExistingProject.project and show me its structure. Then, show me the code for the main POU.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Compile a Project
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
Using the CODESYS Local server, please open the project at C:/MyProjects/MyProject.project and compile it. Let me know if there are any errors.
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Programmatic Usage Examples
|
|
62
|
+
|
|
63
|
+
If you're integrating directly with the server code, here are some examples:
|
|
64
|
+
|
|
65
|
+
### CLI Usage
|
|
66
|
+
|
|
67
|
+
Run the server directly:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
codesys-mcp-toolkit --codesys-path "C:\Program Files\CODESYS 3.5.21.0\CODESYS\Common\CODESYS.exe" --codesys-profile "CODESYS V3.5 SP21"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Use Cases
|
|
74
|
+
|
|
75
|
+
* Automated PLC project creation
|
|
76
|
+
* Standardized Function Block library management
|
|
77
|
+
* Continuous integration for CODESYS projects
|
|
78
|
+
* Documentation generation from CODESYS projects
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"codesys_local": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": [
|
|
6
|
+
"-y",
|
|
7
|
+
"@codesys/mcp-toolkit",
|
|
8
|
+
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
9
|
+
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
10
|
+
]
|
|
11
|
+
},
|
|
12
|
+
"filesystem": {
|
|
13
|
+
"command": "npx",
|
|
14
|
+
"args": [
|
|
15
|
+
"-y",
|
|
16
|
+
"@modelcontextprotocol/server-filesystem",
|
|
17
|
+
"C:/MyProjects"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"memory": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": [
|
|
23
|
+
"-y",
|
|
24
|
+
"@modelcontextprotocol/server-memory"
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
"puppeteer": {
|
|
28
|
+
"command": "npx",
|
|
29
|
+
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codesys/mcp-toolkit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"main": "dist/server.js",
|
|
5
5
|
"bin": {
|
|
6
6
|
"codesys-mcp-toolkit": "./dist/bin.js"
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"description": "Model Context Protocol (MCP) server for CODESYS automation platform",
|
|
25
25
|
"repository": {
|
|
26
26
|
"type": "git",
|
|
27
|
-
"url": "https://github.com/
|
|
27
|
+
"url": "git+https://github.com/johannesPettersson80/codesys-mcp-toolkit.git"
|
|
28
28
|
},
|
|
29
|
-
"homepage": "https://github.com/
|
|
29
|
+
"homepage": "https://github.com/johannesPettersson80/codesys-mcp-toolkit#readme",
|
|
30
30
|
"bugs": {
|
|
31
|
-
"url": "https://github.com/
|
|
31
|
+
"url": "https://github.com/johannesPettersson80/codesys-mcp-toolkit/issues"
|
|
32
32
|
},
|
|
33
33
|
"engines": {
|
|
34
34
|
"node": ">=14.0.0"
|