Welcome to the Horner Cscape Model Context Protocol (MCP) Server project! We are excited to welcome contributors from industrial automation, software engineering, and artificial intelligence disciplines.
This document outlines the engineering directives, safety policies, development workflows, and coding standards required to contribute effectively to this repository.
The mission of Horner Cscape MCP Server is to provide a deterministic, industrial-grade Model Context Protocol (MCP) bridge connecting modern AI engineering clients with Horner APG Cscape 10.2 (Build 10.2.751.4) and native .csp / .cpj Compound File Binary Format (CFBF) project containers.
Our goal is to enable AI-assisted logic generation, offline syntax validation, and deterministic simulation while strictly preserving air-gapped industrial safety, fail-closed hardware lockout, and zero physical PLC risk.
- Safety Over Convenience: In industrial automation, an incorrect command or unauthorized controller download can damage physical machinery or endanger personnel. Our safety guards are immutable and fail-closed.
- Deterministic & Cycle-Accurate: Software verification and simulation must yield predictable, repeatable results without relying on unverified runtime processes.
- Evidence-Gated Progression: Every assertion, compilation, and simulation result must produce verifiable deliverables and honest status reporting. Premature victory declarations or silent mocks are prohibited.
- Clean Architectural Boundaries: High-level AI tools must interact through standardized MCP protocols without corrupting GUI state or bypassing safety boundaries.
All contributors must adhere to the following four core invariants. Pull requests that violate any of these rules will be rejected immediately without exception.
To guarantee air-gapped industrial safety, the codebase enforces an absolute ban on automated hardware communication and flashing:
- Physical Communication Port Lockout: Code must never open, probe, or scan physical serial ports (
COM1–COM256,\\.\COM*,/dev/tty*), industrial fieldbuses (CAN*,CsCAN,DeviceNet,Profibus), USB debuggers, or hardware bridges. Any attempt will immediately raiseHardwareLockoutError. - Zero Automated PLC Downloads: Automated controller downloading, firmware updating, and flash operations are barred. Physical downloads are deferred exclusively to manual execution by authorized commissioning engineers in Phase P7.
- Companion Flashing Utility Lockout: Execution of controller flashing binaries (
PGMUpdateUtility.exe,DfuSeCommand.exe,STMFlashLoader.exe,WinJTAG.exe) is intercepted and prohibited. - CLI Switch Lockout: Passing download/flash flags (
/d,/download,/flash,/burn,/write-flash) raisesDangerousArgumentError. - Win32 Download Message Lockout: The GUI automation layer intercepts and blocks Win32 download command IDs:
ID_PROGRAM_DOWNLOAD = 32827(BLOCKED)ID_CONTROLLER_DOWNLOAD = 33149(BLOCKED)
- Honest Telemetry (
verified_live = false): Never generate synthetic live confirmations or declareVERIFIED_LIVEwithout genuine, signed physical hardware telemetry.
- Pure IEC 61131-3 Structured Text: All logic Program Organization Units (POUs) must be written exclusively in standard IEC 61131-3 Structured Text (
.st). - Ladder Logic Construct Interception: Any ladder logic artifacts introduced into
.stfiles are rejected fail-closed with error codeERR_LADDER_FORBIDDEN(LadderConstructRejectedError).- Prohibited constructs include: ASCII contacts (
---[ ]---,---[/]---), coils (---( )---,---(S)---,---(R)---,---(L)---), rung markers (RUNG,END_RUNG,NETWORK), and instruction mnemonics (XIC,XIO,OTE,OTL,OTU).
- Prohibited constructs include: ASCII contacts (
- ST→LD Language Conversion Reality (
BLOCKED_NATIVE: DOCUMENT_ONLY):- Horner Cscape 10.2 maintains an architectural separation between its legacy Advanced Ladder solver and its IEC 61131-3 engine.
- Cscape 10.2 contains zero GUI menus, commands, or DLL exports for ST→LD conversion.
- Offline AST-based translation and ASCII diagram synthesis are supported via
STLadderInteropGuardfor engineering analysis, but in-GUI language conversion is permanently blocked (BLOCKED_NATIVE).
- Exclusive Window Handle Ownership: Exactly ONE designated automation or watchdog process may drive live Cscape GUI window handles (
HWND) on the interactive desktop (winsta0\Default). - Headless Concurrency: All other subagents, automated test suites, linters, and background jobs MUST execute headlessly or perform non-intrusive read-only queries.
- Keep Cscape Visible: During live GUI test runs,
Cscape.exemust remain open and visible withTankLevelClosedLoop.cspand the Project Navigator loaded. - Fail-Closed GUI State: If Cscape is closed, hidden, minimized, or its main window handle is unavailable, live GUI tools must fail closed immediately (
status: blockedorstatus: failed). Simulating synthetic GUI successes is strictly forbidden.
- Straton K5 Quarantine: Standalone Straton K5 templates (
appli.k5p,appli.CPO,K5DBXS.INI) remain strictly quarantined underquarantine/straton_k5_legacy/. Never import, execute, or reintroduce dependencies on quarantined files. - Pure-Software Simulation: POUs simulate cycle-by-cycle in pure software (
SimulationBackend.EMULATED) without requiring proprietary runtime processes (T5SIMUL,T5RTI).
Every MCP tool, test suite assertion, and API payload must adhere to the 4-state status specification:
{
"status": "success | failed | blocked | inconclusive",
"error_code": "STRING_ENUM_OPTIONAL",
"details": "Factual description of outcome",
"data": {}
}| Status | Definition |
|---|---|
success |
All assertions passed deterministically, valid deliverables created, and verifiable evidence logged. |
failed |
Execution failed due to syntax error (ST_SYNTAX_ERROR), ladder injection (ERR_LADDER_FORBIDDEN), simulation mismatch, or compiler failure. |
blocked |
Operation actively prevented by safety policy (hardware port ban, download lockout) or native platform limitation (BLOCKED_NATIVE). |
inconclusive |
Preconditions unverified, environment unready, or outcome cannot be validated deterministically. |
Warning
Never invent or return subjective statuses such as VERIFIED, 100%, PERFECT, or ALL_TESTS_PASSING. Always use the strict 4-state contract.
- Operating System:
- Windows 10 / 11 (64-bit): Required for live Cscape Win32 GUI automation (
pywinauto,ctypes). - Linux / macOS: Fully supported for headless development, pure-ST parsing, AST validation, security guard testing, and software simulation.
- Windows 10 / 11 (64-bit): Required for live Cscape Win32 GUI automation (
- Python: Version 3.10 or higher (tested on 3.10, 3.11, and 3.12).
- Cscape IDE (Optional for offline development; required for live GUI gate tests):
- Horner APG Cscape 10.2 (Build 10.2.751.4).
We recommend using either venv or uv for environment management.
# Clone the repository
git clone https://github.com/your-org/horner-cscape-mcp.git
cd horner-cscape-mcp
# Create and activate virtual environment
python -m venv .venv
.venv\Scripts\Activate.ps1 # On Windows
# source .venv/bin/activate # On Linux/macOS
# Upgrade packaging tools
pip install --upgrade pip setuptools wheel# Create virtual environment with uv
uv venv .venv
.venv\Scripts\Activate.ps1
# Install project and development dependencies
uv pip install -e .
uv pip install pytest pytest-cov mypy ruff blackInstall the package in editable mode with development tooling:
pip install -e .
pip install pytest pytest-cov mypy ruff blackTo maintain developer convenience across local environments, core configuration files, agent rules, and test suites are synchronized between:
- Primary Workspace:
C:\HornerAI\horner-cscape-mcp\ - User Environment:
C:\Users\ArmandoSilva\
Note: Dual-root parity is an environment synchronization task and is not an acceptance gate for milestone closure.
- PEP 8 Conformance: Follow standard PEP 8 formatting conventions.
- Type Annotations: All function signatures, methods, and module-level constants must have complete, explicit type annotations. Use Python's
typingmodule and standard collections. - Pydantic Models: FastMCP tool schemas and data exchange objects must be defined using Pydantic v2
BaseModelwith explicit field validation and documentation. - Path Sandboxing & Hygiene:
- Always use
pathlib.Pathinstead of string operations for filesystem paths. - Validate all paths through
src.security.sandbox.PathSandboxto prevent directory traversal (..), Alternate Data Streams (:stream), and DOS reserved device names (CON,PRN,AUX,NUL,COM1–COM9,LPT1–LPT9).
- Always use
- Exception Hierarchy: Derive custom exceptions from
src.security.exceptions.SecurityErrororsrc.cscape.exceptions.CscapeError. Never use bareexcept:clauses.
- All Structured Text files must strictly conform to IEC 61131-3 3rd Edition.
- Data types must be standard:
BOOL,INT,DINT,REAL,TIME,STRING, etc. - Variables must follow standard Horner OCS memory mapping conventions (
%R,%AI,%AQ,%I,%Q,%M,%SR) when bound to hardware registers. - No silent fallback: If an ST POU contains syntax or ladder anomalies, reject immediately with precise line and column diagnostic markers.
All contributions must include thorough unit and integration tests under the tests/ directory.
- Deterministic Tests Only: Tests must run deterministically without race conditions or non-deterministic
time.sleep()calls. - Running the Test Suite:
# Run the full test suite pytest -v --strict-markers --basetemp=.pytest_temp # Run security lockout validation pytest -v tests/test_security.py # Run Pure ST vs Ladder interop guard tests pytest -v tests/test_st_ld_interop.py # Run FastMCP status contract verification pytest -v tests/test_mcp_status_contract.py # Run PLC simulation tests pytest -v tests/test_simulation.py
- No Silent Mocks: Mocks must never simulate successful live physical controller interactions or bypass safety gates. If physical hardware is required and absent, the test must yield
status: blockedor cleanly skip. - Temporary Directories: Always isolate file generation during tests using pytest's
tmp_pathfixture or--basetemp=.pytest_temp.
main: The default, production-ready branch. Must always pass all security and unit tests.feature/<feature-name>: New capabilities, MCP tools, or simulation features.fix/<bug-name>: Bug fixes and issue resolutions.docs/<topic>: Documentation updates, guides, and specification updates.safety/<policy>: Security guardrails and lockout policy hardening.
We enforce Conventional Commits v1.0.0. Each commit message should follow this format:
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
feat: A new feature or MCP tool.fix: A bug fix.safety: Hardening of security policies, port bans, or download lockouts.docs: Documentation-only changes.test: Adding or correcting tests; no production code changes.refactor: A code change that neither fixes a bug nor adds a feature.chore: Maintenance tasks, dependency updates, or build configuration.
feat(mcp): implement cscape_validate_st with AST diagnostic markers
safety(lockout): intercept Win32 controller download command ID 33149
test(st-guard): add unit tests for ERR_LADDER_FORBIDDEN detection
docs(contributing): align contributing guide with enterprise open-source standards
Before submitting a pull request, ensure you have completed each item:
- Core Invariants Preserved:
- Zero physical port connections or hardware communications.
- Zero automated download or flashing commands.
- Pure ST enforcement verified (
ERR_LADDER_FORBIDDEN). - Single GUI Owner boundary (
winsta0\Default) respected.
- Tests Pass:
pytest -v --strict-markerspasses with 0 failures. - Type & Style Check: Code passes
mypyandruff/blackformatting. - Status Contract: All new MCP tool responses adhere to the 4-state contract (
success | failed | blocked | inconclusive). - No Large Binary Archives: Large zip archives (
*.zip),.bin,.hex, or core memory dumps are excluded from git. - Secrets Scrubbed: No API tokens, passwords, private keys, or personal credentials are included in code or commit history.
We are committed to providing a welcoming, inclusive, and harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity, level of experience, nationality, personal appearance, race, religion, or sexual identity.
This project has adopted the Contributor Covenant (version 2.1). By participating in this project, you agree to abide by its terms.
For complete details, please read our CODE_OF_CONDUCT.md.
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the project maintainers. All complaints will be reviewed and investigated promptly and fairly, with full respect for the confidentiality of the reporter.
# 1. Activate environment
.venv\Scripts\Activate.ps1
# 2. Run core security verification
pytest -v tests/test_security.py
# 3. Run Structured Text guard verification
pytest -v tests/test_st_ld_interop.py
# 4. Run MCP status contract tests
pytest -v tests/test_mcp_status_contract.py
# 5. Run full test suite
pytest -v --strict-markers --basetemp=.pytest_tempThank you for helping build a safe, robust, and deterministic bridge between artificial intelligence and industrial automation!