0
0
Fork 0
Commit graph

47 commits

Author SHA1 Message Date
steel
320646b8fe fixup
Some checks failed
CI / build-and-test (18.x) (push) Has been cancelled
CI / build-and-test (20.x) (push) Has been cancelled
CI / build-and-test (22.x) (push) Has been cancelled
2026-08-19 18:39:47 +08:00
Karstein Phobic Nyvold Kvistad
0d1d504d30 Add --codesys-additional-folder so installer-managed installs get their plugins
The CODESYS Installer registers add-on packages (Script Engine included) into
<install>\CODESYS\AdditionalFolders\<InstallationName>\, each with its own
profile.xml reusing the SAME <ProfileName> as the bare base profile. Launching
with --profile alone resolves to the base profile, which on such a box can have
zero plugins registered.

Symptoms this fixes:

  - "The command line option 'runscript' has been set. However, there is no
    script engine implementation available" -- the watcher never runs, so every
    tool fails with "Watcher did not signal ready within 60000ms".

  - A load dialog that reads as a contradiction: "created with CODESYS V3.5 SP19
    Patch 2 and contains data that cannot be loaded by CODESYS V3.5 SP19
    Patch 2". Same profile name, different plugin set.

Observed on this box: three profiles all named "CODESYS V3.5 SP19 Patch 2",
with 0 / 118 / 161 plugins registered. Only the 161 one has the Script Engine.
The Start Menu shortcut the installer generates already passes
--additionalfolder=; the server now can too.

detect.ts ranks every AdditionalFolders\* by registered plugin count and emits
the fullest in --detect / --print-config. Installs without AdditionalFolders are
unaffected and get no flag.
2026-07-24 15:03:27 +02:00
Karstein Phobic Nyvold Kvistad
a4f8426369 version pin: refuse to save a project on a mismatched CODESYS install (v0.14.0)
The open_project pre-flight was supposed to prevent this, but it reads
the project's profile from projectinspectiondata.auxiliary inside the
.project ZIP -- and a plain .project is NOT a ZIP. Verified across
3.5.19.20 .. 3.5.22.10: magic 23 89 ED 33, unzip -l fails, no plaintext
profile string. So inspectProjectFile always throws, the pre-flight
catches and proceeds, and the guard is dead code on real projects.
It also only ever covered open_project -- not the release pipeline.

Consequence in the field: a server bound to SP21 Patch 5 opened and
re-saved a 3.5.19.20 vessel project during release_project_version.
4,639,776 -> 4,688,496 bytes, committed and tagged. The tagged binary
stopped being the software on the boat.

Since the version cannot be recovered from the file, pin it in the repo.
New src/version-pin.ts resolves, most specific first:
  1. .codesys-version next to the .project (one line, "3.5.19.20" or
     "CODESYS V3.5 SP19"; comments and blanks skipped) -- the only
     option when seeding a project with no release history
  2. library.md's "CODESYS Development System" row -- every project
     gets a pin for free after its first release

Policy is asymmetric so it guards the dangerous path without breaking
existing repos: bump_project_version and release_project_version refuse
on mismatch AND on no-pin; get_project_info, mirror_export and
list_project_libraries only warn on mismatch and proceed when unpinned.
Both saving tools accept allowVersionUpgrade: true to override.

Parsing note: library.md's row carries no dotted profile version, so it
is matched on the SP/Patch label only -- a naive version regex would
otherwise bind to the ScriptEngine's 4.2.0.0. Covered by a regression
test.

25 new unit tests; suite 180/180.

Also fixes an unrelated pre-existing test failure: the ASCII-only script
template check used readdirSync without filtering, so a local untracked
src/scripts/__pycache__/ made it fail with EISDIR.
2026-07-24 14:18:01 +02:00
Karstein Phobic Nyvold Kvistad
4c5ec53473 docs: README fork-changes narrative for SP21 coverage and v0.12.1 hardening 2026-06-12 14:27:56 +02:00
Karstein Phobic Nyvold Kvistad
5fbe5687de docs+chore: README sections for phases 2-5, plan status, bump to 0.12.0
102 tools total. SP21 ScriptEngine functional coverage complete per plan
(SVN/Composer/Cloud deliberately out of scope; plug_module and trace
tools deferred).
2026-06-12 13:15:26 +02:00
Karstein Phobic Nyvold Kvistad
6d95c4698d docs+chore: README online-tools table for phase 1, bump to 0.11.0 2026-06-12 12:52:57 +02:00
Karstein Phobic Nyvold Kvistad
dead49ada0 fix: never fall back to headless --noUI in persistent mode (v0.10.3)
Persistent mode now uses a LazyPersistentExecutor everywhere the launcher
is not running: --no-auto-launch before first use, after shutdown_codesys,
and after a launch conflict. The first tool call launches the VISIBLE IDE
and delegates; nothing silently spawns --noUI processes anymore.

