# io.github.efranceschetti/festo-codesys-mcp (npm · festo-codesys-mcp)

MCP server for Festo/CODESYS PLCs: IEC 61131-3 ST + validated PLCopen XML generation.

- Trust score: 61/100 (medium)
- Change this week: +15
- Registry status: active
- Liveness: live
- Owner verified: no
- Last scored: 2026-08-03

## Components

- npm · `festo-codesys-mcp`: 61/100 (this document), [markdown](https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp.md), [page](https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp)

## Channel facts

- Registry: `npm`
- Package: `festo-codesys-mcp`
- Version: `1.0.1`
- Transport: `stdio`

## Trust breakdown

How this component scores in each security and reliability category. Every signal is checked automatically from public evidence about the published package, including repeated runs of it in an isolated sandbox, and we only credit what we can confirm. Scores are 0–100 per category. Scoring method: https://verifymcp.io/docs/scoring (what has changed: https://verifymcp.io/docs/scoring/changelog)

Scored 2026-08-03.

- **Supply Chain Security**: 87/100
  - No malware found by supply-chain analysis.
  - Only part of the dependency tree could be resolved (104 of 108), so this covers what we could see, not the whole tree.
  - No install/post-install scripts declared.
  - Only part of the dependency tree could be resolved (104 of 108), so this covers what we could see, not the whole tree.
- **Provenance & Transparency**: 19/100
  - Repository check failed: no source repository is declared.
  - Provenance check failed: no build-provenance attestation is published.
  - Clear OSI-approved license (MIT).
  - Actively maintained (last published 16 days ago).
  - Disclosure check failed: no security disclosure policy was found in the source repository.
- **Schema Quality & AI Usability**: 64/100
  - 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).
  - AI-judged instruction clarity (poor).
  - Tool/resource definitions use about 6795 tokens (~65/item across 103 items; 18 tools + 85 resources), lean.
  - Usage-examples check failed: none of the tools include examples.
- **Stability & Change Management**: 27/100
  - Stability observed for 8 of 30 days with no destabilising changes; credit accrues until the full window elapses.
