0
0
Fork 0

fix(install_addon_from_file): correct default --location and document elevation

Two issues found while installing CODESYS Control for PFC200 SL 4.20.0.0
on the test machine:

  1) Default --location derivation was off by one dirname. APInstaller
     wants the CODESYS install root (the directory containing
     Common\CODESYS.exe), not its parent. The original derivation
     (path.dirname x3 from config.codesysPath) gave the parent
     'C:\Program Files\CODESYS 3.5.XX.YY', which APInstaller rejects:
       Error: No installation was found in the directory ...
     Corrected to (path.dirname x2) which gives the install root
     'C:\Program Files\CODESYS 3.5.XX.YY\CODESYS'. Confirmed by
     re-running with the explicit installation arg pointing there:
     APInstaller stopped with the elevation error instead, meaning it
     reached the install.

  2) APInstaller writes under Program Files and so requires admin
     rights. Without them it exits code 1 with:
       Error: This command needs elevated rights to run.
     The MCP server runs at user level by default, so this is not
     something the tool itself can fix -- the MCP server must be
     launched elevated for this tool to work. Documented in the tool
     description so the failure mode is no longer surprising.

The companion tool description for the 'installation' arg was also
updated to clarify it expects the install root, not the parent.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Karstein Phobic Nyvold Kvistad 2026-04-25 16:47:08 +02:00
parent 3832f9c5cc
commit 33f494e5ad

View file

@ -1118,10 +1118,10 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
s.tool(
'install_addon_from_file',
"Installs a CODESYS .package add-on (e.g. WAGO PFC libraries bundle, vendor packages) into a CODESYS installation by shelling out to APInstaller.CLI.exe --installAddOnFromFile. Use this for .package bundles; use install_library_file for plain .library files. Does not need CODESYS UI to be running.",
"Installs a CODESYS .package add-on (e.g. WAGO PFC libraries bundle, vendor packages) into a CODESYS installation by shelling out to APInstaller.CLI.exe --installAddOnFromFile. Use this for .package bundles; use install_library_file for plain .library files. Does not need CODESYS UI to be running. NOTE: writes under C:\\Program Files\\CODESYS\\... so requires admin rights -- the MCP server itself must have been launched elevated, otherwise APInstaller exits with 'This command needs elevated rights to run.'",
{
packageFilePath: z.string().describe("Full path to the .package file to install."),
installation: z.string().optional().describe("Installation location (e.g. 'C:\\\\Program Files\\\\CODESYS 3.5.21.50'). Defaults to the parent of this MCP's configured CODESYS install."),
installation: z.string().optional().describe("CODESYS install root (e.g. 'C:\\\\Program Files\\\\CODESYS 3.5.21.50\\\\CODESYS' -- the directory containing Common\\\\CODESYS.exe). Defaults to the install root derived from this MCP's configured CODESYS path."),
},
async (args: { packageFilePath: string; installation?: string }) => {
const cli = locateAPInstallerCli();
@ -1141,9 +1141,13 @@ export async function startMcpServer(config: ServerConfig): Promise<void> {
isError: true,
};
}
// Default installation location = parent of CODESYS\Common\CODESYS.exe
// i.e. three dirnames up from config.codesysPath
const defaultLocation = path.dirname(path.dirname(path.dirname(config.codesysPath)));
// Default installation location = the CODESYS install root, i.e.
// C:\Program Files\CODESYS 3.5.XX.YY\CODESYS. config.codesysPath
// points at ...\CODESYS\Common\CODESYS.exe, so two dirnames up.
// (APInstaller --location wants this exact directory; the parent
// 'C:\Program Files\CODESYS 3.5.XX.YY' is rejected with
// "No installation was found in the directory ...".)
const defaultLocation = path.dirname(path.dirname(config.codesysPath));
const location = args.installation && args.installation.trim().length > 0
? path.normalize(args.installation)
: defaultLocation;