Why: headless spawns pop modal dialogs nobody can see (tool calls just
abort), hold .project locks (stale .~u files), and leave orphaned
CODESYS.exe processes that then block the next launch. Diagnosed live on
2026-06-11 while deploying TestN2k_v2_Fable: open_project/download ran
headless via the --no-auto-launch fallback and burned ~30 min on invisible
dialogs, zombie PIDs and lock-file cleanup.

Headless execution now requires explicit opt-in: --mode headless or
--fallback-headless.

Also lands the task-configuration tools from the 2026-06-09 session that
were complete but uncommitted: list_tasks, add_pou_to_task,
remove_pou_from_task (+ their IronPython scripts).
2026-06-11 14:15:50 +02:00
Karstein Phobic Nyvold Kvistad
a037025303 docs: add OpenAI Codex CLI (config.toml) setup instructions
The server is a standard stdio MCP server and works with any MCP client, not
just Claude Code. Added a "Use with OpenAI Codex CLI" section covering the
~/.codex/config.toml location, the [mcp_servers.<name>] TOML table (the
equivalent of the --print-config JSON block), env-based credential injection,
tool_timeout_sec for slow CODESYS launches, and the codex mcp add shortcut.
Linked it from Quick Start step 3.
2026-06-10 09:59:20 +02:00
Karstein Phobic Nyvold Kvistad
4b82b7c569 chore: nuke phobiCS-tui front-end (v0.10.0)
The phobiCS-tui CLI/UI is retired in favour of driving the codesys-mcp-sp21-plus
MCP tools directly from Claude Code (see https://docs.anthropic.com/claude-code).
The MCP server itself is unchanged; only the TUI front-end goes.

Removed:
- src/tui/ (browser + approve + shared + entry; 14 files)
- dist/tui/ (compiled output)
- tests/tui/ (14 .test.* files + the mini-mirror fixture tree)
- tsconfig.tui.json
- 3 superpowers plans/specs docs (2026-04-28 phobics-tui v0.1-v0.2, 2026-04-29 v0.3-live-values, 2026-04-28 tui-design)
- package.json: phobiCS-tui bin entry, build:tui script, TUI compile step in build, TUI typecheck step
- package.json: dependencies ink + react + diff (TUI-only); devDependencies @types/diff + @types/react + ink-testing-library
- README.md: ## phobiCS-tui section + ### Inline live values subsection

Git history side:
- Worktree .worktrees/phobics-tui removed (was on feature/phobics-tui-followup @ 7e427e9)
- Local + origin branches deleted:
  - feature/phobics-tui              (was 08ee361, 0 unmerged vs origin/main)
  - feature/phobics-tui-followup     (was 7e427e9, 0 unmerged vs origin/main)
  - feature/phobics-tui-v0.3-live-values (was 9f4dc48, 0 unmerged vs origin/main)
- All three branches were merged into main, so deleting refs loses no history --
  the commits remain reachable through main.

Knock-on (deliberately deferred):
- src/approve-gate.ts and the --approve-edits flag in src/bin.ts / src/server.ts
  still exist. With the TUI gone, the gate auto-approves at every prompt and
  prints a `[approve-gate] No TTY available -- phobiCS-tui cannot render` warning
  to stderr. The infrastructure also still has callers in the uncommitted
  add_device work, so a clean rip-out is left for a follow-up.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 17:48:28 +02:00
Karstein Phobic Nyvold Kvistad
4236ab07ad docs(readme): document 7 missing tools (network scan/rebind, device user mgmt, remove_library, read_running_version_ssh); bump tool count 41 -> 48 2026-05-12 16:42:15 +02:00
phobicdotno
403a4336ae
fix: no headless fallback by default + clear stale lastError (v0.9.2) (#19)
* fix: disable headless fallback by default

Persistent mode silently fell back to running CODESYS with --noUI
whenever the launch refused (e.g. another GUI instance was already
running). That left the user staring at no window while the MCP
spawned hidden processes per command. Flip the default of
--fallback-headless to false so the MCP errors out loudly instead;
opt in explicitly if silent --noUI is actually wanted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix: clear stale lastError on launch retry and successful ready

get_codesys_status kept reporting historical "Last Error: Refusing
to launch..." messages forever because lastError was set on failure
but never reset. Reset to null at the top of launch() so a retry
starts clean, and again when the watcher signals ready so a
successful re-launch wipes prior errors.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* release: v0.9.2 -- no headless fallback by default + clear stale lastError

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Karstein Phobic Nyvold Kvistad <karstein.kvistad@maritimerobotics.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 20:16:01 +02:00
Karstein Phobic Nyvold Kvistad
b0dadbd5e8 docs: drop redundant 'This fork:' self-link in README header
The line pointed back to phobicdotno/Codesys-MCP-SP21-plus, which is
the URL the visitor is already on when they're reading this on
GitHub. Upstream + npm + maintainer lines give enough provenance for
visitors arriving from npmjs.com or via search.
2026-04-29 18:13:08 +02:00
Karstein Phobic Nyvold Kvistad
9f4dc4864d docs: README section for --live-values inline overlay
Documents the v0.3 live-values pump + TUI overlay:
- example output showing the inline '◀ live: <val>' annotations
- 500 ms server poll, 5 s TUI freshness window
- snapshot keyed by pou_name to reject stale POU views
- v0.3 scope: top-level vars only (deferred sub-property + ARRAY/STRUCT)
2026-04-29 09:59:01 +02:00
Karstein Phobic Nyvold Kvistad
6d5d9b0385 docs: README for v0.2 followup (TUI keybinds + 9-tool gating)
Updates the phobiCS-tui section to cover the new keybinds (/, o, d,
r, ?, v) and documents that --approve-edits now gates all 9
modifying MCP tools (create_pou, create_property, create_method,
create_dut, create_gvl, create_folder, delete_object, rename_object,
add_library) on top of the existing set_pou_code.

Also notes the Viewer syntax highlighting and the statusbar's
mirror-staleness indicator + small-terminal resize warning.
2026-04-29 08:22:09 +02:00
phobicdotno
065bce5b3d
Merge pull request #1 from phobicdotno/feature/phobics-tui
phobiCS-tui v0.1/v0.2: in-fork TUI for CODESYS exported ST + --approve-edits gate
2026-04-29 08:21:34 +02:00
Karstein Phobic Nyvold Kvistad
2c19eca4b3 test+docs(symbol-config): 10 vitest e2e prep tests + README + function-test entry
vitest tests/integration/e2e.test.ts:
  - 10 new template-prep assertions, one per Symbol Configuration tool.
    Each asserts no leftover {PLACEHOLDER} in the rendered script and
    that the relevant CODESYS API method names appear (get_all_signatures,
    application.create_symbol_config, configured_access, etc.).
  - Drive-by: fix the existing add_library e2e test that was missing the
    ALLOW_UNRESOLVED placeholder (added when the resolution gate landed
    in d414c77). Test was previously failing on /\{[A-Z_]+\}/ regex.

Suite is now 107/107 green (excluding the orphan .worktrees/phobics-tui
suite that's been failing pre-this-change).

README.md:
  - Tool count 31 -> 41.
  - New "Symbol Configuration Tools" section under Library Management
    with one row per tool.
  - Project-structure tool count footnote updated.

docs/function-test-2026-04-28.md:
  - Append "Symbol Configuration tools (added 2026-04-28 evening)" block
    with a per-tool vitest/live status grid.
  - Live SP22 column is deferred: the MCP tool list is negotiated at
    Claude Code session start and doesn't refresh mid-session, so the
    new tools aren't callable in the session that built them. Document
    the round-trip cycle so a fresh session can run it.
  - Note the SymbolAccess enum-value probe risk per the plan
    (docs/superpowers/plans/2026-04-28-symbol-config-tools.md).

Python 3 ast.parse run against all 10 new + 1 helper scripts -- 11/11
parsed cleanly (catches the obvious IronPython 2.7 syntax issues that
Py3 would also flag).
2026-04-28 23:52:34 +02:00
Karstein Phobic Nyvold Kvistad
08ee361e9d docs: README section for phobiCS-tui + --approve-edits
Documents the new TUI bin and the opt-in approve-edits flag:
- browser invocation (auto-discovery and explicit path)
- approve invocation
- keybindings for both modes
- state file path on Windows vs POSIX, and the get_user_selection
  bridge that lets an agent ground its actions in the current
  selection
- --approve-edits scope: v0.1 gates only set_pou_code
2026-04-28 22:33:17 +02:00
Karstein Phobic Nyvold Kvistad
fec74e8943 docs: lowercase the doc filenames -- stop shouting in paths 2026-04-28 22:20:21 +02:00
Karstein Phobic Nyvold Kvistad
ab0b30e436 docs: rename "smoke test" -> "function test"
Both the per-day verification docs and the references to them.

git mv preserves history:
  docs/SMOKE-TEST-2026-04-25.md -> docs/FUNCTION-TEST-2026-04-25.md
  docs/SMOKE-TEST-2026-04-28.md -> docs/FUNCTION-TEST-2026-04-28.md

Internal H1 + footer line updated to match. README.md and
OPEN-BUGS-CROSS-REFERENCE.md links retargeted.
2026-04-28 22:17:09 +02:00
Karstein Phobic Nyvold Kvistad
f34d002601 feat(online): pre-register Device User credentials to suppress modal login dialog
WHY: connect_to_device and download_to_device against a password-protected
runtime pop a modal "Device User Login" dialog in the IDE. IronPython can't
marshal to the WPF UI thread to dismiss it, so headless / agent-driven
sessions block forever -- and even for interactive use, the dialog pops on
EVERY download, which is a constant friction point.

API: ScriptOnline.set_default_credentials(username, password) was added in
CODESYS scripting API 3.5.3.0. Effect lasts until end of the current script
execution. Source: https://content.helpme-codesys.com/en/ScriptingEngine/ScriptOnline.html

Implementation:

- New helper script src/scripts/register_device_credentials.py defines a
  register_device_credentials_if_set() function that no-ops when DEVICE_USER
  or DEVICE_PASSWORD is empty, gracefully skips on older SPs that lack
  set_default_credentials, and never raises (always falls back to the
  current dialog-prompting behaviour).

- connect_to_device.py and download_to_device.py call the helper as the
  FIRST action inside their try blocks, before ensure_project_open and
  any login() attempt, so credentials are registered before any code path
  that could trigger the dialog.

- server.ts adds optional deviceUser / devicePassword args to both tools'
  input schemas. Resolution order:
    args.deviceUser     (per-call override)
    -> process.env.CODESYS_DEVICE_USER
    -> '' (empty, dialog pops as before)
  Same for devicePassword. Env-var path is the recommended config:
    claude mcp add -s user codesys-sp22-patch1 \
      -e CODESYS_DEVICE_USER=Karstein \
      -e CODESYS_DEVICE_PASSWORD=codesys123 \
      -- codesys-mcp-sp21-plus --codesys-path ... --codesys-profile ... \
         --mode persistent --no-auto-launch

Backward compat: when both creds are empty (default for existing users),
the helper short-circuits and behaviour is byte-identical to 0.5.x. No
regression. Verified by smoke-testing prepareScriptWithHelpers locally
with both filled and empty inputs -- function definition + callsite are
both wired in either case; only set_default_credentials() is suppressed
when empty.

README updated for connect_to_device and download_to_device tool rows.
Version bumped 0.5.0 -> 0.6.0.
2026-04-28 21:41:31 +02:00
Karstein Phobic Nyvold Kvistad
722c09ed70 feat(ssh): restart_runtime_ssh -- restart codesyscontrol over SSH (password auth + sudo -S + port-listen liveness probe)
WHY: an unlicensed CODESYS Control runtime drops out of demo mode every 2
hours. systemctl is-active reports "active" even after the binary has
died, so a TCP probe on the runtime port (default 11740) is the only
honest liveness signal. The new tool gives MCP a one-call path to bring
the runtime back without dropping into a terminal.

Implementation choices:

- ssh2 (npm) instead of spawning ssh/sshpass: sshpass is not on the
  default Windows path, and the target Pi's sshd 10.x rejects pubkey
  signatures from this client environment in practice. ssh2 handles
  password auth + remote stdin + exit-code capture cross-platform.
- sudo -S with the password fed on remote stdin -- avoids a NOPASSWD
  sudoers entry on the PLC.
- After issuing the restart, polls 'ss -tln | grep :<port>' once per
  second until the listen port is up or livenessWaitSeconds expires.
  This is what catches a half-dead runtime that systemctl reports as
  fine.

Defaults match the only Pi we currently target (codesys-pi.local /
karstein / codesys123 / codesyscontrol / port 11740) but every field
is overridable.

Smoke-tested against codesys-pi.local: restart exit 0, port back up
after ~3s.
2026-04-28 16:50:19 +02:00
Karstein Phobic Nyvold Kvistad
b3d7a6fa64 feat(open_project): pre-flight profile-mismatch check using offline .project inspection
Before delegating to CODESYS for the actual open, inspect the
.project's projectinspectiondata.auxiliary (via src/inspect.ts -- pure
offline, ZIP+XML, no CODESYS) and compare its saved SP+patch against
the server's configured --codesys-profile.

Three outcomes:
- exact match -> proceed silently
- same SP, different patch -> proceed with a warning prefix in the
  response (CODESYS will pop its patch-difference dialog)
- SP mismatch -> refuse without opening; suggest the user either pick
  a different MCP server entry or run --print-config --for-project to
  generate one for the project's required SP

If inspection itself fails (file missing, malformed .project, profile
unparseable), pre-flight falls through silently -- the existing CODESYS
open path then produces its original error.
2026-04-27 22:32:53 +02:00
Karstein Phobic Nyvold Kvistad
7c74249e1b feat(cli): --print-config --for-project <path> picks the install that opens the project
Run --print-config with --for-project pointing at a .project file
and the snippet narrows to just the install(s) that can open it
(exact SP+patch match, or fallback to same-SP-different-patch with
a warning about the conversion dialog). No more eyeballing -- the
project's projectinspectiondata.auxiliary tells us which CODESYS
to route to, and --for-project just looks it up.

Mutually exclusive with --sp. Errors are explicit (no install
matches at all, or both flags supplied).
2026-04-27 22:27:31 +02:00
Karstein Phobic Nyvold Kvistad
be42f60488 fix(mirror): per-project mirror dir name when multiple .project files share a parent
The default mirror root was hard-coded to <projectDir>/mcp-mirror/,
which collides when two .project files live in the same folder
(e.g. \files\...\Multi plc test\ProjectA.project +
ProjectB.project both default to the same mirror -- each
mirror_export call clobbers the other's output).

New resolution rule (preserves backward-compat -- existing setups
unaffected):
- If <projectDir>/mcp-mirror/ already exists, use it
- Else if exactly one .project sibling, use <projectDir>/mcp-mirror/
- Else (multiple .project) use <projectDir>/<basename>_mcp_mirror/

Implemented as src/mirror-paths.ts (TS helper, used by server.ts
maybeOpenMirrorInVscode and unit-testable) plus the same logic
inlined in the Python scripts that need it (mirror_export.py et al.,
no shared-import infra exists CODESYS-side).
2026-04-27 22:22:09 +02:00
Karstein Phobic Nyvold Kvistad
37fc80764e feat(ssh): read_running_version_ssh -- read PLC project version over SSH, no CODESYS needed
New MCP tool + --ssh-version CLI flag. Bypasses the CODESYS IDE
entirely: SSH to a CODESYS Control Linux PLC, sudo strings the boot
application binary, extract the X.Y.Z.W literal of
_MCP_PROJECT_VERSION.sVersion. Filters out 3.5.x.y CODESYS runtime
versions automatically.

Solves the case where the .project file is locked by another CODESYS
instance, or no CODESYS install is reachable, but the PLC is. Read-
only on the PLC (just strings the boot binary).

Requires SSH key auth + passwordless sudo for /usr/bin/strings on
the PLC. Both error paths surface exact-instructions error messages
(PowerShell key install command, sudoers line) instead of opaque
failures.

Smoke-tested against codesys-pi (RPi running CODESYS Control 3.5.22)
with MCPTest2 v1.5.0.0 downloaded -- correctly extracts 1.5.0.0 and
filters out the 3.5.22.0 runtime version literal.
2026-04-27 22:13:29 +02:00
Karstein Phobic Nyvold Kvistad
0fa9b3852b feat(auto-mirror): wrap 13 modifying tools so --auto-mirror actually works
The 75cf74d scaffold added the helpers; this commit makes them
load-bearing by switching every modifying tool's formatToolResponse
call to formatModifyingResponse. Without --auto-mirror, behaviour is
unchanged. With it: mirror_export runs after each successful edit and
'code --add <mirror>' fires once per project to surface the diff in
VSCode's Source Control panel.
2026-04-27 21:53:10 +02:00
Karstein Phobic Nyvold Kvistad
4f5c80e591 docs(README): sync stale text -- new launcher behaviour + remove dead CODESYS Git mentions
Two pieces of doc lag the source had silently outpaced:

1. The embedded --print-config sample showed the old caveat ('only ONE
   can be active at a time') even though the runtime output (in
   src/detect.ts) was already updated to the post-0.4.8 wording about
   multi-install coexistence. Sync the README sample.
2. The 'Reliability fixes' bullet for the launcher still described the
   pre-0.4.8 behaviour (refuses ANY CODESYS.exe). Updated to the
   path-filtered version. Also drop the git_* project.save() bullet --
   those tools were removed in 5be20a6.
2026-04-27 21:48:59 +02:00
Karstein Phobic Nyvold Kvistad
0afdc08c47 feat(cli): --inspect <project> reads CODESYS profile + mandatory libs offline (no CODESYS needed) 2026-04-27 21:47:31 +02:00
Karstein Phobic Nyvold Kvistad
5be20a6e3b remove(codesys-git): drop all 6 CODESYS Git plugin tools
The CODESYS Git plugin wrappers (git_init, git_status, git_commit,
git_remote_add, git_branch_set_upstream_to, git_push) operated on the
binary .project file via CODESYS's IDE-side Git plugin. Drawbacks:

- Required a CODESYS Professional Developer Edition subscription
  (HasGitLicense gate). Anyone without PDE got a fail-fast error on
  every call -- the tools were dead weight for most users.
- Operated on a separate dual-storage repo (the .project stayed put,
  the git repo lived in a sibling directory). Diffs were unreadable
  because they're binary serialisations, not source text.
- Couldn't run on UNC paths -- the plugin rejected them.
- Duplicated functionality release_project_version already provides
  via the system git binary against the source-mirror tree (which IS
  human-readable diff-able .st files).

Removing all 6 tools, all 6 .py templates, and the README section.
Tool count drops 37 -> 31. release_project_version remains the
recommended path for CODESYS-project version control: mirror_export
gives you readable diffs in mcp-mirror/, then standard git commits
+ tags + push, no PDE license required.
2026-04-27 21:43:52 +02:00
Karstein Phobic Nyvold Kvistad
282b261d2f docs(README): drop the no-postinstall-banner footnote 2026-04-27 20:51:34 +02:00
Karstein Phobic Nyvold Kvistad
c7f103d3fd revert: drop postinstall banner -- npm 7+ buffers script stdout by design
Per https://docs.npmjs.com/cli/v11/using-npm/scripts, since npm@7 the
preinstall/install/postinstall scripts run in the background with stdout
AND stderr captured. The only way to surface them is the
`--foreground-scripts` opt-in flag (default false). Three failed
publish cycles (0.4.4, 0.4.5, 0.4.6) couldn't get around this -- the
limitation is by design, not a bug.

Removing src/postinstall.ts and the postinstall script entry from
package.json. The functionality (printing the .mcp.json snippet) is
still available -- it just runs on demand via:

  codesys-mcp-sp21-plus --print-config

Updated the README Quick Start to a numbered 4-step flow:
  1. npm install -g codesys-mcp-sp21-plus
  2. codesys-mcp-sp21-plus --print-config
  3. paste into project- or user-scoped .mcp.json
  4. restart Claude Code

Plus a footnote explaining why no banner -- so a future maintainer
doesn't try to re-add postinstall and waste another publish cycle.
2026-04-27 20:46:45 +02:00
Karstein Phobic Nyvold Kvistad
9c98e61974 feat(cli): --print-config emits ready-to-paste .mcp.json for every detected install
New flags:
- --print-config: scan installs and emit a JSON block per install with
  derived server names (codesys-sp21-patch5, codesys-sp22-patch1, etc.)
- --sp <n>: filter to one SP family; collapses entry name to 'codesys'
  when exactly one install matches
- --name <name>: override the entry name (only valid with --sp narrowing
  to one)

Side effect: --detect now reuses the same detector and additionally
prints the derived profile name + suggested server entry name per
install, so even users sticking to manual config get the values
without guessing.

Refactored install discovery into src/detect.ts so both --detect and
--print-config share one implementation. New unit test fixture covers
version parsing, missing-exe, dedup, sort order, --sp filter behaviour,
--name override constraints, and verifies the emitted JSON parses back
once // comments are stripped.

The output also surfaces the multi-install caveat from launcher.ts:
the double-spawn guard refuses to start a second CODESYS.exe even on
a different exe path, so only one configured entry can be active at
a time.
2026-04-27 20:22:15 +02:00
Karstein Phobic Nyvold Kvistad
d5731512a2 docs(README): Quick Start now shows SP21 example first, then SP22 2026-04-26 22:57:15 +02:00
Karstein Phobic Nyvold Kvistad
ca3062a2d8 docs(README): promote Quick Start (npm install + .mcp.json snippet) above 'What's new' 2026-04-26 22:51:48 +02:00
Karstein Phobic Nyvold Kvistad
0352b6c15e chore: sync lockfile to current name + drop stale branch reference from README 2026-04-26 22:48:11 +02:00
Karstein Phobic Nyvold Kvistad
58d45066e4 docs(README): restructure -- fork notice up top, what's-new section, npm install front-and-center
- Lead with a clear "this is a fork" callout (upstream link, fork link, npm link, maintainer)
- New "What's new in this fork" section grouping all changes:
  * Compatibility fixes (SP21+ watcher rewrite, KeyboardInterrupt cancel hardening)
  * Upstream tool fixes (create_folder, compile JSON long, connect_to_device LoginMode + auto-login, ensure_project_open switch, set_pou_code wipe, add_library, list_project_libraries)
  * New tools (mirror_export, bump_project_version, release_project_version, read_running_version_online, git_remote_add, git_branch_set_upstream_to, git_push)
  * Reliability fixes (launcher refuses double-spawn, shutdown kills orphans, git_* persists via project.save)
- Promote npm install to the top of the install section; source install now follows
- MCP Tools tables now mark each tool as **NEW** or **FIXED** so readers can scan what came from this fork
2026-04-26 22:44:06 +02:00
Karstein Phobic Nyvold Kvistad
4432880d42 docs(README): use the literal branch URL in the About blurb 2026-04-26 22:32:16 +02:00
Karstein Phobic Nyvold Kvistad
bb974655ae docs(README): link the active branch + npm registry from the About blurb
The 'sp21-plus-migration-notes' branch name was shown in code-style
but not linked. Made it a hyperlink to
https://github.com/phobicdotno/Codesys-MCP-SP21-plus/tree/sp21-plus-migration-notes
so a reader landing on the README can click straight through to the
live source state without first navigating to the repo root.

Also added a sibling sentence pointing at the published npm registry
page (https://www.npmjs.com/package/codesys-mcp-sp21-plus) so the
About blurb now exposes the three canonical landing pages: upstream,
fork repo (+ branch), and npm.
2026-04-26 22:29:47 +02:00
Karstein Phobic Nyvold Kvistad
a702f34d9d docs(README): make it explicit that 'codesys-mcp-sp21-plus' npm package IS this fork
Reader feedback: the install line 'npm install -g codesys-mcp-sp21-plus'
didn't make clear that the npm package IS this fork (rather than some
unrelated package or the upstream luke-harriman/Codesys-MCP).

Changes to the Installation section:
- Lead paragraph now states explicitly that the fork is published as
  'codesys-mcp-sp21-plus' by phobic, and that this is this fork (not
  upstream, not a Python package).
- 'npm install -g' command moved into a clear 'Install the fork from
  npm' subsection with a bullet list explaining what -g does, where
  the binary lands on PATH, and which deps come along for the ride.
- Added two verification commands (--version, --detect) so a first-time
  user has an obvious next step after install.
- Added an upgrade command ('npm install -g codesys-mcp-sp21-plus@latest')
  so the post-install workflow is fully documented.
- 'From source' subsection retitled 'Install the fork from source' for
  parallel structure.
2026-04-26 22:28:02 +02:00
Karstein Phobic Nyvold Kvistad
700afe27bf docs(README): lead with 'npm install -g codesys-mcp-sp21-plus' now that fork is published
Package is live on the npm registry as of 2026-04-26 (version 0.4.0,
maintainer phobic). The bare-name install line that was previously
warned-against now actually works, so it's the leading install path
again. The git-clone workflow is demoted to a 'From source' subsection
for users who want to track sp21-plus-migration-notes directly,
contribute patches, or run a specific commit.

Verified live:
  npm view codesys-mcp-sp21-plus version  -> 0.4.0
2026-04-26 22:25:22 +02:00
Karstein Phobic Nyvold Kvistad
2e78c45972 docs(README): focus install on git clone; drop npm-publish caveats
User feedback: don't lead with npm registry concepts when the fork
isn't published. Replaced the three-option list (with the misleading
'not currently published' caveat) with a clean two-step git-clone
workflow:

  1. git clone + npm install + npm run build  (mandatory)
  2. wire into .mcp.json via either:
     A) command: 'node', args: ['<path>/dist/bin.js', ...]
        (simplest -- no global state)
     B) command: 'codesys-mcp-sp21-plus' after running 'npm link'
        (only useful if you also want the bin on PATH for ad-hoc use)

