TwinCAT Validator MCP Server
An MCP server that validates, auto-fixes, and scaffolds TwinCAT 3 XML files (.TcPOU, .TcIO, .TcDUT, .TcGVL). Connect it to any LLM client to give your AI assistant reliable, deterministic TwinCAT code quality tooling — structural checks, 21 IEC 61131-3 OOP checks, auto-fix pipelines, and canonical skeleton generation.
Supported File Types
Installation
pip install twincat-validator-mcp
From Source
git clone https://github.com/agenticcontrolio/twincat-validator-mcp.git
cd twincat-validator-mcp
pip install -e .
Claude Desktop Extension
The easiest way to use this server with Claude Desktop is via the one-click .dxt extension:
pip install twincat-validator-mcp- Download the
.dxtfile from the latest release - Open Claude Desktop → Settings → Extensions → Install Extension
See dxt/README.md for full instructions and troubleshooting.
Connecting to an LLM Client
For other clients (Cursor, VS Code, Windsurf, Cline), the server uses stdio transport. Add the following to your client's MCP config file:
Cursor — .cursor/mcp.json
{
"mcpServers": {
"twincat-validator": {
"command": "twincat-validator-mcp",
"args": []
}
}
}
VS Code (Copilot / Continue) — .vscode/mcp.json
{
"servers": {
"twincat-validator": {
"type": "stdio",
"command": "twincat-validator-mcp",
"args": []
}
}
}
Windsurf — ~/.codeium/windsurf/mcp_config.json
{
"mcpServers": {
"twincat-validator": {
"command": "twincat-validator-mcp",
"args": []
}
}
}
Cline (VS Code Extension)
{
"mcpServers": {
"twincat-validator": {
"command": "twincat-validator-mcp",
"args": [],
"disabled": false
}
}
}
Replace "command": "twincat-validator-mcp" with:
"command": "python",
"args": ["-m", "twincat_validator"],
"cwd": "/path/to/twincat-validator-mcp"
MCP Tools
Validation
Auto-fix
Orchestration
Validation Checks
Structure & Format (critical — blocks import)
- XML structure validity
- GUID format (
{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}) - GUID uniqueness across elements
- Property getter VAR blocks (missing
VAR/END_VAR) - LineIds count consistency
- File ending format
Style (warning — advisory)
- Tab characters (TwinCAT requires spaces)
- 2-space indentation
- Element ordering
- Naming conventions (
FB_,PRG_,FUNC_,E_,ST_,I_,GVL_) - Excessive blank lines
- CDATA formatting
OOP — IEC 61131-3 (21 checks)
Runs automatically when EXTENDS or IMPLEMENTS is detected. Skipped for procedural code.
Auto-fix Capabilities
Fixes are applied in a deterministic, dependency-aware order:
- Tabs → 2 spaces (runs before indentation)
- File ending — fixes truncated
]]>after</TcPlcObject> - Property newlines — normalizes declaration line breaks
- CDATA formatting — corrects CDATA section structure
- Property VAR blocks — inserts missing
VAR/END_VARin getters - Excessive blank lines — reduces to max 2 consecutive
- Indentation — normalizes to 2-space multiples
- GUID case — uppercases hex to canonical lowercase
- LineIds — experimental generation (marked unsafe, opt-in only)
Running autofix twice on the same file produces byte-identical output (idempotency guaranteed).
Intent-Aware OOP Enforcement
All tools accept an intent_profile parameter:
Batch tools scan all .TcPOU files to resolve "auto" once at the batch level.
Health Score
Files are scored 0–100 based on issue counts:
Target ≥ 90 for all production files.
MCP Resources
MCP Prompts
8 reusable prompt templates for canonical LLM workflows — covering single-file generation, batch validation, OOP scaffolding, determinism verification, and troubleshooting flows. Accessible via your MCP client's prompt interface.
Agent Guide
AGENT.md is an example guide prompt that tells your LLM agent exactly how to use this server — which tools to call, in what order, how to route intent (procedural vs OOP), stop conditions, and the reporting contract. Copy it into your system prompt or agent instructions and customise it to match your workflow.
Recommended Workflow
The pattern for any TwinCAT generation task — no code is written until the user has approved the plan.
flowchart LR
A([User Prompt]) --> B[📋 Plan\nLLM produces plan file\nand stops]
B --> C{User reviews\nand approves?}
C -- No --> B
C -- Yes --> D[⚙️ Implement\nLLM generates\nTwinCAT artifacts]
D --> E[✅ Validate\nMCP server validates,\nauto-fixes, confirms safety]
E --> F([Done])
style A fill:#4a90d9,color:#fff,stroke:none
style F fill:#27ae60,color:#fff,stroke:none
style C fill:#f39c12,color:#fff,stroke:none
After approval, the LLM follows this MCP tool sequence:
flowchart TD
START([Plan approved by user]) --> CTX
CTX["get_context_pack\n(stage=pre_generation)"]
CTX --> POLICY["get_effective_oop_policy\n(if OOP task)"]
POLICY --> SKE
CTX --> SKE
SKE["generate_skeleton\nfor each artifact"]
SKE --> WRITE["LLM writes\nST content into files"]
WRITE --> ORCH
subgraph ORCH_LOOP ["Orchestration loop (max 3 iterations)"]
ORCH["process_twincat_single\nor process_twincat_batch"]
ORCH --> SAFE{safe_to_import\n&& safe_to_compile?}
SAFE -- Yes --> DET
SAFE -- No --> BLOCKED{no_progress\nor iter >= 3?}
BLOCKED -- No --> KB["get_context_pack\n(stage=troubleshooting,\ncheck_ids=blockers)"]
KB --> FIX["LLM applies\none focused correction"]
FIX --> ORCH
BLOCKED -- Yes --> FAIL([Report blocked —\nstop])
end
DET["verify_determinism_batch\n(second pass — no changes expected)"]
DET --> STABLE{stable?}
STABLE -- No --> ORCH
STABLE -- Yes --> DONE([Report done ✅\nsafe_to_import, safe_to_compile,\nblocking_count=0, content_changed=false])
style START fill:#4a90d9,color:#fff,stroke:none
style DONE fill:#27ae60,color:#fff,stroke:none
style FAIL fill:#e74c3c,color:#fff,stroke:none
style BLOCKED fill:#f39c12,color:#fff,stroke:none
style SAFE fill:#f39c12,color:#fff,stroke:none
style STABLE fill:#f39c12,color:#fff,stroke:none
See EXAMPLE_PROMPT.md for a complete worked prompt using this pattern.
Configuration
Config files live in twincat_validator/config/ inside the installed package. To locate them:
import twincat_validator, os
print(os.path.join(os.path.dirname(twincat_validator.__file__), "config"))
Restart the server after editing config files to reload.
Development
pip install -e ".[dev]"
# Run tests
pytest tests/
# Format
black --line-length=100 .
# Lint
ruff check .
# Type check
mypy twincat_validator/server.py --ignore-missing-imports
# Full CI suite (py311 + py312, lint, type check)
tox
License
MIT — see LICENSE for details.
Authors
Agentic Control - Jaime Calvente Mieres: design, architecture, and domain expertise
Built with the assistance of Claude (Anthropic) and Codex (OpenAI).