@codesys/mcp-toolkit 1.0.0 → 1.0.3
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 +45 -0
- package/CONTRIBUTING.md +72 -0
- package/README.md +65 -109
- package/README.md.enhanced +155 -0
- package/dist/codesys_interop - Copy.js +180 -0
- package/dist/codesys_interop.js +48 -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 +33 -0
- package/package.json +4 -4
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
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.3] - 2025-04-23
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
- Fixed path handling for CODESYS executable paths with spaces
|
|
12
|
+
- Updated spawn method to use shell:true with quoted paths
|
|
13
|
+
- Improved documentation and sample configuration
|
|
14
|
+
|
|
15
|
+
## [1.0.2] - 2025-04-22
|
|
16
|
+
|
|
17
|
+
### Added
|
|
18
|
+
- Improved error handling for script execution
|
|
19
|
+
- Better feedback in console logs
|
|
20
|
+
|
|
21
|
+
## [1.0.1] - 2025-04-21
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
- Resolved issues with project path resolution
|
|
25
|
+
- Fixed property accessor path handling
|
|
26
|
+
|
|
27
|
+
## [1.0.0] - 2025-04-20
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- Initial release of the MCP server for CODESYS
|
|
31
|
+
- Command-line interface with configuration options
|
|
32
|
+
- Project management functionality:
|
|
33
|
+
- Opening existing CODESYS projects
|
|
34
|
+
- Creating new CODESYS projects
|
|
35
|
+
- Saving projects
|
|
36
|
+
- POU (Program Organization Unit) management:
|
|
37
|
+
- Creating POUs (Programs, Function Blocks, Functions)
|
|
38
|
+
- Setting POU code (declaration and implementation)
|
|
39
|
+
- Creating properties and methods for Function Blocks
|
|
40
|
+
- Project compilation support
|
|
41
|
+
- Resources for querying:
|
|
42
|
+
- Project status
|
|
43
|
+
- Project structure
|
|
44
|
+
- POU code
|
|
45
|
+
- 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,123 +1,79 @@
|
|
|
1
|
-
#
|
|
1
|
+
# CODESYS MCP Toolkit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A Model Context Protocol (MCP) toolkit for interfacing between Claude and CODESYS programming environments.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Overview
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
This toolkit provides a bridge between Claude Desktop and CODESYS V3, allowing Claude to interact with CODESYS projects through a standardized Model Context Protocol (MCP).
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
* `codesys://project/status`: Checks scripting status and if a project is open.
|
|
11
|
-
* `codesys://project/structure`: Retrieves the structure of the open project as text.
|
|
12
|
-
* `codesys://pou/{+pou_path}/code`: Reads the implementation or declaration code of a specific POU or DUT/GVL.
|
|
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.
|
|
9
|
+
## Installation
|
|
20
10
|
|
|
21
|
-
|
|
11
|
+
```bash
|
|
12
|
+
npm install @codesys/mcp-toolkit
|
|
13
|
+
```
|
|
22
14
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
15
|
+
## Configuration
|
|
16
|
+
|
|
17
|
+
Add the following to your Claude Desktop configuration file (`claude_desktop_config.json`):
|
|
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
|
+
```
|
|
26
34
|
|
|
27
|
-
|
|
35
|
+
### Path Handling
|
|
28
36
|
|
|
29
|
-
|
|
37
|
+
The toolkit now properly handles paths with spaces when launching CODESYS. You don't need to add additional quotes in your configuration.
|
|
38
|
+
|
|
39
|
+
## Available Tools
|
|
40
|
+
|
|
41
|
+
This toolkit provides several MCP tools for interacting with CODESYS projects:
|
|
42
|
+
|
|
43
|
+
- `open_project`: Open an existing CODESYS project
|
|
44
|
+
- `create_project`: Create a new CODESYS project from a template
|
|
45
|
+
- `save_project`: Save the current CODESYS project
|
|
46
|
+
- `create_pou`: Create a new Program Organization Unit (POU)
|
|
47
|
+
- `set_pou_code`: Set the declaration and implementation code for a POU
|
|
48
|
+
- `create_property`: Create a property in a Function Block
|
|
49
|
+
- `create_method`: Create a method in a Function Block
|
|
50
|
+
- `compile_project`: Compile the current CODESYS project
|
|
51
|
+
|
|
52
|
+
## Example Usage
|
|
53
|
+
|
|
54
|
+
Claude can use these tools to perform complex CODESYS operations, for example:
|
|
30
55
|
|
|
31
|
-
```
|
|
32
|
-
|
|
56
|
+
```
|
|
57
|
+
Create a new motor controller FB with properties for speed, state, and temperature
|
|
33
58
|
```
|
|
34
59
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
```bash
|
|
41
|
-
git clone https://github.com/yourusername/codesys-mcp-server.git
|
|
42
|
-
cd codesys-mcp-server
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
2. **Install Dependencies:**
|
|
46
|
-
```bash
|
|
47
|
-
npm install
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
3. **Build the Project:**
|
|
51
|
-
```bash
|
|
52
|
-
npm run build
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
4. **Install Globally:**
|
|
56
|
-
```bash
|
|
57
|
-
npm install -g .
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
## Running the Server (via Claude Desktop)
|
|
61
|
-
|
|
62
|
-
This server is designed to be launched automatically by an MCP client like Claude Desktop using its stdio connection mechanism. You don't typically run it directly from the command line yourself.
|
|
63
|
-
|
|
64
|
-
## Configuring Claude Desktop
|
|
65
|
-
|
|
66
|
-
1. **Locate Configuration File:** Find Claude Desktop's MCP configuration file. On Windows, it's typically located at:
|
|
67
|
-
`C:\Users\<YourUsername>\AppData\Roaming\Claude\claude_desktop_config.json`
|
|
68
|
-
(Replace `<YourUsername>` with your actual Windows username).
|
|
69
|
-
2. **Edit Configuration:** Open `claude_desktop_config.json` in a text editor.
|
|
70
|
-
3. **Add Server Entry:** Add an entry for the CODESYS server within the `mcpServers` object. Make sure to replace the example paths and profile name with your actual values.
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
{
|
|
74
|
-
"mcpServers": {
|
|
75
|
-
// ... other servers like puppeteer, filesystem ...
|
|
76
|
-
|
|
77
|
-
"codesys_local": {
|
|
78
|
-
"command": "npx",
|
|
79
|
-
"args": [
|
|
80
|
-
"-y",
|
|
81
|
-
"@codesys/mcp-toolkit",
|
|
82
|
-
"--codesys-path", "C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe",
|
|
83
|
-
"--codesys-profile", "CODESYS V3.5 SP21"
|
|
84
|
-
]
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Important:**
|
|
91
|
-
* Replace `C:/Users/ek6430/Desktop/codesys-mcp-server/dist/server.js` with the correct **absolute path** to the compiled `server.js` file on your system. Use forward slashes (`/`) for path separators within this JSON string.
|
|
92
|
-
* Replace `"C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe"` with the correct **absolute path** to your `CODESYS.exe`. Note the use of double backslashes (`\\`) because backslashes need to be escaped within JSON strings.
|
|
93
|
-
* Replace `"CODESYS V3.5 SP21"` with the **exact name** of your CODESYS profile (the one with scripting enabled). Find this name when starting CODESYS or in its title bar.
|
|
94
|
-
4. **Save the File.**
|
|
95
|
-
5. **Restart Claude Desktop:** Close Claude Desktop completely and restart it. It will now read the updated configuration and attempt to launch the CODESYS server with the specified arguments.
|
|
96
|
-
6. **Verify Connection:** Claude Desktop should indicate that it has successfully connected to the "codesys_local" server. You might see the server listed in your available MCP integrations.
|
|
97
|
-
7. **Use Tools/Resources:** You can now interact with the server from within Claude. For example:
|
|
98
|
-
* Ask Claude to "Use the `project-status` resource from the CODESYS Local server."
|
|
99
|
-
* Ask Claude to "Use the `open_project` tool from CODESYS Local with filePath set to 'C:/Path/To/Your/Project.project'." (Replace with a real project path).
|
|
60
|
+
Claude will then:
|
|
61
|
+
1. Create a Function Block (FB) in your CODESYS project
|
|
62
|
+
2. Add appropriate properties with getters and setters
|
|
63
|
+
3. Add methods for control operations
|
|
64
|
+
4. Implement the logic in Structured Text (ST)
|
|
100
65
|
|
|
101
66
|
## Troubleshooting
|
|
102
67
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
* Connecting to a running PLC (`create_online_device`, `connect`).
|
|
116
|
-
* Logging into the PLC (`login`).
|
|
117
|
-
* Starting/Stopping applications (`start`, `stop`).
|
|
118
|
-
* Reading/Writing live variable values (`read_value`, `set_prepared_value`, `write_prepared_values`).
|
|
119
|
-
* Forcing/Unforcing values (`force_prepared_values`, `unforce_all_values`).
|
|
120
|
-
* Performing downloads and online changes (`login` with options).
|
|
121
|
-
* Managing PLC files (`download_file`, `upload_file`, `delete_file`).
|
|
122
|
-
* Handling PLC user management (`create_live_user_management`).
|
|
123
|
-
* License management (`activate_license`).
|
|
68
|
+
### Path Issues
|
|
69
|
+
|
|
70
|
+
If you encounter issues with paths:
|
|
71
|
+
|
|
72
|
+
- Ensure your CODESYS path is correct in the configuration
|
|
73
|
+
- Make sure the toolkit can locate your CODESYS installation
|
|
74
|
+
- Verify the CODESYS profile name matches your installation
|
|
75
|
+
|
|
76
|
+
### Common Error Messages
|
|
77
|
+
|
|
78
|
+
- `C:\Program is not recognized...`: Update to the latest version of the toolkit which fixes path handling with spaces
|
|
79
|
+
- `Failed to start CODESYS process`: Check if CODESYS is installed at the specified path
|
|
@@ -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,86 @@ 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
|
+
process.stderr.write('>>>> DEBUG: Attempting spawn with shell:true to handle paths with spaces. <<<<\n');
|
|
92
|
+
// Spawn the CODESYS process WITH shell:true to handle paths with spaces properly
|
|
93
|
+
const codesysProcess = (0, child_process_1.spawn)(`"${codesysExePath}"`, argsArray, {
|
|
94
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
95
|
+
shell: true
|
|
91
96
|
});
|
|
92
|
-
// Capture stdout
|
|
97
|
+
// Capture stdout & stderr
|
|
93
98
|
codesysProcess.stdout.on('data', (data) => {
|
|
94
99
|
const chunk = data.toString();
|
|
95
|
-
// console.error('CODESYS stdout:', chunk); // Optional: Original debug log
|
|
96
100
|
output += chunk;
|
|
97
101
|
});
|
|
98
|
-
// Capture stderr
|
|
99
102
|
codesysProcess.stderr.on('data', (data) => {
|
|
100
103
|
const chunk = data.toString();
|
|
101
|
-
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
102
|
-
output += chunk;
|
|
104
|
+
process.stderr.write(`CODESYS stderr: ${chunk}\n`);
|
|
105
|
+
output += chunk;
|
|
103
106
|
});
|
|
104
107
|
// Wait for the process to exit with a timeout
|
|
105
108
|
const exitCode = yield new Promise((resolve, reject) => {
|
|
106
|
-
//
|
|
107
|
-
const timeoutMs = 30000; // 30 seconds
|
|
109
|
+
// Note: timeoutMs is now defined in the outer scope
|
|
108
110
|
const timeout = setTimeout(() => {
|
|
109
|
-
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
111
|
+
process.stderr.write(`TIMEOUT: CODESYS process did not complete in ${timeoutMs}ms. Killing process.\n`);
|
|
112
|
+
codesysProcess.kill('SIGTERM');
|
|
113
|
+
setTimeout(() => {
|
|
114
|
+
if (!codesysProcess.killed) {
|
|
115
|
+
process.stderr.write('Force killing CODESYS process after timeout.\n');
|
|
116
|
+
codesysProcess.kill('SIGKILL');
|
|
117
|
+
}
|
|
118
|
+
}, 2000);
|
|
119
|
+
resolve(999); // Use a distinct code for timeout
|
|
120
|
+
}, timeoutMs); // Use timeoutMs here
|
|
114
121
|
codesysProcess.on('close', (code) => {
|
|
115
122
|
clearTimeout(timeout);
|
|
116
123
|
resolve(code !== null && code !== void 0 ? code : 0);
|
|
117
124
|
});
|
|
118
125
|
codesysProcess.on('error', (err) => {
|
|
119
126
|
clearTimeout(timeout);
|
|
120
|
-
|
|
121
|
-
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`); // Use process.stderr
|
|
127
|
+
process.stderr.write(`Failed to start CODESYS process: ${err.message}\n`);
|
|
122
128
|
reject(err);
|
|
123
129
|
});
|
|
124
130
|
});
|
|
125
|
-
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
131
|
+
process.stderr.write(`CODESYS process exited with code: ${exitCode}\n`);
|
|
126
132
|
// 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
133
|
if (output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
130
134
|
success = true;
|
|
131
135
|
}
|
|
132
136
|
else if (output.includes(SCRIPT_ERROR_MARKER)) {
|
|
133
137
|
success = false;
|
|
134
138
|
}
|
|
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
|
-
}
|
|
139
|
+
else if (exitCode !== 0) {
|
|
140
|
+
success = false;
|
|
141
|
+
if (!output.includes(SCRIPT_ERROR_MARKER)) {
|
|
142
|
+
// Use timeoutMs from outer scope here - NOW IT WORKS!
|
|
143
|
+
const exitReason = exitCode === 999 ? `due to timeout (${timeoutMs}ms)` : `with non-zero code ${exitCode}`;
|
|
144
|
+
output += `\nSCRIPT_ERROR: Process exited ${exitReason}. Check CODESYS stderr output above for details.`;
|
|
146
145
|
}
|
|
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
|
-
}
|
|
146
|
+
}
|
|
147
|
+
else {
|
|
148
|
+
if (!output.includes(SCRIPT_SUCCESS_MARKER)) {
|
|
149
|
+
process.stderr.write("Warning: CODESYS script finished with exit code 0 but no SCRIPT_SUCCESS marker found.\n");
|
|
155
150
|
}
|
|
151
|
+
success = true;
|
|
156
152
|
}
|
|
157
153
|
}
|
|
158
154
|
catch (error) {
|
|
159
|
-
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
155
|
+
process.stderr.write(`Error executing CODESYS script: ${error}\n`);
|
|
160
156
|
output += `\nSCRIPT_ERROR: Failed to execute script process. ${error.message}`;
|
|
161
157
|
success = false;
|
|
162
158
|
}
|
|
@@ -164,17 +160,16 @@ function executeCodesysScript(scriptContent, codesysExePath, codesysProfileName)
|
|
|
164
160
|
// Clean up the temporary file
|
|
165
161
|
try {
|
|
166
162
|
yield (0, promises_1.unlink)(tempFilePath);
|
|
167
|
-
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
163
|
+
process.stderr.write(`Temporary script deleted: ${tempFilePath}\n`);
|
|
168
164
|
}
|
|
169
165
|
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
|
|
166
|
+
process.stderr.write(`Warning: Failed to delete temporary script file ${tempFilePath}: ${cleanupError.message}\n`);
|
|
167
|
+
if (success) {
|
|
173
168
|
output += `\nWARNING: Failed to delete temporary script file ${tempFilePath}. ${cleanupError.message}`;
|
|
174
169
|
}
|
|
175
170
|
}
|
|
176
171
|
}
|
|
177
|
-
process.stderr.write(`Final script output received:\n---\n${output}\n---\n`);
|
|
178
|
-
return { success, output };
|
|
172
|
+
// process.stderr.write(`Final script output received:\n---\n${output}\n---\n`);
|
|
173
|
+
return { success, output };
|
|
179
174
|
});
|
|
180
175
|
}
|
|
@@ -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,33 @@
|
|
|
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
|
+
// Note: Path with spaces is handled by the toolkit now. No need for additional quotes.
|
|
12
|
+
},
|
|
13
|
+
"filesystem": {
|
|
14
|
+
"command": "npx",
|
|
15
|
+
"args": [
|
|
16
|
+
"-y",
|
|
17
|
+
"@modelcontextprotocol/server-filesystem",
|
|
18
|
+
"C:/MyProjects"
|
|
19
|
+
]
|
|
20
|
+
},
|
|
21
|
+
"memory": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": [
|
|
24
|
+
"-y",
|
|
25
|
+
"@modelcontextprotocol/server-memory"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
"puppeteer": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "@modelcontextprotocol/server-puppeteer"]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codesys/mcp-toolkit",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
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"
|