Plus a short 'Updating' section that documents what to pull / rebuild
when the upstream branch advances.

Removed entirely:
- 'Option 1: npm install -g github:phobicdotno/...' (still works, but
  drowns the simpler path)
- The 'Heads-up on npm install -g codesys-mcp-sp21-plus' caveat
  paragraph (the new section doesn't mention the registry name at all,
  so the warning has no premise)
2026-04-26 22:18:12 +02:00
Karstein Phobic Nyvold Kvistad
d922238059 docs(README): clear install instructions for the unpublished fork
Three explicit install paths replacing the misleading 'npm install -g codesys-mcp-sp21-plus' top-line (the fork is not published to npm; bare-name install would fail with 404):

1. npm install -g github:phobicdotno/Codesys-MCP-SP21-plus
   -- installs directly from this repo, recommended for end users
2. git clone + npm install + npm run build + npm link
   -- recommended for development; lets src/ edits take effect after a
   build, and Python script edits hot-reload from dist/scripts/ without
   one
3. git clone + npm install + npm run build, then node dist/bin.js
   -- avoids touching global node_modules; full .mcp.json snippet shown

Also clarifies up-front that this is a Node/npm package, not a Python
package -- the .py files under src/scripts/ are CODESYS IronPython
templates bundled into the npm distribution, not a pypi project. There
is no pip install. Requirements section now lists the supported CODESYS
versions explicitly (SP19 / SP21 3.5.21.x / SP22 3.5.22.x) and notes
the PDE subscription gate on the git_* tools.
2026-04-26 22:03:38 +02:00
Karstein Phobic Nyvold Kvistad
405be44a58 rename: Codesys-MCP-SP22+ -> Codesys-MCP-SP21+ + multi-install README + missing tools
Project rename. The 'SP21+' identifier is more accurate than the
previous 'SP22+' label -- this fork specifically carries the SP21+
migration fixes (the upstream's system.execute_on_primary_thread()
removal and downstream API drift), and is forward-compat with later
SPs. The repo on GitHub has been renamed to
phobicdotno/Codesys-MCP-SP21-plus accordingly.

