fixup msp-con
This commit is contained in:
parent
2158c9f725
commit
729ba03593
8 changed files with 81 additions and 10 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "codesys-mcp-sp21-plus",
|
||||
"version": "0.13.0",
|
||||
"version": "0.15.2",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "codesys-mcp-sp21-plus",
|
||||
"version": "0.13.0",
|
||||
"version": "0.15.2",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.26.0",
|
||||
|
|
|
|||
10
src/bin.ts
10
src/bin.ts
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { program } from 'commander';
|
||||
import { startMcpServer } from './server';
|
||||
import { resolveLogLevel, setLogLevel } from './logger';
|
||||
import { ServerConfig, ExecutionMode } from './types';
|
||||
import { detectInstalls, printConfig } from './detect';
|
||||
import { inspectProjectFile, suggestedServerName } from './inspect';
|
||||
|
|
@ -42,12 +43,14 @@ program
|
|||
.option(
|
||||
'-p, --codesys-path <path>',
|
||||
'Path to CODESYS executable',
|
||||
process.env.CODESYS_PATH || 'C:\\Program Files\\CODESYS 3.5.21.0\\CODESYS\\Common\\CODESYS.exe'
|
||||
//process.env.CODESYS_PATH || 'C:\\CODESYS3.5.21.40\\Codesys\\Common\\Codesys.exe'
|
||||
process.env.CODESYS_PATH || 'C:\\Program Files\\MSP-Con 3.5.21.40\\MSP-Con\\Common\\MSP-Con.exe'
|
||||
)
|
||||
.option(
|
||||
'-f, --codesys-profile <profile>',
|
||||
'CODESYS profile name',
|
||||
process.env.CODESYS_PROFILE || 'CODESYS V3.5 SP21'
|
||||
//process.env.CODESYS_PROFILE || 'CODESYS V3.5 SP21 Patch 4'
|
||||
process.env.CODESYS_PROFILE || 'MSP-Con V3.5 SP21 Patch 4'
|
||||
)
|
||||
.option(
|
||||
'--codesys-additional-folder <dir>',
|
||||
|
|
@ -87,6 +90,9 @@ program
|
|||
|
||||
const opts = program.opts();
|
||||
|
||||
const initialLogLevel = resolveLogLevel(opts.debug ? 'debug' : opts.verbose ? 'info' : undefined);
|
||||
setLogLevel(initialLogLevel);
|
||||
|
||||
if (opts.sshVersion) {
|
||||
// --ssh-version emits to stdout (pipe-friendly); errors go to stderr with exit 1.
|
||||
readRunningVersionSsh({
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ function findRichestAdditionalFolder(
|
|||
try {
|
||||
const xml = readFileSync(path.join(profilesDir, profile), 'utf-8');
|
||||
plugins += (xml.match(/<Hint>/g) ?? []).length;
|
||||
console.log(`Found ${plugins} plugins in ${path.join(profilesDir, profile)}`);
|
||||
} catch {
|
||||
/* unreadable profile -- treat as contributing nothing */
|
||||
}
|
||||
|
|
@ -142,7 +143,7 @@ export function detectInstalls(
|
|||
if (!fsApi.existsSync(exePath)) continue;
|
||||
if (seen.has(exePath.toLowerCase())) continue;
|
||||
seen.add(exePath.toLowerCase());
|
||||
|
||||
console.log(`Detected CODESYS install: ${exePath} (V${major}.${minor} SP${sp} Patch ${patch})`);
|
||||
installs.push({
|
||||
installDir: path.join(base, entry),
|
||||
exePath,
|
||||
|
|
@ -255,6 +256,7 @@ export function printConfig(installs: CodesysInstall[], opts: PrintConfigOptions
|
|||
} else {
|
||||
name = install.serverName;
|
||||
}
|
||||
console.log(name);
|
||||
let unique = name;
|
||||
let suffix = 2;
|
||||
while (usedNames.has(unique)) {
|
||||
|
|
@ -267,6 +269,7 @@ export function printConfig(installs: CodesysInstall[], opts: PrintConfigOptions
|
|||
lines.push('{');
|
||||
lines.push(' "mcpServers": {');
|
||||
for (const { name, install, isLast } of namedEntries) {
|
||||
console.log(name);
|
||||
lines.push(` ${JSON.stringify(name)}: {`);
|
||||
lines.push(` "command": "codesys-mcp-sp21-plus",`);
|
||||
lines.push(` "args": [`);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,19 @@ const LOG_LEVELS: Record<LogLevel, number> = {
|
|||
error: 3,
|
||||
};
|
||||
|
||||
const VALID_LOG_LEVELS = new Set<LogLevel>(['debug', 'info', 'warn', 'error']);
|
||||
|
||||
let currentLevel: LogLevel = 'info';
|
||||
|
||||
export function resolveLogLevel(input: string | undefined): LogLevel {
|
||||
const normalized = (input ?? '').trim().toLowerCase();
|
||||
if (VALID_LOG_LEVELS.has(normalized as LogLevel)) {
|
||||
return normalized as LogLevel;
|
||||
}
|
||||
return process.env.CODESYS_MCP_LOG_LEVEL?.trim().toLowerCase() as LogLevel | undefined
|
||||
?? 'info';
|
||||
}
|
||||
|
||||
export function setLogLevel(level: LogLevel): void {
|
||||
currentLevel = level;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ UI thread. The single-thread design here works on SP19, SP21, and SP22+.
|
|||
{IPC_BASE_DIR} is interpolated by Node.js before launch.
|
||||
"""
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import os
|
||||
import traceback
|
||||
import json
|
||||
|
||||
|
|
@ -204,7 +204,8 @@ try:
|
|||
os.remove(command_path)
|
||||
sp = os.path.join(COMMANDS_DIR, "%s.py" % request_id)
|
||||
if os.path.exists(sp):
|
||||
os.remove(sp)
|
||||
pass
|
||||
#os.remove(sp)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import { ServerConfig, IpcResult, ScriptExecutor, ExecutionMode } from './types'
|
|||
import { CodesysLauncher } from './launcher';
|
||||
import { HeadlessExecutor } from './headless';
|
||||
import { ScriptManager } from './script-manager';
|
||||
import { serverLog, setLogLevel } from './logger';
|
||||
import { serverLog, setLogLevel, resolveLogLevel } from './logger';
|
||||
import { readRunningVersionSsh, formatSshVersionResult } from './ssh-version';
|
||||
import {
|
||||
restartCodesysRuntime,
|
||||
|
|
@ -1240,8 +1240,8 @@ function defaultLiveValuesFilePath(): string {
|
|||
|
||||
export async function startMcpServer(config: ServerConfig): Promise<void> {
|
||||
// Set log level
|
||||
if (config.debug) setLogLevel('debug');
|
||||
else if (config.verbose) setLogLevel('info');
|
||||
const configuredLogLevel = resolveLogLevel(config.debug ? 'debug' : config.verbose ? 'info' : undefined);
|
||||
setLogLevel(configuredLogLevel);
|
||||
|
||||
serverLog.info(`Starting CODESYS Persistent MCP Server v0.1.0`);
|
||||
serverLog.info(`Mode: ${config.mode}`);
|
||||
|
|
|
|||
30
tests/unit/logger.test.ts
Normal file
30
tests/unit/logger.test.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { afterEach, beforeEach, describe, expect, it } from 'vitest';
|
||||
import { getLogLevel, resolveLogLevel, setLogLevel } from '../../src/logger';
|
||||
|
||||
describe('logger level handling', () => {
|
||||
beforeEach(() => {
|
||||
delete process.env.CODESYS_MCP_LOG_LEVEL;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
delete process.env.CODESYS_MCP_LOG_LEVEL;
|
||||
setLogLevel('info');
|
||||
});
|
||||
|
||||
it('normalizes explicit log levels', () => {
|
||||
expect(resolveLogLevel('DEBUG')).toBe('debug');
|
||||
expect(resolveLogLevel('warn')).toBe('warn');
|
||||
expect(resolveLogLevel('ERROR')).toBe('error');
|
||||
});
|
||||
|
||||
it('uses the environment variable when present', () => {
|
||||
process.env.CODESYS_MCP_LOG_LEVEL = 'debug';
|
||||
expect(resolveLogLevel('info')).toBe('debug');
|
||||
});
|
||||
|
||||
it('applies the resolved level through the public logger API', () => {
|
||||
process.env.CODESYS_MCP_LOG_LEVEL = 'warn';
|
||||
setLogLevel(resolveLogLevel('info'));
|
||||
expect(getLogLevel()).toBe('warn');
|
||||
});
|
||||
});
|
||||
20
tests/unit/print-config.test.ts
Normal file
20
tests/unit/print-config.test.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
import { printConfig } from '../../src/detect';
|
||||
|
||||
test('printConfig generates config for one install (exercises name generation)', () => {
|
||||
const installs = [
|
||||
{
|
||||
installDir: 'C:\\Program Files\\CODESYS 3.5.21.10',
|
||||
exePath: 'C:\\Program Files\\CODESYS 3.5.21.10\\CODESYS\\Common\\CODESYS.exe',
|
||||
version: '3.5.21.10',
|
||||
major: 3,
|
||||
minor: 5,
|
||||
sp: 21,
|
||||
patch: 1,
|
||||
profileName: 'CODESYS V3.5 SP21 Patch 1',
|
||||
serverName: 'codesys-sp21-patch1',
|
||||
},
|
||||
];
|
||||
|
||||
const out = printConfig(installs);
|
||||
expect(out).toContain('mcpServers');
|
||||
});
|
||||
Loading…
Reference in a new issue