Skip to main content
Glama
TIA-Portal MCP-Server

TIA-Portal MCP-Server

README.md
# TIA Portal MCP-Server

![vscode-tiaportal-mcp-logo](https://raw.githubusercontent.com/heilingbrunner/vscode-tiaportal-mcp/master/assets/vscode-tiaportal-mcp-logo.png)

![License](https://img.shields.io/github/license/heilingbrunner/vscode-tiaportal-mcp.svg?style=flat)
[![Version](https://img.shields.io/visual-studio-marketplace/v/JHeilingbrunner.vscode-tiaportal-mcp.svg?label=Version&style=flat)](https://marketplace.visualstudio.com/items?itemName=JHeilingbrunner.vscode-tiaportal-mcp)
![Visual Studio Marketplace Installs](https://img.shields.io/visual-studio-marketplace/i/JHeilingbrunner.vscode-tiaportal-mcp)

A Visual Studio Code extension to connect to Siemens TIA Portal and interact with TIA Portal projects directly from VS Code with GitHub Copilot.

## Requirements

- __Siemens TIA Portal V21__ installed and running on your machine
- __Siemens.Openness__ installed
- __net Framework 4.8__ installed
- __Visual Studio Code__ installed
- __GitHub Copilot__ in Visual Studio Code installed and configured (check: `Chat > Mcp: Enabled`)

## Chat

The chat allows you to interact with TIA Portal using natural language commands. You can instruct it to perform tasks such as connecting to a project, exporting PLC programs, modifying files, and importing changes back into TIA Portal. The chat works in conjunction with the `tia` porcelain commands for streamlined workflows.

## Chat Examples using natural language

```
Do the following steps:
- Connect to tia portal
- export plc program
- ... modify files ...
- Give me preview which modified files would be imported to plc program
- Get project tree and save output to project-tree.txt
- Get software tree and save output to software-tree.txt
- Import plc program changes
- Close the project
- Disconnect from tia portal
```

```
Do the following steps:
- Connect to tia portal
- Give me the structure of the project and save output to project-structure.txt
- Give me the software structure and save output to software-structure.txt
- Close the project
- Disconnect from tia portal
```

```
Do the following steps:
- Connect to tia portal
- Compile plc software
- Close the project
- Disconnect from tia portal
```

## `tia` porcelain commands: connect, pull and push

Short tools for the chat that work like the git commands they are named after. They sit on top of the tools above:
`connect` attaches to TIA Portal and opens the project, `pull` brings TIA Portal into the export folder, `push`
brings the changed files of that folder into TIA Portal.
Type the command in the chat, e.g. `tia pull blocks ".+HMI"`, or pick the tool or the prompt of the same name.

| You say                      | Tool                 | Same as                                                  |
| ---------------------------- | -------------------- | -------------------------------------------------------- |
| `tia connect`                | `TiaConnect`         | `OpenTiaProject`                                         |
| `tia pull`                   | `TiaPull`            | `ExportPlcProgram`                                       |
| `tia pull blocks [rx]`       | `TiaPullBlocks`      | `ExportBlocks`, optionally by regex                      |
| `tia pull types [rx]`        | `TiaPullTypes`       | `ExportTypes`, optionally by regex                       |
| `tia pull tagtables [rx]`    | `TiaPullTagTables`   | `ExportTagTables`, optionally by regex                   |
| `tia pull block <path>`      | `TiaPullBlock`       | `ExportBlock`, exactly one block by its full path        |
| `tia pull type <path>`       | `TiaPullType`        | `ExportType`, exactly one PLC data type by its full path |
| `tia pull tagtable <path>`   | `TiaPullTagTable`    | `ExportTagTable`, exactly one tag table by its path      |
| `tia pull watchtables [rx]`  | `TiaPullWatchTables` | `ExportWatchTables`, optionally by regex                 |
| `tia pull watchtable <path>` | `TiaPullWatchTable`  | `ExportWatchTable`, exactly one watch table by its path  |
| `tia pull forcetable <path>` | `TiaPullForceTable`  | `ExportForceTable`, the force table of the PLC           |
| `tia push`                   | `TiaPush`            | `ImportPlcProgramChanges` with `dryRun=false`            |
| `tia push preview`           | `TiaPushPreview`     | `ImportPlcProgramChanges` with `dryRun=true`             |

- `TiaConnect` connects to the running TIA Portal (or starts one), opens the `.apXX` project or `.alsXX` session
  and returns the PLC software paths to use as `softwarePath`. `path` takes the preset of `--project-path`; pass
  `portalId` when several instances run. It closes the project that is open first, unless it is the one asked for.
- The pull tools write the tree of `ExportPlcProgram`, each object in the format of `<exportPath>/tia.json`, so a pull
  of blocks and a pull of the whole program land in the same folders. `TiaPullTagTables` writes one XML file per tag
  table below `<exportPath>/<softwarePath>/PLC tags/<groups>/`, `TiaPullWatchTables` one per watch table below the watch and force tables folder; both have one format only.
- The optional regular expression (`regexName`) selects objects by name, e.g. `.+HMI`. `TiaPullBlocks` writes no
  types and `TiaPullTypes` no blocks.
- The push tools are the import tools under another name and need `--allow-write`. `TiaPush` shows the same
  confirmation dialog ("Yes, import") and `TiaPushPreview` imports nothing. They read only the files git reports as
  changed, and not the tag or watch tables; there is no tool that imports tag tables.
- `softwarePath` and `exportPath` take the presets from `--software-path` and `--export-path`.

Prompts using the `tia` commands (see "`tia` porcelain commands" above; with the presets from the json config
file `softwarePath` and `exportPath` can be left out):

- 'tia connect'
- 'tia pull'
- 'tia pull blocks'
- 'tia pull blocks ".+HMI_.+"'
- 'tia pull types'
- 'tia pull tagtables'
- 'tia pull watchtables'
- 'tia pull block Group1/Subgroup/FB_Motor'
- 'tia pull type Group1/Udt_Drive'
- 'tia pull tagtable TagGroup1/Table1'
- 'tia pull watchtable WatchGroup1/WatchTable_1'
- 'tia pull forcetable ForceTable'
- 'tia push preview'
- 'tia push'
- 'save project'

## MCP-Server

- Refer to [tiaportal-mcp](https://github.com/heilingbrunner/tiaportal-mcp) 

## Features

- Connect to a TIA Portal instance
- Browse and interact with TIA Portal projects
- Perform basic project operations from within VS Code

## Requirements

- __.net Framework 4.8__ installed
- __Siemens TIA Portal V20__ installed and running on your machine
- Check if under `Environment Variables/User variable for user <name>` the variable `TiaPortalLocation` is set to `C:\Program Files\Siemens\Automation\Portal V20`. Details on [nuget.org - Siemens.Collaboration.Net.TiaPortal.Openness.Resolver](https://www.nuget.org/packages/Siemens.Collaboration.Net.TiaPortal.Openness.Resolver#readme-body-tab)
- User must be in Windows User Group `Siemens TIA Openness`. Details on [TIA Portal Openness - Adding Users to the Siemens TIA Openness User Group](https://docs.tia.siemens.cloud/r/en-us/v20/tia-portal-openness-api-for-automation-of-engineering-workflows/basics/installation/adding-users-to-the-siemens-tia-openness-user-group)


## Usage

### Project configuration

The extension only writes project-scoped files in the first workspace folder. User-level files (for example the VS Code user `mcp.json` or `claude_desktop_config.json`) are never touched.

| Client                         | File in the workspace folder | Format and key                             |
| ------------------------------ | ---------------------------- | ------------------------------------------ |
| GitHub Copilot                 | `.vscode\mcp.json`           | JSON, `servers`                            |
| Anthropic Claude (Claude Code) | `.mcp.json`                  | JSON, `mcpServers`                         |
| Cursor                         | `.cursor\mcp.json`           | JSON, `mcpServers`                         |
| OpenAI Codex                   | `.codex\config.toml`         | TOML, `[mcp_servers.vscode-tiaportal-mcp]` |

These are the clients that run in VS Code or a VS Code fork, where this extension can be installed: GitHub Copilot, the Claude Code extension, Cursor and the Codex IDE extension. Cursor installs extensions from Open VSX, so this extension has to be installed there from the `.vsix` file unless it is published on Open VSX.

Notes on single clients:

- Only GitHub Copilot expands `${workspaceFolder}`. For GitHub Copilot the export path is written exactly as you enter it. For Anthropic Claude, Cursor and OpenAI Codex `${workspaceFolder}` is replaced by the absolute path of the workspace folder, because these clients pass it to the server unchanged. Relative and absolute paths are written as entered for all clients; prefer an absolute path, since a relative one depends on the working directory the client starts the server in.
- When you run the command again, the arguments of the first existing entry are offered as defaults. If that is a non-Copilot file, the export path is already absolute.
- Claude Code asks for approval the first time it sees a project-scoped server. Codex only loads `.codex\config.toml` for trusted projects.

#### Add server

- After installation restart VS Code.
- Run the command `TIA Portal: Add MCP Server Configuration` and tick the clients (checkboxes) you want to configure, then press `Enter`. The questions are asked once and the files of all ticked clients are written.
- Before the list is shown, the extension looks at the config files of all clients. Clients that already contain the server entry are ticked and marked `(already configured)` (in `Remove` as well), and the arguments of the first entry found are the default answers of the questions, even if you tick a different client. A file that cannot be parsed is ignored at this point and reported when you select its client.
- Arguments the existing entry does not have are taken from the `args` section (`project`, `software-path`, `export-path`) of `<export path>/tia.json`, if that file exists (`tia init` of the server writes it). It is looked up in the export path of the existing entry, otherwise in `${workspaceFolder}\Project`. A value of the existing entry always wins, and a file that is missing or invalid is ignored.
- Answer the prompts (press `Esc` to cancel, nothing is written then). Values from an existing entry, or else from `tia.json`, are offered as defaults:
   1. TIA Portal major version (`--tia-major-version`)
   2. Project or session file (`--project-path`)
   3. PLC software path (`--software-path`), e.g. `PC-System_1/Software PLC_1`
   4. Export path (`--export-path`), default `${workspaceFolder}\Project` (kept for GitHub Copilot, resolved to the absolute folder for the other clients)
   5. Preserve path structure (`--preserve-path`)
   6. Allow write access to the project (`--allow-write`), default `No`. The flag is only written if you answer `Yes`.
- Check the written file (GitHub Copilot example below). Other servers and settings in the file are kept.
   - `<user>`: Your Windows username
   - `<version>`: The version of the extension you have installed.
    ```json
    {
        "servers": {
            "vscode-tiaportal-mcp": {
                "type": "stdio",
                "command": "c:\\Users\\<user>\\.vscode\\extensions\\jheilingbrunner.vscode-tiaportal-mcp-<version>\\srv\\net48\\TiaMcpServer.exe",
                "args": [
                    "--tia-major-version", "21",
                    "--project-path", "D:\\Siemens\\Projects\\MyProject\\MyProject.ap21",
                    "--software-path", "PC-System_1/Software PLC_1",
                    "--export-path", "${workspaceFolder}\\Project",
                    "--preserve-path",
                    "--allow-write"
                ],
                "env": {}
            }
        }
    }
    ```
    The Anthropic Claude and Cursor entries look the same under `"mcpServers"` (Cursor has no `"type"` field), but with an absolute `--export-path` such as `"E:\\Work\\MyWorkspace\\Project"`.
- Comments and trailing commas in the JSON files, and comments in `config.toml`, are allowed and are kept when the entry is added, updated or removed. If a file is not valid JSON or TOML the command stops with an error instead of overwriting it.

#### Use the server

- GitHub Copilot: open GitHub Copilot, switch to `Agent` mode, check the tools by `Select Tools` and start to chat with TIA Portal.
- Anthropic Claude: start Claude Code in the workspace folder and approve the project-scoped server `vscode-tiaportal-mcp` when asked (check with `/mcp`).
- Other clients: open the workspace folder in the tool; see its own MCP documentation for listing and enabling servers.

#### Remove server

- Run the command `TIA Portal: Remove MCP Server Configuration` and tick the clients (checkboxes) to remove the mcp server entry from their config files. The files of clients that are not ticked are not touched.

### `tia.json`: the export formats of TIA Portal

TIA Portal exports each kind of object in the format set under **Options > Settings > Version control interface >
Export formats**: SIMATIC SD documents (`.s7dcl`, `.s7res`), SimaticML (`.xml`) or a source file. Openness cannot
read that setting (the settings tree it offers has no export formats), so the server keeps the formats in a plain,
visible file at the root of the export folder:

```
<exportPath>/tia.json
```

It is one file for all PLCs below `<exportPath>`, because the setting is global. It is meant to be kept and committed
together with the export, so everyone who works with the folder uses the same formats.

**You normally do not write it.** The first time a tool needs it and it does not exist, the server creates it with the
defaults TIA Portal offers for a new workspace:


```json
{
  "version control interface": {
    "code blocks-LAD": "SIMATIC SD(.s7dcl, .s7res)",
    "code blocks-FBD": "SIMATIC SD(.s7dcl, .s7res)",
    "code blocks-SCL": "SIMATIC SD(.s7dcl, .s7res)",
    "code blocks-STL": ".awl",
    "data blocks": "SIMATIC SD(.s7dcl, .s7res)",
    "safety data blocks (F-DBs)": "SIMATIC SD(.s7dcl, .s7res)",
    "PLC data types": "SIMATIC SD(.s7dcl, .s7res)",
    "F-compliant PLC data types (UDT)": "SIMATIC SD(.s7dcl, .s7res)"
  }
}
```

Available file formats per object type; the first one listed is the default of a new file:

| Key                                | Available formats                                     |
| ---------------------------------- | ----------------------------------------------------- |
| `code blocks-LAD`                  | `SIMATIC SD(.s7dcl, .s7res)`, `.xml`                  |
| `code blocks-FBD`                  | `SIMATIC SD(.s7dcl, .s7res)`, `.xml`                  |
| `code blocks-SCL`                  | `SIMATIC SD(.s7dcl, .s7res)`, `.scl`, `.xml`          |
| `code blocks-STL`                  | `.awl`, `.xml`                                        |
| `data blocks`                      | `SIMATIC SD(.s7dcl, .s7res)`, `.db`, `.xml`           |
| `safety data blocks (F-DBs)`       | `SIMATIC SD(.s7dcl, .s7res)`, `.xml`                  |
| `PLC data types`                   | `SIMATIC SD(.s7dcl, .s7res)`, `.udt`, `.xml`          |
| `F-compliant PLC data types (UDT)` | `SIMATIC SD(.s7dcl, .s7res)`, `.xml`                  |

## License

MIT