Substitutions (UTF-8 preserved this time -- prior PowerShell pass
mangled em-dashes via a Win-1252 round-trip):
- package.json: name codesys-mcp-sp22-plus -> codesys-mcp-sp21-plus,
  bin entry, repository.url, homepage, description, author trailer
- README.md: title, banner, install + clone snippets, CLI invocations
- ARCHITECTURE.md: comparison-table column header + temp-dir prefix
- tests/TEST_OVERVIEW.md: title
- src/bin.ts: header comment + program().name()
- src/launcher.ts: SESSION_DIR_PREFIX
- src/types.ts: header comment

Compatibility phrase 'Works on SP19, SP21, and SP22+' and the technical
identifier 'SP22 Patch 1 fixes' (which name the actual CODESYS version)
were preserved -- those refer to CODESYS, not the project name.

README additions:
- Quick Start example switched from SP21 Patch 3 to SP22 Patch 1 to
  match the more common modern install
- New 'Multiple CODESYS installations' subsection with worked
  side-by-side example for SP21 (3.5.21.50) and SP22 (3.5.22.10) --
  one named MCP server entry per install, called by name from Claude.
  Documents the constraint that --codesys-path/--codesys-profile are
  bound at server startup, that --detect lists installs, and that
  config edits require a Claude Code restart