- **Tool Coverage**: 95/100
  - 100% of tools have a non-trivial description (not blank, and not just the tool's name).
  - 83% of tool parameters carry a description.
  - Structured output schemas are declared (33% of tools); any adoption earns full credit.
- **Capabilities**: 100/100
  - Implements a supported MCP spec version (2025-11-25); the latest is 2026-07-28.

## Install

### Claude

```bash
claude mcp add efranceschetti-festo-codesys-mcp -- npx -y festo-codesys-mcp
```

### Codex

```bash
codex mcp add efranceschetti-festo-codesys-mcp -- npx -y festo-codesys-mcp
```

### opencode

```json
{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "efranceschetti-festo-codesys-mcp": {
      "type": "local",
      "command": [
        "npx",
        "-y",
        "festo-codesys-mcp"
      ],
      "enabled": true
    }
  }
}
```

### OpenClaw

```bash
openclaw mcp add efranceschetti-festo-codesys-mcp --command npx --arg -y --arg festo-codesys-mcp
```

### Hermes

```yaml
mcp_servers:
  efranceschetti-festo-codesys-mcp:
    command: "npx"
    args: ["-y", "festo-codesys-mcp"]
```

### Other

```json
{
  "mcpServers": {
    "efranceschetti-festo-codesys-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "festo-codesys-mcp"
      ]
    }
  }
}
```

## Changelog

Every change recorded for this component, newest first. Days that predate change tracking, or that we cannot explain, say so: "we were watching and nothing happened" and "we were not watching" are different claims.

### 2026-08-03 (score 61, +4)

- [functional improvement] Stability: unverified → 0.27

### 2026-08-02 (score 57, +11)

- [security regression] Known CVEs: partial → unverified
- [security improvement] Malware scan: unverified → pass
- [security] Stability: Stability not yet verified: we do not have a sandbox capture of the MCP schema this version of the package serves yet.
- [functional regression] Capabilities: pass → unverified
- [functional regression] Tool coverage: 100 → unverified
- [functional regression] Schema quality: 100 → unverified
- [functional regression] Dependency health: partial → unverified

### 2026-08-01 (score 46, +25)

- [security regression] Provenance: unverified → fail
- [security improvement] Install scripts: unverified → pass
- [security improvement] Known CVEs: unverified → partial
- [security] Stability: Stability not yet verified: not enough scan history yet (needs a 30-day window).
- [functional regression] Security disclosure: unverified → fail
- [functional improvement] License: unverified → pass
- [functional improvement] Dependency health: unverified → partial
- [functional improvement] Maintenance: unverified → pass
- [functional improvement] MCP protocol: unverified → pass
- [functional improvement] Schema quality: unverified → poor
- [functional] Licence: MIT

### 2026-07-31 (score 21, −25)

- [functional] We updated how we score, so this day's move reflects our rubric, not a change to the server

### 2026-07-27 (score 46)

First indexed and scored.

## MCP tools (18)

### `create_function_block` (~246 tokens)

Create Function Block

Generate a CODESYS Function Block (.st + PLCopen XML) with the standard interface built in.
USE WHEN: the user asks for a new FB and plc_library returned no reusable match.
ALWAYS BEFORE: (1) plc_library action=search — never create what already exists; (2) plc_knowledge topics 'conventions' + 'abbreviations'.
Standard pattern: bEnable/bExecute inputs, bDone/bBusy/bErr/nErrId outputs, nState state machine. Name auto-corrected to FB_ prefix.
DO NOT: use this for servo motion logic — motion uses MC_*_Festo blocks (topic 'festo-ptp'), not custom FBs.

Input parameters:

- `description` (string, required): What this FB does (English)
- `inOutVars` (array)
- `inputVars` (array)
- `localVars` (array)
- `name` (string, required): FB name (e.g., FB_ServoAxis or just ServoAxis)
- `outputDir` (string): Output directory (default: cwd)
- `outputVars` (array)
- `stCode` (string, required): Structured Text body (the logic)

### `create_program` (~155 tokens)

Create Program (PRG)

Generate a CODESYS Program (.st + PLCopen XML) for cyclic control logic.
USE WHEN: you need a cyclic PRG (runs once per scan) — PRG_Main, PRG_Auto, sequence orchestration — and no reusable one exists.
Programs run once per PLC scan (PRG_Main, PRG_Auto, etc.). Name auto-corrected to PRG_ prefix if missing.

Input parameters:

- `description` (string, required): What this program does
- `localVars` (array)
- `name` (string, required): Program name (e.g., PRG_Main or just Main)
- `outputDir` (string): Output directory (default: cwd)
- `stCode` (string, required): Structured Text body

### `create_data_type` (~144 tokens)

Create Data Type (ENUM/STRUCT)

Generate a CODESYS data type: ENUM (E_*) or STRUCT (ST_*), with .st + PLCopen XML output.
USE WHEN: you need an ENUM (state/mode) or STRUCT (config/record) to back FB, GVL, or program declarations.
Name auto-corrected to E_ (enum) or ST_ (struct) prefix if missing.

Input parameters:

- `kind` (string, required)
- `members` (array, required)
- `name` (string, required): Type name (e.g., E_MachState or MachState, ST_AxisCfg or AxisCfg)
- `outputDir` (string): Output directory (default: cwd)

### `create_gvl` (~142 tokens)

Create Global Variable List

Generate a Global Variable List (.st + PLCopen XML) with {attribute 'qualified_only'}.
USE WHEN: you need globals shared across POUs — I/O map, system flags, HMI tags (GVL_HMI), config.
Name auto-corrected to GVL_ prefix if missing. Common: GVL_Sys, GVL_IO, GVL_HMI, GVL_Cfg.

Input parameters:

- `isConstant` (boolean)
- `name` (string, required): GVL name (e.g., GVL_Sys or just Sys)
- `outputDir` (string): Output directory (default: cwd)
- `variables` (array, required)

### `generate_plcopen_xml` (~180 tokens)

Generate PLCopen XML (batch)

Batch-convert a directory of .st files into a single PLCopen TC6 0200 XML for CODESYS import.
USE WHEN: .st sources are final and reviewed, and the user wants a CODESYS-importable file.
ALWAYS BEFORE: plc_knowledge topic 'ground-truth' (anti-hallucination XML rules) if you have not loaded it this session.
ALWAYS AFTER: validate_plcopen_xml -> validate_plcopen_xsd -> validate_plcopen_semantic. Never hand the XML to the user before the chain passes.
DO NOT: hand-write PLCopen XML — always generate it from .st sources with this tool.

Input parameters:

- `outputFile` (string, required): Output XML file path
- `projectName` (string)
- `sourceDir` (string, required): Directory containing .st files

### `validate_plcopen_xml` (~230 tokens)

Validate PLCopen XML (fast sanity check)

Fast smoke check for PLCopen XML — XML well-formedness + 13 structural regex heuristics.
USE WHEN: immediately after generate_plcopen_xml, as the fast first gate before the XSD/semantic validators.
Use AFTER generate_plcopen_xml as a quick gate before the heavier validators.
Checks: XML well-formedness, PLCopen namespace, XHTML namespace, fileHeader, contentHeader,
coordinateInfo (fbd/ld/sfc), mandatory instances footer, zero-ID rule on connectionPoints,
ST code wrapping in xhtml, inOutVariables on blocks, structural hierarchy.
Returns: PASSED/ISSUES counts and VALID/FIX verdict.

NOTE: this is a sanity check only. For full validation use:
  \- validate_plcopen_xsd      — XSD official PLCopen TC6 v2.00 (catches structural issues)
  \- validate_plcopen_semantic — count vars/inits source ST vs XML (catches Bugs A/B/E/F: missing vars/inits)

Input parameters:

- `filePath` (string, required): Path to PLCopen XML file

Output parameters:

- `counts` (object)
- `failed` (number)
- `failedChecks` (array)
- `filePath` (string)
- `passed` (number)
- `passedChecks` (array)
- `valid` (boolean)

### `validate_plcopen_xsd` (~220 tokens)

Validate PLCopen XML against official TC6 v2.00 XSD

Strict schema validation against the official PLCopen TC6 v2.00 XSD (embedded).
USE WHEN: after validate_plcopen_xml passes and you need strict schema conformance before import.
Catches structural issues that the fast sanity check misses: malformed elements,
required attributes missing, type mismatches, etc.
Use AFTER generate_plcopen_xml for full structural validation before CODESYS import.

Output: { gate, valid, summary, errors[{line, location, code, message}], counts }
Codes: FILE_NOT_FOUND, XSD_NOT_FOUND, XSD_PARSE_ERROR, XML_PARSE_ERROR, XSD_VIOLATION.

NOTE: requires lxml in the MCP python venv. Pair with validate_plcopen_semantic
for end-to-end coverage (XSD catches structure, semantic catches missing vars/inits).

Input parameters:

- `filePath` (string, required): Path to PLCopen XML file
- `xsdPath` (string): Optional custom XSD path. Default: bundled tc6_xml_v200_patched.xsd

### `validate_plcopen_semantic` (~334 tokens)

Validate PLCopen XML semantically against source ST

Compares variable/initializer counts between source .st files and generated PLCopen XML.
USE WHEN: after validate_plcopen_xsd passes, to confirm no variables/initializers were silently dropped vs the .st sources.
Detects bugs where the generator silently drops variables or initializers:
  \- VARS_MISSING        — ST has more vars than XML (Bugs A/B/F)
  \- INITS_MISSING       — ST has more initializers than XML (Bug E)
  \- AT_ADDR_LOST        — ST has vars with AT %IX/QX, XML has 0 <address> tags (Bug A)
  \- POU_MISSING_IN_XML  — POU declared in .st but absent in XML

Use AFTER validate_plcopen_xsd. If XSD passes but semantic fails, the XML is
structurally valid but missing content — exactly the silent-failure scenario
that caused the 2026-05-22 incident (203 CODESYS errors).

Tolerances are configurable; defaults are permissive (-25% vars, -30% inits).

Output: { gate, valid, summary, errors[{line, location, code, message}], counts }

Input parameters:

- `filePath` (string, required): Path to PLCopen XML file (e.g. master-final.xml)
- `initsTolerance` (number): XML/ST init ratio threshold (default 0.70)
- `sourceDir` (string, required): Directory containing source .st files (recursive scan)
- `varsTolerance` (number): XML/ST var ratio threshold (default 0.75)

### `create_project_structure` (~167 tokens)

Create CODESYS Project Structure

Scaffold a standard CODESYS project directory for Festo CPX-E.
USE WHEN: starting a new CODESYS project and you need the standard folder scaffold before creating POUs.
Creates: src/0_Types, src/1_Globals, src/2_Programs, src/3_FunctionBlocks,
src/4_Functions, src/5_Library, export/xml, docs.
Set includeExamples=true to pre-populate with E_MachState, GVL_Sys, and PRG_Main stubs.
After scaffolding, create files in order: Types → GVLs → FBs → Programs → generate XML.

Input parameters:

- `includeExamples` (boolean)
- `projectDir` (string, required): Root directory
- `projectName` (string, required): Project name

### `plc_knowledge` (~504 tokens)

PLC Knowledge Base

Load embedded PLC reference documentation — the source of truth for Festo/CODESYS/EtherCAT/PLCopen.
USE WHEN: before writing ANY Structured Text (load 'conventions' + 'abbreviations' first), before generating XML (load 'ground-truth'), before motion code (load 'festo-ptp' + 'ethercat-cia402'), or whenever a technical fact is needed — never answer from memory.
Actions: 'topic' (load by name), 'search' (BM25 full-text across ALL topics + manuals), 'list_manuals', 'read_manual'.
Topics (27): conventions, abbreviations, hungarian-notation, state-machines, engineering-discipline, ground-truth, xml-rules,
  plcopen-schema, plcopen-example, plcopen-extensions, festo-cpx, festo-ptp, festo-cdpx-hmi,
  festo-vtux-terminal, festo-cmmt-st, festo-mqtt, motion-patterns, ethercat-cia402, eplan,
  hmi-web-architecture, opcua-websocket-gateway, hmi-embedded-deploy, plc-architecture-patterns,
  plc-alarm-patterns, codesys-recipe-manager, codesys-gotchas, plc-testing-twin.
Covers: Festo CPX/PtP/CMMT/MQTT, CODESYS, EtherCAT CiA 402, PLCopen XML, naming conventions, engineering discipline & quality gates, custom Web HMI + OPC-UA gateway, PLC program architecture + alarm design, recipes, testing without hardware, CODESYS gotchas, 19 device manuals.
If information is not found here, you may search the web — but suggest saving useful findings to knowledge/manuals/ for future use.

Input parameters:

- `action` (string, required): 'topic': load reference by name | 'search': full-text across ALL topics + manuals | 'list_manuals': show available manuals | 'read_manual': load complete manual
- `filename` (string): Manual filename for action=read_manual (e.g., "festo-cpx-e-system")
- `query` (string): Search term for action=search (e.g., "P-0-4014", "homing method", "CMMT fault")
- `topic` (string): Topic name for action=topic. Use "all" to load every topic concatenated.

### `debug_plc_code` (~156 tokens)

Debug PLC Code (static analysis)

Static analysis for Structured Text bugs — run BEFORE deploying to a real PLC.
USE WHEN: ST code is convention-clean and you need runtime-bug analysis, or the user reports misbehavior.
Catches: WHILE/REPEAT loops (watchdog risk), missing error handling (bErr/nErrId),
CiA 402 safety gaps (MC_Power without MC_Stop), state machine issues (missing IDLE/ERROR),
Hungarian notation violations, REAL-INT type mismatches, unused timer outputs.
Returns categorized Critical/Warning/Suggestion results.

Input parameters:

- `code` (string, required): The Structured Text code to analyze
- `context` (string): Additional context (e.g., "EtherCAT axis", "conveyor control")

### `review_st_code` (~133 tokens)

Review ST Code (naming conventions)

Validate ST code against naming conventions — returns ONLY violations, not reference dumps.
USE WHEN: immediately after writing or editing any ST code.
Checks: Hungarian notation (b=BOOL, n=INT, r=REAL, t=TIME, fb=FB instance),
POU prefixes (FB_, PRG_, FC_), FB interface pattern (bEnable/bDone/bBusy/bErr/nErrId),
state machine (0=IDLE, 90=DONE, 99=ERROR), snake_case detection.
Includes quick-reference table when violations are found.

Input parameters:

- `code` (string, required): The Structured Text code to review

### `explain_error_code` (~172 tokens)

Explain Error Code

Decode Festo/CODESYS/EtherCAT error codes using ALL embedded references.
USE WHEN: any Festo/CODESYS/EtherCAT error code appears — 0x…, 16#…, drive fault, AL status. Never guess meanings.
Accepts hex (0x7500), IEC (16#8011), or decimal formats.
Searches: CiA 402, Festo PtP, CODESYS ground truth, ALL embedded topics, and all device manuals.
If not found locally, search the web — then save useful findings to knowledge/manuals/ for future use.

Input parameters:

- `errorCode` (string, required): The error code (e.g., "0x7500", "16#8011", "MC error 4357")
- `source` (string): Error source platform

Output parameters:

- `errorCode` (string)
- `found` (boolean)
- `manualHits` (boolean)
- `message` (string)
- `snippetCount` (number)
- `source` (string)
- `sourcesMatched` (array)

### `plc_library` (~261 tokens)

PLC Function Block Library

Access the 38-block reusable ST library (30 Function Blocks + 8 shared DUTs) — ALWAYS check here BEFORE creating new FBs.
USE WHEN: about to create any FB, or looking for ready-made motor/valve/PID/sensor/safety logic.
Actions: 'search' (keyword match), 'list' (browse by category), 'get' (full source code).
Categories: types (8), motion (4), actuators (5), sensors (4), safety (2), system (5), utilities (10).
Contains ready-to-use blocks for motors, valves, PID, sensors, safety, and more.
DO NOT create a new FB if a similar one already exists here.

Input parameters:

- `action` (string, required): 'search': find blocks by keyword | 'list': browse all blocks (optionally by category) | 'get': retrieve full .st source code
- `category` (string): Filter by category for action=list, or category hint for action=get
- `name` (string): Block name for action=get (e.g., "FB_StandardMotor", "E_AxisState")
- `query` (string): Search term for action=search (e.g., "motor", "temperature", "pid")

### `plc_lookup` (~207 tokens)

PLC Quick Lookup

Quick lookup for PLC conventions and error codes — instant answers without loading full knowledge topics.
USE WHEN: you need a single fact — prefix, state number, error code — without loading a full topic. Try this BEFORE plc_knowledge for point lookups.
Actions: 'hungarian' (type→prefix), 'type_prefix' (POU→prefix), 'state' (state number→name),
'error_code' (decode Festo/CiA402/CODESYS error), 'fb_interface' (standard FB pattern), 'list_standard' (full reference).

Input parameters:

- `action` (string, required): 'hungarian': get prefix for a type | 'type_prefix': get prefix for POU type | 'state': decode state number | 'error_code': decode error | 'fb_interface': show standard FB pattern | 'list_standard': f…
- `value` (string): The value to look up (type name, POU type, state number, or error code)

Output parameters:

- `action` (string)
- `details` (object)
- `found` (boolean)
- `message` (string)

### `plc_validate` (~267 tokens)

PLC Code Validator

Validate PLC code against conventions — composable validators with consistent results.
USE WHEN: you need to check ST against conventions programmatically — naming, FB interface, or state machine — without a full review.
Actions: 'naming' (check variable names + Hungarian notation), 'fb_interface' (check FB pattern),
'state_machine' (check nState pattern), 'batch' (validate multiple items at once).
Returns {valid, message, details} for each check.

Input parameters:

- `action` (string, required): 'naming': check variable/POU naming | 'fb_interface': check FB bEnable/bDone pattern | 'state_machine': check nState 0/90/99 | 'batch': multiple validations
- `code` (string): ST code to validate (for fb_interface, state_machine)
- `items` (string): JSON array of {type, input, extra?} for batch mode
- `pouName` (string): POU name (for naming action with pouType)
- `pouType` (string): POU type: functionBlock, program, enum, struct (for naming action)
- `typeName` (string): Type name like BOOL, INT, REAL (for naming action)
- `varName` (string): Variable name (for naming action)

Output parameters:

- `action` (string)
- `details` (object)
- `failed` (number)
- `message` (string)
- `passed` (number)
- `results` (array)
- `valid` (boolean)

### `st_symbols` (~254 tokens)

ST Symbols (cross-file outline & definition)

Index a directory of .st files and navigate symbols across files — dialect-aware (CODESYS V3.5), comment/string-safe, better than grep.
USE WHEN: you need to navigate an existing .st project — outline symbols or resolve a definition across files (better than grep).
Actions:
  'outline'    — project map. Returns top-level symbols (functionBlock/program/function/enum/struct/gvl) by default;
                 pass kindFilter to include vars/members (e.g. ["inputVar","globalVar"]).
  'definition' — resolve a name (case-insensitive) to its definition(s); requires 'name'.
Notes: sourceDir must be inside the workspace unless FESTO_MCP_ALLOW_OUTSIDE_WORKSPACE=1.
Line numbers and find-references arrive in a later version (this version returns file + container).

Input parameters:

- `action` (string, required): 'outline' = project map | 'definition' = resolve a name
- `kindFilter` (array): Filter by SymbolKind (e.g. ["functionBlock","globalVar"])
- `name` (string): Symbol name (required for action=definition)
- `sourceDir` (string, required): Directory containing .st files (recursive scan)

Output parameters:

- `action` (string)
- `fileCount` (number)
- `sourceDir` (string)
- `symbolCount` (number)
- `symbols` (array)

### `st_find_references` (~200 tokens)

ST Find References (where-used)

Find all references (usages) of an ST identifier across a directory of .st files — token-aware and comment/string-safe (unlike grep: ignores comments, strings, typed literals, and substring matches).
USE WHEN: you need every usage of an ST identifier across files before renaming or refactoring.
Each reference carries file, line/column, the line text, the containing POU, whether it is the declaration site, and disambiguation hints (e.g. resolves E_X.MEMBER member access via the qualifier).
Note: sourceDir must be inside the workspace unless FESTO_MCP_ALLOW_OUTSIDE_WORKSPACE=1.

Input parameters:

- `caseInsensitive` (boolean): IEC is case-insensitive (default true)
- `includeDeclaration` (boolean): Include the declaration site (default false)
- `name` (string, required): Identifier to search for (whole token)
- `sourceDir` (string, required): Directory containing .st files (recursive scan)

Output parameters:

- `definitions` (array)
- `name` (string)
- `referenceCount` (number)
- `references` (array)
- `sourceDir` (string)

## Diagnostics

Captured diagnostic sections: Provenance, Dependencies. The full working is on the page: https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp#diagnostics

## Score history

- 2026-08-03: 61
- 2026-08-02: 57
- 2026-08-01: 46
- 2026-07-31: 21
- 2026-07-30: 46
- 2026-07-28: 46
- 2026-07-27: 46

## Links

- npm package: https://www.npmjs.com/package/festo-codesys-mcp
- Socket report: https://socket.dev/npm/package/festo-codesys-mcp
- Changelog RSS feed: https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp/changelog.xml
- Changelog JSON feed: https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp/changelog.json
- HTML version of this page: https://verifymcp.io/servers/efranceschetti-festo-codesys-mcp/festo-codesys-mcp
