mcp-for-i 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/store.js +4 -1
- package/dist/controlplane/connectionService.js +1 -1
- package/dist/controlplane/server.js +63 -2
- package/dist/controlplane/ui.js +645 -851
- package/dist/mcp/context.js +270 -41
- package/dist/mcp/tools.js +46 -46
- package/package.json +1 -1
package/dist/config/store.js
CHANGED
|
@@ -17,7 +17,10 @@ const defaultSettings = {
|
|
|
17
17
|
objectFilters: [],
|
|
18
18
|
ifsShortcuts: [],
|
|
19
19
|
debugPort: 8005,
|
|
20
|
-
debugSepPort: 8008
|
|
20
|
+
debugSepPort: 8008,
|
|
21
|
+
sessionIdleMinutes: 30,
|
|
22
|
+
sessionPingSeconds: 15,
|
|
23
|
+
sessionReconnectAttempts: 2
|
|
21
24
|
};
|
|
22
25
|
export class ConfigStore {
|
|
23
26
|
configDir;
|
|
@@ -35,7 +35,7 @@ export class ConnectionService {
|
|
|
35
35
|
port: input.port ?? existing.port,
|
|
36
36
|
username: input.username ?? existing.username,
|
|
37
37
|
privateKeyPath: input.privateKeyPath ?? existing.privateKeyPath,
|
|
38
|
-
settings: input.settings
|
|
38
|
+
settings: input.settings ? { ...(existing.settings || {}), ...input.settings } : existing.settings,
|
|
39
39
|
policy: input.policy ?? existing.policy
|
|
40
40
|
};
|
|
41
41
|
await this.store.upsertConnection(next);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import http from "http";
|
|
2
2
|
import fs from "fs";
|
|
3
|
+
import fsp from "fs/promises";
|
|
3
4
|
import path from "path";
|
|
4
5
|
import { URL } from "url";
|
|
5
6
|
import { fileURLToPath } from "url";
|
|
6
|
-
import { ConfigStore } from "../config/store.js";
|
|
7
|
+
import { ConfigStore, getConfigDir } from "../config/store.js";
|
|
7
8
|
import { isKeychainAvailable } from "../security/credentialStore.js";
|
|
8
9
|
import { ConnectionService } from "./connectionService.js";
|
|
9
10
|
import { RuntimeService } from "./runtimeService.js";
|
|
@@ -17,7 +18,7 @@ export async function startControlPlaneServer(opts) {
|
|
|
17
18
|
const runtime = new RuntimeService(rootDir);
|
|
18
19
|
const server = http.createServer(async (req, res) => {
|
|
19
20
|
try {
|
|
20
|
-
await routeRequest(req, res, { connections, runtime });
|
|
21
|
+
await routeRequest(req, res, { store, connections, runtime });
|
|
21
22
|
}
|
|
22
23
|
catch (err) {
|
|
23
24
|
sendJson(res, 500, { error: err?.message || String(err) });
|
|
@@ -48,6 +49,42 @@ async function routeRequest(req, res, services) {
|
|
|
48
49
|
sendJson(res, 200, { ok: true, keychainAvailable: await isKeychainAvailable() });
|
|
49
50
|
return;
|
|
50
51
|
}
|
|
52
|
+
if (method === "GET" && pathname === "/api/settings") {
|
|
53
|
+
const settings = await services.store.getSettings();
|
|
54
|
+
sendJson(res, 200, { settings });
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (method === "PUT" && pathname === "/api/settings") {
|
|
58
|
+
const body = await readJson(req);
|
|
59
|
+
const update = {};
|
|
60
|
+
try {
|
|
61
|
+
if (typeof body.sessionIdleMinutes !== "undefined") {
|
|
62
|
+
update.sessionIdleMinutes = parseNumberSetting(body.sessionIdleMinutes, 1, 24 * 60, "sessionIdleMinutes");
|
|
63
|
+
}
|
|
64
|
+
if (typeof body.sessionPingSeconds !== "undefined") {
|
|
65
|
+
update.sessionPingSeconds = parseNumberSetting(body.sessionPingSeconds, 5, 300, "sessionPingSeconds");
|
|
66
|
+
}
|
|
67
|
+
if (typeof body.sessionReconnectAttempts !== "undefined") {
|
|
68
|
+
update.sessionReconnectAttempts = parseNumberSetting(body.sessionReconnectAttempts, 1, 5, "sessionReconnectAttempts");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (err) {
|
|
72
|
+
sendJson(res, 400, { error: err?.message || String(err) });
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (Object.keys(update).length === 0) {
|
|
76
|
+
sendJson(res, 400, { error: "No supported settings provided" });
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await services.store.updateSettings(update);
|
|
80
|
+
const settings = await services.store.getSettings();
|
|
81
|
+
sendJson(res, 200, { settings });
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
if (method === "GET" && pathname === "/api/sessions") {
|
|
85
|
+
sendJson(res, 200, { snapshot: await readSessionSnapshot() });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
51
88
|
if (method === "GET" && pathname === "/api/runtime/status") {
|
|
52
89
|
sendJson(res, 200, { jobs: services.runtime.getStatus() });
|
|
53
90
|
return;
|
|
@@ -197,3 +234,27 @@ function getDefaultRootDir() {
|
|
|
197
234
|
}
|
|
198
235
|
return process.cwd();
|
|
199
236
|
}
|
|
237
|
+
function parseNumberSetting(input, min, max, key) {
|
|
238
|
+
const value = Number(input);
|
|
239
|
+
if (!Number.isFinite(value)) {
|
|
240
|
+
throw new Error(`${key} must be a number`);
|
|
241
|
+
}
|
|
242
|
+
const normalized = Math.floor(value);
|
|
243
|
+
if (normalized < min || normalized > max) {
|
|
244
|
+
throw new Error(`${key} must be between ${min} and ${max}`);
|
|
245
|
+
}
|
|
246
|
+
return normalized;
|
|
247
|
+
}
|
|
248
|
+
async function readSessionSnapshot() {
|
|
249
|
+
const snapshotPath = path.join(getConfigDir(), "session-state.json");
|
|
250
|
+
try {
|
|
251
|
+
const raw = await fsp.readFile(snapshotPath, "utf8");
|
|
252
|
+
const parsed = JSON.parse(raw);
|
|
253
|
+
if (!parsed || typeof parsed !== "object")
|
|
254
|
+
return null;
|
|
255
|
+
return parsed;
|
|
256
|
+
}
|
|
257
|
+
catch {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
}
|