- Tool count corrected from 28 -> 37 in the Features bullets
- New Tools sections covering 10 previously-undocumented tools:
  Version Anchor + Release Pipeline (bump_project_version,
  release_project_version, read_running_version_online), Source
  Mirror (mirror_export), and CODESYS Git PDE-gated (git_init,
  git_status, git_commit, git_remote_add, git_branch_set_upstream_to,
  git_push). Each row carries the actual operational gotchas
  discovered during this session (UNC localRepoPath rejection,
  push-without-upstream failure, optimizer stripping unreferenced
  globals from the online symbol table, etc.)
- list_project_libraries + add_library row text updated to reflect
  the post-fix behaviour (compiler-version capture; managed-overload
  preference + resolution gate)

Local origin URL updated: phobicdotno/Codesys-MCP -> phobicdotno/Codesys-MCP-SP21-plus.

37/37 tests green.
2026-04-26 22:02:46 +02:00
Karstein Phobic Nyvold Kvistad
f157e7b61e rename: project -> Codesys-MCP-SP22+
Project identity rename. Concrete changes:

- package.json
  - name: codesys-mcp-persistent -> codesys-mcp-sp22-plus (npm-safe;
    '+' is not allowed in npm package names)
  - description: prepended 'Codesys-MCP-SP22+' branding + brief
    summary of the SP22+ fixes carried in this fork
  - bin entry: codesys-mcp-persistent -> codesys-mcp-sp22-plus
  - repository.url + homepage: now point at
    github.com/phobicdotno/Codesys-MCP-SP22-plus (using -plus
    spelling on the URL side; '+' would require URL-encoding)
  - author: noted upstream + SP22+ fork attribution
- README.md: title + about-this-fork blurb + clone instructions
- tests/TEST_OVERVIEW.md: title
- ARCHITECTURE.md: comparison-table column header + temp-dir path
- src/bin.ts: file header + program().name()
- src/launcher.ts: SESSION_DIR_PREFIX (with note on backwards compat)
- src/types.ts: file header

Display name everywhere: 'Codesys-MCP-SP22+'.
npm package name: 'codesys-mcp-sp22-plus'.

Out of scope for this commit -- need user action:
- Local directory rename (C:/Users/karstein.kvistad/Codesys-MCP ->
  ...-SP22+) cannot be done while the persistent MCP is using dist/
  from the current path; user can rename after shutting down VS Code.
- GitHub repo rename (phobicdotno/Codesys-MCP -> ...-SP22-plus or
  ...-SP22+) needs the github.com web UI; the package.json URLs
  already point at the post-rename name so a 'git remote set-url
  origin <new>' lines up after.
- MCP client config in .mcp.json or similar: the bin name changed
  from 'codesys-mcp-persistent' to 'codesys-mcp-sp22-plus' -- update
  any 'command' field that referenced the old name. (Local sessions
  invoking node dist/bin.js directly are unaffected.)

37/37 tests still green after rename.
2026-04-26 20:42:15 +02:00
Karstein Phobic Nyvold Kvistad
3bdd48f93a docs(README): add fork notice at top explaining SP21+ rationale + cancel hardening
Prepended a blockquote section above the existing title that:

  - Identifies this as a fork of luke-harriman/Codesys-MCP, links to both
    upstream and the phobicdotno mirror.
  - Explains why the fork exists (SP21+/SP22 removal of
    system.execute_on_primary_thread() made upstream unusable on current
    CODESYS releases).
  - Summarises the two substantive fixes carried on this branch:
      * SP21+/SP22 watcher rewrite (single-thread, primary)
      * KeyboardInterrupt hardening so the CODESYS Cancel link no longer
        pops the modal traceback dialog
  - Links to docs/MIGRATION-SP21-PLUS.md and docs/SMOKE-TEST-2026-04-25.md
    for the rationale and the per-tool verification results.

Original README content is unchanged below the notice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 15:13:55 +02:00
Luke
aad246576c Add 17 new MCP tools for v0.4.0: compiler diagnostics, project authoring, runtime monitoring, library management
- Phase 1: Structured compiler diagnostics — compile_project now returns parsed errors/warnings with object name and line number; new get_compile_messages tool reads last build messages without recompiling
- Phase 2: Project authoring — create_dut, create_gvl, create_folder, delete_object, rename_object, get_all_pou_code
- Phase 3: Online/runtime — connect_to_device, disconnect_from_device, get_application_state, read_variable, write_variable, download_to_device, start_stop_application (with ensure_online_connection helper)
- Phase 4: Library management — list_project_libraries, add_library
- Bump version to 0.4.0, update README with full tool reference

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 21:05:12 +10:00
Luke
e374519fe1 Initial release: MCP server for CODESYS with persistent UI instance
v0.3.0 returning-watcher architecture — background thread polls for commands
and marshals execution onto the CODESYS UI thread, keeping the IDE fully
responsive between operations. File-based IPC with atomic writes, async mutex
command serialization, headless fallback, and 35 passing tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-08 18:59:16 +10:00