@chkp/policy-insights-mcp 0.4.3 → 0.4.4
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/index.js +1067 -846
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/package.json.bak +1 -1
package/dist/index.js
CHANGED
|
@@ -1270,600 +1270,451 @@ var toolDefinitionMap = [
|
|
|
1270
1270
|
// ../infra/dist/api-client.js
|
|
1271
1271
|
import axios from "axios";
|
|
1272
1272
|
import https from "https";
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
}
|
|
1278
|
-
function
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1273
|
+
|
|
1274
|
+
// ../mcp-utils/dist/cli-options.js
|
|
1275
|
+
function booleanOptionDefault(envValue, optionDefault) {
|
|
1276
|
+
return envValue === "true" || optionDefault === "true";
|
|
1277
|
+
}
|
|
1278
|
+
function resolveTransportType(transportOption, env = process.env) {
|
|
1279
|
+
return (transportOption || env.MCP_TRANSPORT_TYPE || "stdio").toLowerCase() === "http" ? "http" : "stdio";
|
|
1280
|
+
}
|
|
1281
|
+
function optionKey(flag) {
|
|
1282
|
+
const long = flag.split(/[,\s]+/).find((part) => part.startsWith("--"));
|
|
1283
|
+
if (!long)
|
|
1284
|
+
return void 0;
|
|
1285
|
+
const negated = long.startsWith("--no-");
|
|
1286
|
+
return {
|
|
1287
|
+
key: long.replace(/^--(no-)?/, "").replace(/-([a-z])/g, (_match, char) => char.toUpperCase()),
|
|
1288
|
+
negated
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function operatorValues(options, parsed, env = process.env) {
|
|
1292
|
+
const values = { ...env };
|
|
1293
|
+
for (const option of options) {
|
|
1294
|
+
const derived = option.env ? optionKey(option.flag) : void 0;
|
|
1295
|
+
if (!derived || derived.negated)
|
|
1296
|
+
continue;
|
|
1297
|
+
const value = parsed[derived.key];
|
|
1298
|
+
if (value !== void 0)
|
|
1299
|
+
values[option.env] = value;
|
|
1283
1300
|
}
|
|
1284
|
-
return
|
|
1301
|
+
return values;
|
|
1285
1302
|
}
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1303
|
+
|
|
1304
|
+
// ../mcp-utils/dist/debug-view.js
|
|
1305
|
+
import { createHash } from "node:crypto";
|
|
1306
|
+
var BUILTIN_LOGGABLE_KEYS = [
|
|
1307
|
+
"accept",
|
|
1308
|
+
"accept-encoding",
|
|
1309
|
+
"accept-language",
|
|
1310
|
+
"connection",
|
|
1311
|
+
"content-length",
|
|
1312
|
+
"content-type",
|
|
1313
|
+
"host",
|
|
1314
|
+
"mcp-protocol-version",
|
|
1315
|
+
"traceparent",
|
|
1316
|
+
"user-agent",
|
|
1317
|
+
"x-correlation-id",
|
|
1318
|
+
"x-gw-auth-method",
|
|
1319
|
+
"x-request-id",
|
|
1320
|
+
// Launcher options
|
|
1321
|
+
"debug",
|
|
1322
|
+
"telemetry",
|
|
1323
|
+
"telemetry-url",
|
|
1324
|
+
"transport",
|
|
1325
|
+
"transport-port"
|
|
1326
|
+
];
|
|
1327
|
+
function normalizeDebugKey(key) {
|
|
1328
|
+
const split = /[-_]/.test(key) ? key : key.replace(/([a-z][0-9]*)([A-Z])/g, "$1-$2");
|
|
1329
|
+
return split.replace(/_/g, "-").toLowerCase();
|
|
1330
|
+
}
|
|
1331
|
+
function debugLoggableKeys(extra = []) {
|
|
1332
|
+
return new Set([...BUILTIN_LOGGABLE_KEYS, ...extra].map(normalizeDebugKey));
|
|
1333
|
+
}
|
|
1334
|
+
function describe(key, value, loggable) {
|
|
1335
|
+
if (value === void 0 || value === null || value === "")
|
|
1336
|
+
return "(unset)";
|
|
1337
|
+
if (loggable.has(normalizeDebugKey(key))) {
|
|
1338
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
1339
|
+
}
|
|
1340
|
+
const text = typeof value === "string" ? value : Array.isArray(value) ? value.join(", ") : void 0;
|
|
1341
|
+
return text === void 0 ? "(hidden)" : `(hidden, ${text.length} chars)`;
|
|
1342
|
+
}
|
|
1343
|
+
function debugView(record, loggable = debugLoggableKeys()) {
|
|
1344
|
+
return Object.fromEntries(Object.entries(record ?? {}).map(([key, value]) => [key, describe(key, value, loggable)]));
|
|
1345
|
+
}
|
|
1346
|
+
function sessionLogLabel(sessionId) {
|
|
1347
|
+
if (!sessionId || sessionId === "default")
|
|
1348
|
+
return "default";
|
|
1349
|
+
return `session#${createHash("sha256").update(sessionId).digest("hex").slice(0, 8)}`;
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1352
|
+
// ../mcp-utils/dist/launcher.js
|
|
1353
|
+
import { Command } from "commander";
|
|
1354
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1355
|
+
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
1356
|
+
import fs from "fs";
|
|
1357
|
+
import http from "http";
|
|
1358
|
+
import { randomUUID } from "crypto";
|
|
1359
|
+
|
|
1360
|
+
// ../mcp-utils/dist/connection-source.js
|
|
1361
|
+
function hasValue(value) {
|
|
1362
|
+
return value !== void 0 && value !== null && value !== "" && !(Array.isArray(value) && value.length === 0);
|
|
1363
|
+
}
|
|
1364
|
+
function headersRead(fromHeaders, headers) {
|
|
1365
|
+
const read = /* @__PURE__ */ new Set();
|
|
1366
|
+
const recording = new Proxy(headers, {
|
|
1367
|
+
get(target, prop, receiver) {
|
|
1368
|
+
const value = Reflect.get(target, prop, receiver);
|
|
1369
|
+
if (typeof prop === "string" && hasValue(value))
|
|
1370
|
+
read.add(prop);
|
|
1371
|
+
return value;
|
|
1372
|
+
}
|
|
1373
|
+
});
|
|
1374
|
+
try {
|
|
1375
|
+
fromHeaders(recording);
|
|
1376
|
+
} catch {
|
|
1290
1377
|
}
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
this.isMDS = false;
|
|
1301
|
-
this._externalSid = false;
|
|
1378
|
+
return read;
|
|
1379
|
+
}
|
|
1380
|
+
function keySet(keys = []) {
|
|
1381
|
+
return new Set(keys.map(normalizeDebugKey));
|
|
1382
|
+
}
|
|
1383
|
+
function chooseConnectionSource(read, basicKeys) {
|
|
1384
|
+
for (const key of read) {
|
|
1385
|
+
if (!basicKeys.has(normalizeDebugKey(key)))
|
|
1386
|
+
return "caller";
|
|
1302
1387
|
}
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1388
|
+
return "operator";
|
|
1389
|
+
}
|
|
1390
|
+
function basicOnly(headers, basicKeys) {
|
|
1391
|
+
return Object.fromEntries(Object.entries(headers).filter(([key]) => basicKeys.has(normalizeDebugKey(key))));
|
|
1392
|
+
}
|
|
1393
|
+
function mergeHeaders(base, overrides) {
|
|
1394
|
+
const merged = {};
|
|
1395
|
+
const index = /* @__PURE__ */ new Map();
|
|
1396
|
+
for (const [key, value] of [...Object.entries(base), ...Object.entries(overrides)]) {
|
|
1397
|
+
const id = normalizeDebugKey(key);
|
|
1398
|
+
const previous = index.get(id);
|
|
1399
|
+
if (previous !== void 0)
|
|
1400
|
+
delete merged[previous];
|
|
1401
|
+
index.set(id, key);
|
|
1402
|
+
merged[key] = value;
|
|
1403
|
+
}
|
|
1404
|
+
return merged;
|
|
1405
|
+
}
|
|
1406
|
+
function operatorHeaders(values) {
|
|
1407
|
+
const headers = {};
|
|
1408
|
+
for (const [name, value] of Object.entries(values)) {
|
|
1409
|
+
if (!hasValue(value))
|
|
1410
|
+
continue;
|
|
1411
|
+
headers[name.replace(/_/g, "-")] = Array.isArray(value) ? value.map(String) : String(value);
|
|
1308
1412
|
}
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
const headers = {
|
|
1314
|
-
"Content-Type": "application/json",
|
|
1315
|
-
"User-Agent": getMainPackageUserAgent()
|
|
1316
|
-
};
|
|
1317
|
-
if (this.sid) {
|
|
1318
|
-
headers["X-chkp-sid"] = this.sid;
|
|
1319
|
-
}
|
|
1320
|
-
if (this.cloudConnected && this.tokenType === TokenType.CI_TOKEN) {
|
|
1321
|
-
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
1322
|
-
headers["CLOUD-INFRA-TOKEN"] = this.authToken;
|
|
1323
|
-
}
|
|
1413
|
+
return headers;
|
|
1414
|
+
}
|
|
1415
|
+
function canonicalizeAliases(headers, aliases) {
|
|
1416
|
+
if (aliases.size === 0)
|
|
1324
1417
|
return headers;
|
|
1418
|
+
const canonical = new Set([...aliases.values()].map(normalizeDebugKey));
|
|
1419
|
+
const present = new Set(Object.keys(headers).map(normalizeDebugKey).filter((key) => canonical.has(key)));
|
|
1420
|
+
const result = {};
|
|
1421
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1422
|
+
const target = aliases.get(normalizeDebugKey(key));
|
|
1423
|
+
if (target === void 0) {
|
|
1424
|
+
result[key] = value;
|
|
1425
|
+
} else if (!present.has(normalizeDebugKey(target))) {
|
|
1426
|
+
result[target] = value;
|
|
1427
|
+
present.add(normalizeDebugKey(target));
|
|
1428
|
+
}
|
|
1429
|
+
}
|
|
1430
|
+
return result;
|
|
1431
|
+
}
|
|
1432
|
+
function aliasMap(aliases = {}) {
|
|
1433
|
+
return new Map(Object.entries(aliases).map(([alias, target]) => [normalizeDebugKey(alias), target]));
|
|
1434
|
+
}
|
|
1435
|
+
function sessionHeaders(source, callerHeaders, operator, basicKeys, operatorSettingsOverHttp) {
|
|
1436
|
+
if (source === "caller") {
|
|
1437
|
+
return mergeHeaders(basicOnly(operator, basicKeys), callerHeaders);
|
|
1325
1438
|
}
|
|
1439
|
+
const base = operatorSettingsOverHttp ? operator : basicOnly(operator, basicKeys);
|
|
1440
|
+
return mergeHeaders(base, basicOnly(callerHeaders, basicKeys));
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
// ../mcp-utils/dist/settings-manager.js
|
|
1444
|
+
var SettingsManager = class _SettingsManager {
|
|
1326
1445
|
/**
|
|
1327
|
-
*
|
|
1446
|
+
* Creates a new SettingsManager
|
|
1447
|
+
* @param settingsClass The Settings class to use for creating settings instances
|
|
1328
1448
|
*/
|
|
1329
|
-
|
|
1330
|
-
|
|
1449
|
+
constructor(settingsClass) {
|
|
1450
|
+
this.settingsMap = /* @__PURE__ */ new Map();
|
|
1451
|
+
this.defaultSessionId = "default";
|
|
1452
|
+
this.operatorValues = {};
|
|
1453
|
+
this.sessionSources = /* @__PURE__ */ new Map();
|
|
1454
|
+
this.settingsClass = settingsClass;
|
|
1455
|
+
this.loggableKeys = debugLoggableKeys(settingsClass?.debugLoggableKeys ?? []);
|
|
1456
|
+
this.basicKeys = keySet(settingsClass?.basicKeys ?? []);
|
|
1457
|
+
this.headerAliases = aliasMap(settingsClass?.headerAliases);
|
|
1458
|
+
this.operatorSettingsOverHttp = settingsClass?.operatorSettingsOverHttp !== false;
|
|
1331
1459
|
}
|
|
1332
1460
|
/**
|
|
1333
|
-
*
|
|
1461
|
+
* Get settings for a specific session
|
|
1462
|
+
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1463
|
+
* @returns Settings instance for the session
|
|
1334
1464
|
*/
|
|
1335
|
-
|
|
1336
|
-
|
|
1465
|
+
getSettings(sessionId) {
|
|
1466
|
+
const sid = sessionId || this.defaultSessionId;
|
|
1467
|
+
if (!this.settingsMap.has(sid)) {
|
|
1468
|
+
this.settingsMap.set(sid, new this.settingsClass());
|
|
1469
|
+
}
|
|
1470
|
+
return this.settingsMap.get(sid);
|
|
1337
1471
|
}
|
|
1338
1472
|
/**
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
this.
|
|
1346
|
-
this.sessionTimeout = Number.MAX_SAFE_INTEGER / 1e3;
|
|
1473
|
+
* Set settings for a specific session
|
|
1474
|
+
* @param settings The settings object to set
|
|
1475
|
+
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1476
|
+
*/
|
|
1477
|
+
setSettings(settings, sessionId) {
|
|
1478
|
+
const sid = sessionId || this.defaultSessionId;
|
|
1479
|
+
this.settingsMap.set(sid, settings);
|
|
1347
1480
|
}
|
|
1348
1481
|
/**
|
|
1349
|
-
*
|
|
1482
|
+
* Injects debug settings from source into settings object
|
|
1483
|
+
* @param settings The settings object to update
|
|
1484
|
+
* @param source Source object containing debug information
|
|
1485
|
+
* @param scope 'process' when the operator set debug (CLI/env), which also
|
|
1486
|
+
* updates the process-wide state; 'session' when a caller set it through a
|
|
1487
|
+
* header, which affects only that session's settings
|
|
1488
|
+
* @private
|
|
1350
1489
|
*/
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1490
|
+
injectDebug(settings, source, scope) {
|
|
1491
|
+
const debug = source?.debug ?? _SettingsManager.globalDebugState ?? process.env.DEBUG;
|
|
1492
|
+
if (typeof debug !== "undefined") {
|
|
1493
|
+
if (scope === "process" && source?.debug !== void 0) {
|
|
1494
|
+
_SettingsManager.globalDebugState = source.debug;
|
|
1495
|
+
}
|
|
1496
|
+
if (typeof settings.set === "function") {
|
|
1497
|
+
settings.set("debug", debug);
|
|
1498
|
+
} else {
|
|
1499
|
+
settings.debug = debug;
|
|
1500
|
+
}
|
|
1501
|
+
if (debug) {
|
|
1502
|
+
console.error("Debug enabled. Source:");
|
|
1503
|
+
this.printDebugView(source);
|
|
1504
|
+
}
|
|
1354
1505
|
}
|
|
1355
|
-
return true;
|
|
1356
1506
|
}
|
|
1357
1507
|
/**
|
|
1358
|
-
*
|
|
1508
|
+
* Print settings object for debugging by dynamically discovering its properties
|
|
1509
|
+
* @param settings The settings object to print
|
|
1510
|
+
* @private
|
|
1359
1511
|
*/
|
|
1360
|
-
|
|
1361
|
-
if (
|
|
1362
|
-
|
|
1512
|
+
printSettingsDebug(settings) {
|
|
1513
|
+
if (typeof settings.get === "function") {
|
|
1514
|
+
console.error("Settings (using get method):");
|
|
1515
|
+
if (settings.data && typeof settings.data === "object") {
|
|
1516
|
+
this.printDebugView(settings.data);
|
|
1517
|
+
} else {
|
|
1518
|
+
console.error(" Unable to enumerate settings properties - no accessible data structure");
|
|
1519
|
+
}
|
|
1520
|
+
} else {
|
|
1521
|
+
console.error("Settings (plain object):");
|
|
1522
|
+
this.printDebugView(settings);
|
|
1363
1523
|
}
|
|
1364
|
-
return this.isMDS;
|
|
1365
1524
|
}
|
|
1366
|
-
/**
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1525
|
+
/** Print allowlisted values; everything else as "(hidden, N chars)". */
|
|
1526
|
+
printDebugView(record) {
|
|
1527
|
+
Object.entries(debugView(record, this.loggableKeys)).forEach(([key, value]) => {
|
|
1528
|
+
console.error(` ${key}: ${value}`);
|
|
1529
|
+
});
|
|
1371
1530
|
}
|
|
1372
1531
|
/**
|
|
1373
|
-
*
|
|
1532
|
+
* Create settings from command-line arguments
|
|
1533
|
+
* @param args Command line arguments
|
|
1534
|
+
* @param sessionId Optional session ID
|
|
1535
|
+
* @returns Settings instance
|
|
1374
1536
|
*/
|
|
1375
|
-
|
|
1376
|
-
|
|
1537
|
+
createFromArgs(args, sessionId) {
|
|
1538
|
+
const settings = this.settingsClass.fromArgs(args);
|
|
1539
|
+
this.injectDebug(settings, args, "process");
|
|
1540
|
+
this.setSettings(settings, sessionId);
|
|
1541
|
+
return settings;
|
|
1377
1542
|
}
|
|
1378
1543
|
/**
|
|
1379
|
-
*
|
|
1380
|
-
*
|
|
1544
|
+
* Record the operator's values (environment variables and parsed CLI
|
|
1545
|
+
* options, keyed by environment-variable name). HTTP sessions take basic
|
|
1546
|
+
* keys from them when the caller doesn't send its own, and their whole
|
|
1547
|
+
* connection set when the caller sends none of it.
|
|
1381
1548
|
*/
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
Object.assign(newClient, originalClient);
|
|
1385
|
-
newClient.sid = sid;
|
|
1386
|
-
newClient.sessionStart = Date.now();
|
|
1387
|
-
return newClient;
|
|
1549
|
+
setOperatorValues(values) {
|
|
1550
|
+
this.operatorValues = canonicalizeAliases(operatorHeaders(values), this.headerAliases);
|
|
1388
1551
|
}
|
|
1389
1552
|
/**
|
|
1390
|
-
*
|
|
1553
|
+
* Create settings from HTTP headers
|
|
1554
|
+
* @param headers HTTP headers
|
|
1555
|
+
* @param sessionId Optional session ID
|
|
1556
|
+
* @returns Settings instance
|
|
1391
1557
|
*/
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
if (error instanceof ClientResponse) {
|
|
1398
|
-
console.error(`Login failed with status ${error.status}:`, error.response);
|
|
1399
|
-
return error;
|
|
1400
|
-
}
|
|
1401
|
-
console.error("Login failed with unexpected error:", error);
|
|
1402
|
-
return new ClientResponse(500, { error: "Authentication failed", message: error.message });
|
|
1403
|
-
}
|
|
1558
|
+
createFromHeaders(headers, sessionId) {
|
|
1559
|
+
const verbose = _SettingsManager.globalDebugState;
|
|
1560
|
+
if (verbose) {
|
|
1561
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Starting with session:", sessionLogLabel(sessionId));
|
|
1562
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Incoming headers count:", Object.keys(headers).length);
|
|
1404
1563
|
}
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1564
|
+
if (_SettingsManager.globalDebugState) {
|
|
1565
|
+
console.error("=== createFromHeaders Debug Info ===");
|
|
1566
|
+
console.error("Incoming headers:");
|
|
1567
|
+
this.printDebugView(headers);
|
|
1408
1568
|
}
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
}
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
this.sessionStart = null;
|
|
1419
|
-
try {
|
|
1420
|
-
await this.login();
|
|
1421
|
-
} catch (loginError) {
|
|
1422
|
-
if (loginError instanceof ClientResponse) {
|
|
1423
|
-
console.error(`Login retry failed with status ${loginError.status}:`, loginError.response);
|
|
1424
|
-
return loginError;
|
|
1425
|
-
}
|
|
1426
|
-
console.error("Login retry failed with unexpected error:", loginError);
|
|
1427
|
-
throw loginError;
|
|
1428
|
-
}
|
|
1429
|
-
return await this.makeRequest(this.getHost(), method, uri, data, this.getHeaders(), params, httpsAgent);
|
|
1569
|
+
if (verbose && (!headers || Object.keys(headers).length === 0)) {
|
|
1570
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: WARNING - Headers object is empty or undefined");
|
|
1571
|
+
}
|
|
1572
|
+
const normalizedHeaders = {};
|
|
1573
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
1574
|
+
const normalizedKey = key.includes("_") ? key.replace(/_/g, "-") : key;
|
|
1575
|
+
normalizedHeaders[normalizedKey] = value;
|
|
1576
|
+
if (verbose) {
|
|
1577
|
+
console.error(`[SettingsManager.createFromHeaders] Verbose: Header normalized: "${key}" -> "${normalizedKey}"`);
|
|
1430
1578
|
}
|
|
1431
|
-
throw error;
|
|
1432
1579
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
* Check if the session is expired based on sessionTimeout and sessionStart
|
|
1436
|
-
*/
|
|
1437
|
-
isSessionExpired() {
|
|
1438
|
-
if (!this.sid || !this.sessionTimeout || !this.sessionStart)
|
|
1439
|
-
return true;
|
|
1440
|
-
const now = Date.now();
|
|
1441
|
-
return now > this.sessionStart + (this.sessionTimeout - 5) * 1e3;
|
|
1442
|
-
}
|
|
1443
|
-
getHeadersForLogin() {
|
|
1444
|
-
return { "Content-Type": "application/json" };
|
|
1445
|
-
}
|
|
1446
|
-
/**
|
|
1447
|
-
* Login to the API using the API key
|
|
1448
|
-
*/
|
|
1449
|
-
async login() {
|
|
1450
|
-
if (this._externalSid) {
|
|
1451
|
-
if (!this.sid)
|
|
1452
|
-
throw new Error("External SID has expired");
|
|
1453
|
-
return this.sid;
|
|
1580
|
+
if (verbose) {
|
|
1581
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Normalized headers count:", Object.keys(normalizedHeaders).length);
|
|
1454
1582
|
}
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
if (loginResp.status !== 200 || !loginResp.response || !loginResp.response.sid) {
|
|
1458
|
-
throw loginResp;
|
|
1583
|
+
if (_SettingsManager.globalDebugState) {
|
|
1584
|
+
console.error("Normalized header names:", Object.keys(normalizedHeaders));
|
|
1459
1585
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1586
|
+
const debugHeader = normalizedHeaders["debug"] || normalizedHeaders["Debug"] || normalizedHeaders["DEBUG"];
|
|
1587
|
+
const requestedDebug = Array.isArray(debugHeader) ? debugHeader[0] : debugHeader;
|
|
1588
|
+
const debugSource = {
|
|
1589
|
+
debug: requestedDebug !== void 0 ? requestedDebug.toLowerCase() === "true" : _SettingsManager.globalDebugState
|
|
1590
|
+
};
|
|
1591
|
+
const callerHeaders = canonicalizeAliases(normalizedHeaders, this.headerAliases);
|
|
1592
|
+
const source = this.connectionSource(callerHeaders, sessionId);
|
|
1593
|
+
const inputHeaders = sessionHeaders(source, callerHeaders, this.operatorValues, this.basicKeys, this.operatorSettingsOverHttp);
|
|
1594
|
+
if (verbose) {
|
|
1595
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Connection settings source:", source);
|
|
1596
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Calling settingsClass.fromHeaders");
|
|
1465
1597
|
}
|
|
1466
|
-
|
|
1598
|
+
const settings = this.settingsClass.fromHeaders(inputHeaders);
|
|
1599
|
+
if (verbose) {
|
|
1600
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Settings object created");
|
|
1601
|
+
}
|
|
1602
|
+
this.injectDebug(settings, debugSource, "session");
|
|
1603
|
+
if (_SettingsManager.globalDebugState) {
|
|
1604
|
+
console.error("Final settings object for session:", sessionLogLabel(sessionId));
|
|
1605
|
+
this.printSettingsDebug(settings);
|
|
1606
|
+
console.error("=== End createFromHeaders Debug Info ===");
|
|
1607
|
+
}
|
|
1608
|
+
if (verbose) {
|
|
1609
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Storing settings for session:", sessionLogLabel(sessionId));
|
|
1610
|
+
}
|
|
1611
|
+
this.setSettings(settings, sessionId);
|
|
1612
|
+
return settings;
|
|
1467
1613
|
}
|
|
1468
1614
|
/**
|
|
1469
|
-
*
|
|
1615
|
+
* Clear settings for a session
|
|
1616
|
+
* @param sessionId The session ID to clear
|
|
1470
1617
|
*/
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
1476
|
-
}
|
|
1477
|
-
const sessionResp = await this.makeRequest(this.getHost(), "POST", "show-session", { uid: sessionUid }, this.getHeaders(), null, httpsAgent);
|
|
1478
|
-
if (sessionResp.status === 200 && sessionResp.response?.domain?.["domain-type"] === "mds") {
|
|
1479
|
-
this.isMDS = true;
|
|
1480
|
-
}
|
|
1481
|
-
} catch (error) {
|
|
1482
|
-
console.warn("Could not determine MDS status:", error);
|
|
1483
|
-
this.isMDS = false;
|
|
1618
|
+
clearSession(sessionId) {
|
|
1619
|
+
if (sessionId !== this.defaultSessionId) {
|
|
1620
|
+
this.settingsMap.delete(sessionId);
|
|
1621
|
+
this.sessionSources.delete(sessionId);
|
|
1484
1622
|
}
|
|
1485
1623
|
}
|
|
1486
1624
|
/**
|
|
1487
|
-
*
|
|
1625
|
+
* The session's connection source: decided by the request that creates the
|
|
1626
|
+
* session and kept for its lifetime, so a later request cannot switch it.
|
|
1488
1627
|
*/
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
};
|
|
1498
|
-
if (httpsAgent) {
|
|
1499
|
-
config.httpsAgent = httpsAgent;
|
|
1500
|
-
}
|
|
1501
|
-
if (method.toUpperCase() !== "GET" && data !== void 0) {
|
|
1502
|
-
config.data = data;
|
|
1503
|
-
}
|
|
1504
|
-
console.error(`API Request: ${method} ${url}`);
|
|
1505
|
-
try {
|
|
1506
|
-
const response = await axios(config);
|
|
1507
|
-
return new ClientResponse(response.status, response.data);
|
|
1508
|
-
} catch (error) {
|
|
1509
|
-
if (error.response) {
|
|
1510
|
-
console.error(`\u274C API Error (${error.response.status}):`);
|
|
1511
|
-
console.error("Headers:", error.response.headers);
|
|
1512
|
-
console.error("Data:", error.response.data);
|
|
1513
|
-
if (this.debug) {
|
|
1514
|
-
console.error("Debug mode: Printing request details:");
|
|
1515
|
-
console.error("Request Method:", method);
|
|
1516
|
-
console.error("Request URL:", url);
|
|
1517
|
-
console.error("Request Headers:", config.headers);
|
|
1518
|
-
console.error("Request Data:", config.data);
|
|
1519
|
-
console.error("Request Params:", config.params);
|
|
1520
|
-
}
|
|
1521
|
-
}
|
|
1522
|
-
if (error.response) {
|
|
1523
|
-
throw new Error(`API request failed: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
|
|
1524
|
-
}
|
|
1525
|
-
throw error;
|
|
1526
|
-
}
|
|
1628
|
+
connectionSource(headers, sessionId) {
|
|
1629
|
+
const known = sessionId ? this.sessionSources.get(sessionId) : void 0;
|
|
1630
|
+
if (known)
|
|
1631
|
+
return known;
|
|
1632
|
+
const source = chooseConnectionSource(headersRead((h) => this.settingsClass.fromHeaders(h), headers), this.basicKeys);
|
|
1633
|
+
if (sessionId)
|
|
1634
|
+
this.sessionSources.set(sessionId, source);
|
|
1635
|
+
return source;
|
|
1527
1636
|
}
|
|
1528
1637
|
};
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1638
|
+
SettingsManager.globalDebugState = void 0;
|
|
1639
|
+
|
|
1640
|
+
// ../mcp-utils/dist/telemetry.js
|
|
1641
|
+
import machineIdPkg from "node-machine-id";
|
|
1642
|
+
import { createHash as createHash2 } from "crypto";
|
|
1643
|
+
var { machineIdSync } = machineIdPkg;
|
|
1644
|
+
var machineId = null;
|
|
1645
|
+
var hashedMachineId = null;
|
|
1646
|
+
var transportType = "stdio";
|
|
1647
|
+
function setTransportType(type) {
|
|
1648
|
+
transportType = type;
|
|
1649
|
+
}
|
|
1650
|
+
function isTelemetryDisabled() {
|
|
1651
|
+
return process.env.TELEMETRY_DISABLED === "true" || process.env.TELEMETRY_DISABLED === "1";
|
|
1652
|
+
}
|
|
1653
|
+
function getTelemetryUrl() {
|
|
1654
|
+
return process.env.TELEMETRY_URL || "https://metrics.security.ai.checkpoint.com/api/v1/metrics/collect";
|
|
1655
|
+
}
|
|
1656
|
+
function hashString(input) {
|
|
1657
|
+
return createHash2("sha256").update(input).digest("hex");
|
|
1658
|
+
}
|
|
1659
|
+
function getMachineId() {
|
|
1660
|
+
if (!machineId) {
|
|
1661
|
+
try {
|
|
1662
|
+
machineId = machineIdSync();
|
|
1663
|
+
} catch (error) {
|
|
1664
|
+
console.warn("Failed to get machine ID for telemetry:", error);
|
|
1665
|
+
machineId = "unknown";
|
|
1541
1666
|
}
|
|
1542
|
-
return headers;
|
|
1543
1667
|
}
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
this.managementPort = managementPort;
|
|
1550
|
-
this.domain = domain;
|
|
1551
|
-
this.username = username;
|
|
1552
|
-
this.password = password;
|
|
1668
|
+
return machineId;
|
|
1669
|
+
}
|
|
1670
|
+
function getHashedMachineId() {
|
|
1671
|
+
if (!hashedMachineId) {
|
|
1672
|
+
hashedMachineId = hashString(getMachineId());
|
|
1553
1673
|
}
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1674
|
+
return hashedMachineId;
|
|
1675
|
+
}
|
|
1676
|
+
function calculateChecksum(mcpName, toolName, machineId2, clientVersion) {
|
|
1677
|
+
const data = mcpName + machineId2.slice(0, 16) + toolName + clientVersion;
|
|
1678
|
+
return hashString(data);
|
|
1679
|
+
}
|
|
1680
|
+
async function trackToolCall(mcpName, toolName, clientVersion, extra) {
|
|
1681
|
+
if (isTelemetryDisabled()) {
|
|
1682
|
+
return;
|
|
1558
1683
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
if (this.domain) {
|
|
1577
|
-
loginPayload["domain"] = this.domain;
|
|
1578
|
-
}
|
|
1579
|
-
const loginResp = await this.makeRequest(this.getHost(), "POST", "login", loginPayload, { "Content-Type": "application/json" }, null, httpsAgent);
|
|
1580
|
-
if (loginResp.status !== 200 || !loginResp.response || !loginResp.response.sid) {
|
|
1581
|
-
throw loginResp;
|
|
1582
|
-
}
|
|
1583
|
-
this.sid = loginResp.response.sid;
|
|
1584
|
-
this.sessionTimeout = loginResp.response["session-timeout"] || null;
|
|
1585
|
-
this.sessionStart = Date.now();
|
|
1586
|
-
if (loginResp.response.uid) {
|
|
1587
|
-
await this.detectMDS(loginResp.response.uid, true);
|
|
1588
|
-
}
|
|
1589
|
-
return loginResp.response.sid;
|
|
1684
|
+
try {
|
|
1685
|
+
const machineId2 = getHashedMachineId();
|
|
1686
|
+
const checksum = calculateChecksum(mcpName, toolName, machineId2, clientVersion);
|
|
1687
|
+
fetch(getTelemetryUrl(), {
|
|
1688
|
+
method: "POST",
|
|
1689
|
+
headers: { "Content-Type": "application/json" },
|
|
1690
|
+
body: JSON.stringify({
|
|
1691
|
+
mcp_name: mcpName,
|
|
1692
|
+
tool_name: toolName,
|
|
1693
|
+
machine_id: machineId2,
|
|
1694
|
+
client_version: clientVersion,
|
|
1695
|
+
transport_type: transportType,
|
|
1696
|
+
checksum
|
|
1697
|
+
})
|
|
1698
|
+
}).catch(() => {
|
|
1699
|
+
});
|
|
1700
|
+
} catch (error) {
|
|
1590
1701
|
}
|
|
1591
|
-
};
|
|
1592
|
-
|
|
1593
|
-
// ../infra/dist/string-utils.js
|
|
1594
|
-
function nullOrEmpty(val) {
|
|
1595
|
-
return val === void 0 || val === null || typeof val === "string" && (val.trim() === "" || val === "undefined" || val === "null");
|
|
1596
1702
|
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1703
|
+
|
|
1704
|
+
// ../mcp-utils/dist/launcher.js
|
|
1705
|
+
function mirrorBooleanFlagsToEnv(config, options) {
|
|
1706
|
+
for (const option of config.options) {
|
|
1707
|
+
if (option.type !== "boolean" || !option.env)
|
|
1601
1708
|
continue;
|
|
1709
|
+
const derived = optionKey(option.flag);
|
|
1710
|
+
if (!derived)
|
|
1711
|
+
continue;
|
|
1712
|
+
if (derived.negated) {
|
|
1713
|
+
throw new Error(`Option '${option.flag}' in the configuration for '${config.name}' is a negatable flag paired with env var '${option.env}', which cannot be mirrored automatically: commander keys it as '${derived.key}' and inverts its meaning, so whether the flag being present should set '${option.env}' to 'true' or 'false' depends on how that variable is named. Mirror it explicitly in launchMCPServer instead, the way --no-telemetry does for TELEMETRY_DISABLED.`);
|
|
1714
|
+
}
|
|
1715
|
+
if (options[derived.key] === true) {
|
|
1716
|
+
process.env[option.env] = "true";
|
|
1602
1717
|
}
|
|
1603
|
-
const safeKey = key.replace(/_/g, "-");
|
|
1604
|
-
data[safeKey] = value;
|
|
1605
|
-
}
|
|
1606
|
-
return data;
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
// ../mcp-utils/dist/cli-options.js
|
|
1610
|
-
function booleanOptionDefault(envValue, optionDefault) {
|
|
1611
|
-
return envValue === "true" || optionDefault === "true";
|
|
1612
|
-
}
|
|
1613
|
-
|
|
1614
|
-
// ../mcp-utils/dist/launcher.js
|
|
1615
|
-
import { Command } from "commander";
|
|
1616
|
-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
1617
|
-
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
1618
|
-
import fs from "fs";
|
|
1619
|
-
import http from "http";
|
|
1620
|
-
import { randomUUID } from "crypto";
|
|
1621
|
-
|
|
1622
|
-
// ../mcp-utils/dist/settings-manager.js
|
|
1623
|
-
var SettingsManager = class _SettingsManager {
|
|
1624
|
-
/**
|
|
1625
|
-
* Creates a new SettingsManager
|
|
1626
|
-
* @param settingsClass The Settings class to use for creating settings instances
|
|
1627
|
-
*/
|
|
1628
|
-
constructor(settingsClass) {
|
|
1629
|
-
this.settingsMap = /* @__PURE__ */ new Map();
|
|
1630
|
-
this.defaultSessionId = "default";
|
|
1631
|
-
this.settingsClass = settingsClass;
|
|
1632
|
-
}
|
|
1633
|
-
/**
|
|
1634
|
-
* Get settings for a specific session
|
|
1635
|
-
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1636
|
-
* @returns Settings instance for the session
|
|
1637
|
-
*/
|
|
1638
|
-
getSettings(sessionId) {
|
|
1639
|
-
const sid = sessionId || this.defaultSessionId;
|
|
1640
|
-
if (!this.settingsMap.has(sid)) {
|
|
1641
|
-
this.settingsMap.set(sid, new this.settingsClass());
|
|
1642
|
-
}
|
|
1643
|
-
return this.settingsMap.get(sid);
|
|
1644
|
-
}
|
|
1645
|
-
/**
|
|
1646
|
-
* Set settings for a specific session
|
|
1647
|
-
* @param settings The settings object to set
|
|
1648
|
-
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1649
|
-
*/
|
|
1650
|
-
setSettings(settings, sessionId) {
|
|
1651
|
-
const sid = sessionId || this.defaultSessionId;
|
|
1652
|
-
this.settingsMap.set(sid, settings);
|
|
1653
|
-
}
|
|
1654
|
-
/**
|
|
1655
|
-
* Injects debug settings from source into settings object
|
|
1656
|
-
* @param settings The settings object to update
|
|
1657
|
-
* @param source Source object containing debug information
|
|
1658
|
-
* @private
|
|
1659
|
-
*/
|
|
1660
|
-
injectDebug(settings, source) {
|
|
1661
|
-
const debug = source?.debug ?? _SettingsManager.globalDebugState ?? process.env.DEBUG;
|
|
1662
|
-
if (typeof debug !== "undefined") {
|
|
1663
|
-
if (source?.debug !== void 0) {
|
|
1664
|
-
_SettingsManager.globalDebugState = source.debug;
|
|
1665
|
-
}
|
|
1666
|
-
if (typeof settings.set === "function") {
|
|
1667
|
-
settings.set("debug", debug);
|
|
1668
|
-
} else {
|
|
1669
|
-
settings.debug = debug;
|
|
1670
|
-
}
|
|
1671
|
-
if (debug) {
|
|
1672
|
-
console.error("Debug enabled. Source object contents:");
|
|
1673
|
-
console.error(JSON.stringify(source, null, 2));
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
/**
|
|
1678
|
-
* Print settings object for debugging by dynamically discovering its properties
|
|
1679
|
-
* @param settings The settings object to print
|
|
1680
|
-
* @private
|
|
1681
|
-
*/
|
|
1682
|
-
printSettingsDebug(settings) {
|
|
1683
|
-
if (typeof settings.get === "function") {
|
|
1684
|
-
console.error("Settings (using get method):");
|
|
1685
|
-
if (settings.data && typeof settings.data === "object") {
|
|
1686
|
-
Object.entries(settings.data).forEach(([key, value]) => {
|
|
1687
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
1688
|
-
});
|
|
1689
|
-
} else {
|
|
1690
|
-
console.error(" Unable to enumerate settings properties - no accessible data structure");
|
|
1691
|
-
}
|
|
1692
|
-
} else {
|
|
1693
|
-
console.error("Settings (plain object):");
|
|
1694
|
-
Object.entries(settings).forEach(([key, value]) => {
|
|
1695
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
1696
|
-
});
|
|
1697
|
-
}
|
|
1698
|
-
}
|
|
1699
|
-
/**
|
|
1700
|
-
* Create settings from command-line arguments
|
|
1701
|
-
* @param args Command line arguments
|
|
1702
|
-
* @param sessionId Optional session ID
|
|
1703
|
-
* @returns Settings instance
|
|
1704
|
-
*/
|
|
1705
|
-
createFromArgs(args, sessionId) {
|
|
1706
|
-
const settings = this.settingsClass.fromArgs(args);
|
|
1707
|
-
this.injectDebug(settings, args);
|
|
1708
|
-
this.setSettings(settings, sessionId);
|
|
1709
|
-
return settings;
|
|
1710
|
-
}
|
|
1711
|
-
/**
|
|
1712
|
-
* Create settings from HTTP headers
|
|
1713
|
-
* @param headers HTTP headers
|
|
1714
|
-
* @param sessionId Optional session ID
|
|
1715
|
-
* @returns Settings instance
|
|
1716
|
-
*/
|
|
1717
|
-
createFromHeaders(headers, sessionId) {
|
|
1718
|
-
const verbose = _SettingsManager.globalDebugState;
|
|
1719
|
-
if (verbose) {
|
|
1720
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Starting with sessionId:", sessionId || "(default)");
|
|
1721
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Incoming headers count:", Object.keys(headers).length);
|
|
1722
|
-
}
|
|
1723
|
-
if (_SettingsManager.globalDebugState) {
|
|
1724
|
-
console.error("=== createFromHeaders Debug Info ===");
|
|
1725
|
-
console.error("Incoming headers:");
|
|
1726
|
-
console.error(JSON.stringify(headers, null, 2));
|
|
1727
|
-
}
|
|
1728
|
-
if (verbose && (!headers || Object.keys(headers).length === 0)) {
|
|
1729
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: WARNING - Headers object is empty or undefined");
|
|
1730
|
-
}
|
|
1731
|
-
const normalizedHeaders = {};
|
|
1732
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
1733
|
-
const normalizedKey = key.includes("_") ? key.replace(/_/g, "-") : key;
|
|
1734
|
-
normalizedHeaders[normalizedKey] = value;
|
|
1735
|
-
if (verbose) {
|
|
1736
|
-
console.error(`[SettingsManager.createFromHeaders] Verbose: Header normalized: "${key}" -> "${normalizedKey}"`);
|
|
1737
|
-
}
|
|
1738
|
-
}
|
|
1739
|
-
if (verbose) {
|
|
1740
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Normalized headers count:", Object.keys(normalizedHeaders).length);
|
|
1741
|
-
}
|
|
1742
|
-
if (_SettingsManager.globalDebugState) {
|
|
1743
|
-
console.error("Normalized headers:");
|
|
1744
|
-
console.error(JSON.stringify(normalizedHeaders, null, 2));
|
|
1745
|
-
}
|
|
1746
|
-
const debugHeader = normalizedHeaders["debug"] || normalizedHeaders["Debug"] || normalizedHeaders["DEBUG"];
|
|
1747
|
-
const debugSource = { debug: debugHeader !== void 0 ? debugHeader : _SettingsManager.globalDebugState };
|
|
1748
|
-
if (verbose) {
|
|
1749
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Calling settingsClass.fromHeaders");
|
|
1750
|
-
}
|
|
1751
|
-
const settings = this.settingsClass.fromHeaders(normalizedHeaders);
|
|
1752
|
-
if (verbose) {
|
|
1753
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Settings object created");
|
|
1754
|
-
}
|
|
1755
|
-
this.injectDebug(settings, debugSource);
|
|
1756
|
-
if (_SettingsManager.globalDebugState) {
|
|
1757
|
-
console.error("Final settings object for session:", sessionId || "(default)");
|
|
1758
|
-
this.printSettingsDebug(settings);
|
|
1759
|
-
console.error("=== End createFromHeaders Debug Info ===");
|
|
1760
|
-
}
|
|
1761
|
-
if (verbose) {
|
|
1762
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Storing settings for session:", sessionId || "(default)");
|
|
1763
|
-
}
|
|
1764
|
-
this.setSettings(settings, sessionId);
|
|
1765
|
-
return settings;
|
|
1766
|
-
}
|
|
1767
|
-
/**
|
|
1768
|
-
* Clear settings for a session
|
|
1769
|
-
* @param sessionId The session ID to clear
|
|
1770
|
-
*/
|
|
1771
|
-
clearSession(sessionId) {
|
|
1772
|
-
if (sessionId !== this.defaultSessionId) {
|
|
1773
|
-
this.settingsMap.delete(sessionId);
|
|
1774
|
-
}
|
|
1775
|
-
}
|
|
1776
|
-
};
|
|
1777
|
-
SettingsManager.globalDebugState = void 0;
|
|
1778
|
-
|
|
1779
|
-
// ../mcp-utils/dist/telemetry.js
|
|
1780
|
-
import machineIdPkg from "node-machine-id";
|
|
1781
|
-
import { createHash } from "crypto";
|
|
1782
|
-
var { machineIdSync } = machineIdPkg;
|
|
1783
|
-
var machineId = null;
|
|
1784
|
-
var hashedMachineId = null;
|
|
1785
|
-
var transportType = "stdio";
|
|
1786
|
-
function setTransportType(type) {
|
|
1787
|
-
transportType = type;
|
|
1788
|
-
}
|
|
1789
|
-
function isTelemetryDisabled() {
|
|
1790
|
-
return process.env.TELEMETRY_DISABLED === "true" || process.env.TELEMETRY_DISABLED === "1";
|
|
1791
|
-
}
|
|
1792
|
-
function getTelemetryUrl() {
|
|
1793
|
-
return process.env.TELEMETRY_URL || "https://metrics.security.ai.checkpoint.com/api/v1/metrics/collect";
|
|
1794
|
-
}
|
|
1795
|
-
function hashString(input) {
|
|
1796
|
-
return createHash("sha256").update(input).digest("hex");
|
|
1797
|
-
}
|
|
1798
|
-
function getMachineId() {
|
|
1799
|
-
if (!machineId) {
|
|
1800
|
-
try {
|
|
1801
|
-
machineId = machineIdSync();
|
|
1802
|
-
} catch (error) {
|
|
1803
|
-
console.warn("Failed to get machine ID for telemetry:", error);
|
|
1804
|
-
machineId = "unknown";
|
|
1805
|
-
}
|
|
1806
|
-
}
|
|
1807
|
-
return machineId;
|
|
1808
|
-
}
|
|
1809
|
-
function getHashedMachineId() {
|
|
1810
|
-
if (!hashedMachineId) {
|
|
1811
|
-
hashedMachineId = hashString(getMachineId());
|
|
1812
|
-
}
|
|
1813
|
-
return hashedMachineId;
|
|
1814
|
-
}
|
|
1815
|
-
function calculateChecksum(mcpName, toolName, machineId2, clientVersion) {
|
|
1816
|
-
const data = mcpName + machineId2.slice(0, 16) + toolName + clientVersion;
|
|
1817
|
-
return hashString(data);
|
|
1818
|
-
}
|
|
1819
|
-
async function trackToolCall(mcpName, toolName, clientVersion, extra) {
|
|
1820
|
-
if (isTelemetryDisabled()) {
|
|
1821
|
-
return;
|
|
1822
|
-
}
|
|
1823
|
-
try {
|
|
1824
|
-
const machineId2 = getHashedMachineId();
|
|
1825
|
-
const checksum = calculateChecksum(mcpName, toolName, machineId2, clientVersion);
|
|
1826
|
-
fetch(getTelemetryUrl(), {
|
|
1827
|
-
method: "POST",
|
|
1828
|
-
headers: { "Content-Type": "application/json" },
|
|
1829
|
-
body: JSON.stringify({
|
|
1830
|
-
mcp_name: mcpName,
|
|
1831
|
-
tool_name: toolName,
|
|
1832
|
-
machine_id: machineId2,
|
|
1833
|
-
client_version: clientVersion,
|
|
1834
|
-
transport_type: transportType,
|
|
1835
|
-
checksum
|
|
1836
|
-
})
|
|
1837
|
-
}).catch(() => {
|
|
1838
|
-
});
|
|
1839
|
-
} catch (error) {
|
|
1840
|
-
}
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
// ../mcp-utils/dist/launcher.js
|
|
1844
|
-
function optionKey(flag) {
|
|
1845
|
-
const long = flag.split(/[,\s]+/).find((part) => part.startsWith("--"));
|
|
1846
|
-
if (!long)
|
|
1847
|
-
return void 0;
|
|
1848
|
-
const negated = long.startsWith("--no-");
|
|
1849
|
-
return {
|
|
1850
|
-
key: long.replace(/^--(no-)?/, "").replace(/-([a-z])/g, (_match, char) => char.toUpperCase()),
|
|
1851
|
-
negated
|
|
1852
|
-
};
|
|
1853
|
-
}
|
|
1854
|
-
function mirrorBooleanFlagsToEnv(config, options) {
|
|
1855
|
-
for (const option of config.options) {
|
|
1856
|
-
if (option.type !== "boolean" || !option.env)
|
|
1857
|
-
continue;
|
|
1858
|
-
const derived = optionKey(option.flag);
|
|
1859
|
-
if (!derived)
|
|
1860
|
-
continue;
|
|
1861
|
-
if (derived.negated) {
|
|
1862
|
-
throw new Error(`Option '${option.flag}' in the configuration for '${config.name}' is a negatable flag paired with env var '${option.env}', which cannot be mirrored automatically: commander keys it as '${derived.key}' and inverts its meaning, so whether the flag being present should set '${option.env}' to 'true' or 'false' depends on how that variable is named. Mirror it explicitly in launchMCPServer instead, the way --no-telemetry does for TELEMETRY_DISABLED.`);
|
|
1863
|
-
}
|
|
1864
|
-
if (options[derived.key] === true) {
|
|
1865
|
-
process.env[option.env] = "true";
|
|
1866
|
-
}
|
|
1867
1718
|
}
|
|
1868
1719
|
}
|
|
1869
1720
|
async function launchMCPServer(configPath, serverModule2) {
|
|
@@ -1901,17 +1752,23 @@ async function launchMCPServer(configPath, serverModule2) {
|
|
|
1901
1752
|
process.env.TELEMETRY_URL = options.telemetryUrl;
|
|
1902
1753
|
}
|
|
1903
1754
|
mirrorBooleanFlagsToEnv(config, options);
|
|
1755
|
+
const transportType2 = resolveTransportType(options.transport);
|
|
1756
|
+
process.env.MCP_TRANSPORT_TYPE = transportType2;
|
|
1904
1757
|
if (!serverModule2.settingsManager) {
|
|
1905
1758
|
throw new Error("ServerModule must have a settingsManager. Create it with createServerModule.");
|
|
1906
1759
|
}
|
|
1907
1760
|
const settings = serverModule2.settingsManager.createFromArgs(options);
|
|
1761
|
+
serverModule2.settingsManager.setOperatorValues?.(operatorValues(config.options, options));
|
|
1908
1762
|
if (typeof serverModule2.server.applyToolPolicy === "function") {
|
|
1909
1763
|
console.error("[launchMCPServer] Applying tool policy before connecting");
|
|
1910
1764
|
serverModule2.server.applyToolPolicy();
|
|
1911
1765
|
}
|
|
1912
|
-
const transportType2 = (options.transport || process.env.MCP_TRANSPORT_TYPE || "stdio").toLowerCase() === "http" ? "http" : "stdio";
|
|
1913
1766
|
const transportPort = options.transportPort ? parseInt(options.transportPort, 10) : process.env.MCP_TRANSPORT_PORT ? parseInt(process.env.MCP_TRANSPORT_PORT, 10) : 3e3;
|
|
1914
1767
|
if (transportType2 === "http") {
|
|
1768
|
+
const refusal = serverModule2.httpStartupCheck?.();
|
|
1769
|
+
if (refusal) {
|
|
1770
|
+
throw new Error(refusal);
|
|
1771
|
+
}
|
|
1915
1772
|
setTransportType("http");
|
|
1916
1773
|
await launchHTTPServer(config, serverModule2, transportPort);
|
|
1917
1774
|
} else {
|
|
@@ -1960,7 +1817,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
1960
1817
|
if (sessionId && transports[sessionId]) {
|
|
1961
1818
|
const verbose = SettingsManager.globalDebugState;
|
|
1962
1819
|
if (verbose) {
|
|
1963
|
-
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionId);
|
|
1820
|
+
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionLogLabel(sessionId));
|
|
1964
1821
|
}
|
|
1965
1822
|
transport = transports[sessionId];
|
|
1966
1823
|
if (!serverModule2.settingsManager) {
|
|
@@ -1980,7 +1837,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
1980
1837
|
onsessioninitialized: (sid) => {
|
|
1981
1838
|
const verbose = SettingsManager.globalDebugState;
|
|
1982
1839
|
if (verbose) {
|
|
1983
|
-
console.error("[launchHTTPServer] Verbose: New session initialized:", sid);
|
|
1840
|
+
console.error("[launchHTTPServer] Verbose: New session initialized:", sessionLogLabel(sid));
|
|
1984
1841
|
}
|
|
1985
1842
|
transports[sid] = transport;
|
|
1986
1843
|
if (verbose) {
|
|
@@ -2183,7 +2040,6 @@ function headersToEnvVars(headers, config) {
|
|
|
2183
2040
|
}
|
|
2184
2041
|
if (verbose) {
|
|
2185
2042
|
console.error("[headersToEnvVars] Verbose: Final result keys:", Object.keys(result));
|
|
2186
|
-
console.error("[headersToEnvVars] Verbose: Final result (sanitized):", Object.fromEntries(Object.entries(result).map(([k, v]) => [k, k.toLowerCase().includes("key") || k.toLowerCase().includes("token") || k.toLowerCase().includes("password") ? "***" : v])));
|
|
2187
2043
|
}
|
|
2188
2044
|
return result;
|
|
2189
2045
|
}
|
|
@@ -2210,7 +2066,7 @@ var APIManagerFactory = class {
|
|
|
2210
2066
|
const verbose = SettingsManager.globalDebugState;
|
|
2211
2067
|
const sid = sessionId || this.defaultSessionId;
|
|
2212
2068
|
if (verbose) {
|
|
2213
|
-
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sid);
|
|
2069
|
+
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sessionLogLabel(sid));
|
|
2214
2070
|
}
|
|
2215
2071
|
if (!this.apiManagerMap.has(sid)) {
|
|
2216
2072
|
if (verbose) {
|
|
@@ -2308,16 +2164,15 @@ var SessionContext = class {
|
|
|
2308
2164
|
/**
|
|
2309
2165
|
* Get the current session ID from the MCP extra context
|
|
2310
2166
|
* @param extra Extra context passed to MCP tool callbacks
|
|
2311
|
-
* @returns The session ID or DEFAULT_SESSION_ID
|
|
2167
|
+
* @returns The session ID, or DEFAULT_SESSION_ID under stdio
|
|
2168
|
+
* @throws Under HTTP transport when the context carries no session ID
|
|
2312
2169
|
*/
|
|
2313
2170
|
static getSessionId(extra) {
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
if (extra.sessionId) {
|
|
2320
|
-
return extra.sessionId;
|
|
2171
|
+
const sessionId = extra?.transport?.sessionId || extra?.sessionId;
|
|
2172
|
+
if (sessionId)
|
|
2173
|
+
return sessionId;
|
|
2174
|
+
if (process.env.MCP_TRANSPORT_TYPE === "http") {
|
|
2175
|
+
throw new Error("No MCP session in this request context; HTTP transport requires one");
|
|
2321
2176
|
}
|
|
2322
2177
|
return this.DEFAULT_SESSION_ID;
|
|
2323
2178
|
}
|
|
@@ -2434,10 +2289,10 @@ var SessionContext = class {
|
|
|
2434
2289
|
}
|
|
2435
2290
|
}
|
|
2436
2291
|
}
|
|
2437
|
-
console.error(`Using cached user data for
|
|
2292
|
+
console.error(`Using cached user data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
2438
2293
|
return { cancelled: false, data: dataToReturn2 };
|
|
2439
2294
|
}
|
|
2440
|
-
console.error(`Prompting user for data for
|
|
2295
|
+
console.error(`Prompting user for data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
2441
2296
|
let result;
|
|
2442
2297
|
if (options.showLoginDialog) {
|
|
2443
2298
|
const { showLoginDialog: showLoginDialog2 } = await Promise.resolve().then(() => (init_ui_dialog(), ui_dialog_exports));
|
|
@@ -2478,338 +2333,691 @@ var SessionContext = class {
|
|
|
2478
2333
|
}
|
|
2479
2334
|
}
|
|
2480
2335
|
}
|
|
2481
|
-
return { cancelled: false, data: dataToReturn };
|
|
2336
|
+
return { cancelled: false, data: dataToReturn };
|
|
2337
|
+
}
|
|
2338
|
+
/**
|
|
2339
|
+
* Clear cached user data for a specific key
|
|
2340
|
+
* @param cacheKey The cache key to clear
|
|
2341
|
+
* @param extra Extra context with session information
|
|
2342
|
+
*/
|
|
2343
|
+
static clearUserData(cacheKey, extra) {
|
|
2344
|
+
const sessionId = this.getSessionId(extra);
|
|
2345
|
+
if (this.sessionData.has(sessionId)) {
|
|
2346
|
+
const sessionInfo = this.sessionData.get(sessionId);
|
|
2347
|
+
sessionInfo.data.delete(cacheKey);
|
|
2348
|
+
sessionInfo.lastAccessed = Date.now();
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
/**
|
|
2352
|
+
* Check if user data exists and is not expired
|
|
2353
|
+
* @param cacheKey The cache key to check
|
|
2354
|
+
* @param extra Extra context with session information
|
|
2355
|
+
* @returns true if valid cached data exists, false otherwise
|
|
2356
|
+
*/
|
|
2357
|
+
static hasValidUserData(cacheKey, extra) {
|
|
2358
|
+
const cachedData = this.getData(cacheKey, extra);
|
|
2359
|
+
if (!cachedData || !cachedData.expiresAt) {
|
|
2360
|
+
return false;
|
|
2361
|
+
}
|
|
2362
|
+
return Date.now() < cachedData.expiresAt;
|
|
2363
|
+
}
|
|
2364
|
+
};
|
|
2365
|
+
_a = SessionContext;
|
|
2366
|
+
SessionContext.DEFAULT_SESSION_ID = "default";
|
|
2367
|
+
SessionContext.sessionData = /* @__PURE__ */ new Map();
|
|
2368
|
+
SessionContext.SESSION_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
2369
|
+
SessionContext.CLEANUP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
2370
|
+
SessionContext.MAX_SESSIONS = 1e3;
|
|
2371
|
+
SessionContext.cleanupTimer = null;
|
|
2372
|
+
(() => {
|
|
2373
|
+
_a.startCleanupTimer();
|
|
2374
|
+
})();
|
|
2375
|
+
|
|
2376
|
+
// ../mcp-utils/dist/session-manager.js
|
|
2377
|
+
var DEFAULT_SESSION_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
2378
|
+
var SessionManager = class {
|
|
2379
|
+
constructor() {
|
|
2380
|
+
this.sessions = /* @__PURE__ */ new Map();
|
|
2381
|
+
}
|
|
2382
|
+
/**
|
|
2383
|
+
* Create a new session
|
|
2384
|
+
* @param sessionId The session ID
|
|
2385
|
+
* @param metadata Optional metadata to store with the session
|
|
2386
|
+
* @returns Session info
|
|
2387
|
+
*/
|
|
2388
|
+
createSession(sessionId, metadata = {}) {
|
|
2389
|
+
const now = /* @__PURE__ */ new Date();
|
|
2390
|
+
const sessionInfo = {
|
|
2391
|
+
sessionId,
|
|
2392
|
+
createdAt: now,
|
|
2393
|
+
lastActive: now,
|
|
2394
|
+
...metadata
|
|
2395
|
+
};
|
|
2396
|
+
this.sessions.set(sessionId, sessionInfo);
|
|
2397
|
+
return sessionInfo;
|
|
2398
|
+
}
|
|
2399
|
+
/**
|
|
2400
|
+
* Get info for a session
|
|
2401
|
+
* @param sessionId The session ID
|
|
2402
|
+
* @returns Session info or undefined if not found
|
|
2403
|
+
*/
|
|
2404
|
+
getSession(sessionId) {
|
|
2405
|
+
if (this.sessions.has(sessionId)) {
|
|
2406
|
+
this.touchSession(sessionId);
|
|
2407
|
+
}
|
|
2408
|
+
return this.sessions.get(sessionId);
|
|
2409
|
+
}
|
|
2410
|
+
/**
|
|
2411
|
+
* Update session activity timestamp
|
|
2412
|
+
* @param sessionId The session ID
|
|
2413
|
+
*/
|
|
2414
|
+
touchSession(sessionId) {
|
|
2415
|
+
const session = this.sessions.get(sessionId);
|
|
2416
|
+
if (session) {
|
|
2417
|
+
session.lastActive = /* @__PURE__ */ new Date();
|
|
2418
|
+
}
|
|
2419
|
+
}
|
|
2420
|
+
/**
|
|
2421
|
+
* Remove a session
|
|
2422
|
+
* @param sessionId The session ID
|
|
2423
|
+
*/
|
|
2424
|
+
removeSession(sessionId) {
|
|
2425
|
+
this.sessions.delete(sessionId);
|
|
2426
|
+
SessionContext.clearSessionData(sessionId);
|
|
2427
|
+
}
|
|
2428
|
+
/**
|
|
2429
|
+
* Get all active sessions
|
|
2430
|
+
* @returns Array of session info objects
|
|
2431
|
+
*/
|
|
2432
|
+
getAllSessions() {
|
|
2433
|
+
return Array.from(this.sessions.values());
|
|
2434
|
+
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Get count of active sessions
|
|
2437
|
+
* @returns Number of active sessions
|
|
2438
|
+
*/
|
|
2439
|
+
getSessionCount() {
|
|
2440
|
+
return this.sessions.size;
|
|
2441
|
+
}
|
|
2442
|
+
/**
|
|
2443
|
+
* Clean up inactive sessions older than the specified timeout
|
|
2444
|
+
* @param timeoutMs Timeout in milliseconds (default: 30 minutes)
|
|
2445
|
+
* @returns Number of sessions removed
|
|
2446
|
+
*/
|
|
2447
|
+
cleanupInactiveSessions(timeoutMs = DEFAULT_SESSION_TIMEOUT_MS) {
|
|
2448
|
+
const now = /* @__PURE__ */ new Date();
|
|
2449
|
+
let removedCount = 0;
|
|
2450
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
2451
|
+
const inactiveTime = now.getTime() - session.lastActive.getTime();
|
|
2452
|
+
if (inactiveTime > timeoutMs) {
|
|
2453
|
+
this.removeSession(sessionId);
|
|
2454
|
+
removedCount++;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
return removedCount;
|
|
2458
|
+
}
|
|
2459
|
+
};
|
|
2460
|
+
|
|
2461
|
+
// ../mcp-utils/dist/server-utils.js
|
|
2462
|
+
function getHeaderValue(headers, key) {
|
|
2463
|
+
const normalizedKey = key.replace(/_/g, "-");
|
|
2464
|
+
const value = headers[normalizedKey] || headers[normalizedKey.toUpperCase()] || headers[normalizedKey.toLowerCase()];
|
|
2465
|
+
return typeof value === "string" ? value : Array.isArray(value) ? value[0] : void 0;
|
|
2466
|
+
}
|
|
2467
|
+
function createApiRunner(serverModule2) {
|
|
2468
|
+
return async (method, uri, data, extra, domain) => {
|
|
2469
|
+
const apiManager = SessionContext.getAPIManager(serverModule2, extra);
|
|
2470
|
+
return await apiManager.callApi(method, uri, data, domain);
|
|
2471
|
+
};
|
|
2472
|
+
}
|
|
2473
|
+
function wrapServerWithTracking(server2, createServerFn) {
|
|
2474
|
+
const registrations = [];
|
|
2475
|
+
const originalTool = server2.tool?.bind(server2);
|
|
2476
|
+
const originalPrompt = server2.prompt?.bind(server2);
|
|
2477
|
+
const originalResource = server2.resource?.bind(server2);
|
|
2478
|
+
if (originalTool) {
|
|
2479
|
+
server2.tool = function(...args) {
|
|
2480
|
+
registrations.push({ type: "tool", method: "tool", args: [...args] });
|
|
2481
|
+
return originalTool(...args);
|
|
2482
|
+
};
|
|
2483
|
+
}
|
|
2484
|
+
if (originalPrompt) {
|
|
2485
|
+
server2.prompt = function(...args) {
|
|
2486
|
+
registrations.push({ type: "prompt", method: "prompt", args: [...args] });
|
|
2487
|
+
return originalPrompt(...args);
|
|
2488
|
+
};
|
|
2489
|
+
}
|
|
2490
|
+
if (originalResource) {
|
|
2491
|
+
server2.resource = function(...args) {
|
|
2492
|
+
registrations.push({ type: "resource", method: "resource", args: [...args] });
|
|
2493
|
+
return originalResource(...args);
|
|
2494
|
+
};
|
|
2495
|
+
}
|
|
2496
|
+
const createInstance = () => {
|
|
2497
|
+
const newServer = createServerFn();
|
|
2498
|
+
for (const reg of registrations) {
|
|
2499
|
+
if (newServer[reg.method]) {
|
|
2500
|
+
newServer[reg.method](...reg.args);
|
|
2501
|
+
}
|
|
2502
|
+
}
|
|
2503
|
+
const toolPolicy = typeof server2.getToolPolicy === "function" ? server2.getToolPolicy() : void 0;
|
|
2504
|
+
if (toolPolicy && typeof newServer.setToolPolicy === "function") {
|
|
2505
|
+
newServer.setToolPolicy(toolPolicy);
|
|
2506
|
+
if (typeof newServer.applyToolPolicy === "function") {
|
|
2507
|
+
newServer.applyToolPolicy();
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
return newServer;
|
|
2511
|
+
};
|
|
2512
|
+
return { wrappedServer: server2, createInstance };
|
|
2513
|
+
}
|
|
2514
|
+
function createServerModule(server2, Settings2, pkg2, apiManagerClass, toolPolicyCallback, createServerFn) {
|
|
2515
|
+
const settingsManager = new SettingsManager(Settings2);
|
|
2516
|
+
const apiManagerFactory = new APIManagerFactory(apiManagerClass, settingsManager);
|
|
2517
|
+
const sessionManager = new SessionManager();
|
|
2518
|
+
if (toolPolicyCallback && typeof server2.setToolPolicy === "function") {
|
|
2519
|
+
console.error("[createServerModule] Setting tool policy callback on server");
|
|
2520
|
+
server2.setToolPolicy(toolPolicyCallback);
|
|
2521
|
+
}
|
|
2522
|
+
const serverFactory = createServerFn || server2._createServerFn;
|
|
2523
|
+
let createServerInstance;
|
|
2524
|
+
if (serverFactory) {
|
|
2525
|
+
const { wrappedServer, createInstance } = wrapServerWithTracking(server2, serverFactory);
|
|
2526
|
+
createServerInstance = createInstance;
|
|
2527
|
+
console.error("[createServerModule] Server factory enabled - HTTP multi-user support active");
|
|
2528
|
+
} else {
|
|
2529
|
+
console.error("[createServerModule] Warning: No server factory provided - HTTP multi-user may have issues");
|
|
2530
|
+
}
|
|
2531
|
+
return {
|
|
2532
|
+
server: server2,
|
|
2533
|
+
Settings: Settings2,
|
|
2534
|
+
settingsManager,
|
|
2535
|
+
apiManagerFactory,
|
|
2536
|
+
sessionManager,
|
|
2537
|
+
pkg: pkg2,
|
|
2538
|
+
toolPolicyCallback,
|
|
2539
|
+
createServerInstance
|
|
2540
|
+
};
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
// ../mcp-utils/dist/index.js
|
|
2544
|
+
init_ui_dialog();
|
|
2545
|
+
|
|
2546
|
+
// ../mcp-utils/dist/mcp-server.js
|
|
2547
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2548
|
+
var CPMcpServer = class extends McpServer {
|
|
2549
|
+
constructor(serverInfo, options) {
|
|
2550
|
+
super(serverInfo, options);
|
|
2551
|
+
this.mcpName = serverInfo.name;
|
|
2552
|
+
this.mcpVersion = serverInfo.version || "0.0.0";
|
|
2553
|
+
}
|
|
2554
|
+
/**
|
|
2555
|
+
* Set a tool policy callback to filter which tools are available
|
|
2556
|
+
* This should be called after all tools are registered but before connecting
|
|
2557
|
+
* @param callback Function that returns true if a tool should be enabled
|
|
2558
|
+
*/
|
|
2559
|
+
setToolPolicy(callback) {
|
|
2560
|
+
console.error("[CPMcpServer] Setting tool policy callback");
|
|
2561
|
+
this.toolPolicyCallback = callback;
|
|
2562
|
+
}
|
|
2563
|
+
/**
|
|
2564
|
+
* Get the tool policy callback, if one was set.
|
|
2565
|
+
*
|
|
2566
|
+
* Needed so the policy can be carried onto the per-session server instances
|
|
2567
|
+
* created for HTTP transport. A typed accessor keeps that transfer honest:
|
|
2568
|
+
* callers do not have to reach into the private field, where a misspelling
|
|
2569
|
+
* would go unnoticed by the compiler.
|
|
2570
|
+
*/
|
|
2571
|
+
getToolPolicy() {
|
|
2572
|
+
return this.toolPolicyCallback;
|
|
2573
|
+
}
|
|
2574
|
+
/**
|
|
2575
|
+
* Apply the tool policy by checking all registered tools
|
|
2576
|
+
* This should be called after all tools are registered but before connecting
|
|
2577
|
+
*
|
|
2578
|
+
* Per-tool tracing is behind the debug flag. This used to run once per process
|
|
2579
|
+
* on the template server, where a line per tool was a cheap startup banner.
|
|
2580
|
+
* It now also runs per session under HTTP transport, so unconditional tracing
|
|
2581
|
+
* would scale stderr with sessions x tools and bury the summary. The summary
|
|
2582
|
+
* line always prints — it is the fact worth having for every session.
|
|
2583
|
+
*/
|
|
2584
|
+
applyToolPolicy() {
|
|
2585
|
+
const verbose = SettingsManager.globalDebugState === true || SettingsManager.globalDebugState === "true";
|
|
2586
|
+
if (!this.toolPolicyCallback) {
|
|
2587
|
+
if (verbose) {
|
|
2588
|
+
console.error("[CPMcpServer] No tool policy callback set, allowing all tools");
|
|
2589
|
+
}
|
|
2590
|
+
return;
|
|
2591
|
+
}
|
|
2592
|
+
const registeredTools = this._registeredTools;
|
|
2593
|
+
if (!registeredTools || typeof registeredTools !== "object") {
|
|
2594
|
+
console.error("[CPMcpServer] No tools registered yet");
|
|
2595
|
+
return;
|
|
2596
|
+
}
|
|
2597
|
+
const toolNames = Object.keys(registeredTools);
|
|
2598
|
+
if (verbose) {
|
|
2599
|
+
console.error(`[CPMcpServer] Applying tool policy`);
|
|
2600
|
+
console.error(`[CPMcpServer] Found ${toolNames.length} registered tools:`, toolNames);
|
|
2601
|
+
}
|
|
2602
|
+
let enabledCount = 0;
|
|
2603
|
+
let disabledCount = 0;
|
|
2604
|
+
for (const [toolName, tool] of Object.entries(registeredTools)) {
|
|
2605
|
+
const isAllowed = this.toolPolicyCallback(toolName);
|
|
2606
|
+
if (!isAllowed) {
|
|
2607
|
+
if (verbose) {
|
|
2608
|
+
console.error(`[CPMcpServer] Tool '${toolName}' is NOT allowed by policy - disabling`);
|
|
2609
|
+
}
|
|
2610
|
+
if (typeof tool.disable === "function") {
|
|
2611
|
+
tool.disable();
|
|
2612
|
+
disabledCount++;
|
|
2613
|
+
}
|
|
2614
|
+
} else {
|
|
2615
|
+
if (verbose) {
|
|
2616
|
+
console.error(`[CPMcpServer] Tool '${toolName}' is allowed by policy`);
|
|
2617
|
+
}
|
|
2618
|
+
enabledCount++;
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
console.error(`[CPMcpServer] Policy applied: ${enabledCount}/${toolNames.length} tools enabled, ${disabledCount} disabled`);
|
|
2622
|
+
}
|
|
2623
|
+
// Override the tool method to wrap callbacks with telemetry
|
|
2624
|
+
tool(...args) {
|
|
2625
|
+
const callback = args[args.length - 1];
|
|
2626
|
+
if (typeof callback === "function") {
|
|
2627
|
+
const toolName = args[0];
|
|
2628
|
+
const wrappedCallback = async (...callbackArgs) => {
|
|
2629
|
+
let extra = callbackArgs[1];
|
|
2630
|
+
if (!extra && callbackArgs[0]?.sessionId) {
|
|
2631
|
+
extra = callbackArgs[0];
|
|
2632
|
+
}
|
|
2633
|
+
trackToolCall(this.mcpName, toolName, this.mcpVersion, extra).catch(() => {
|
|
2634
|
+
});
|
|
2635
|
+
if (callbackArgs.length === 1 && callbackArgs[0]?.sessionId) {
|
|
2636
|
+
return callback({}, callbackArgs[0]);
|
|
2637
|
+
}
|
|
2638
|
+
return callback(...callbackArgs);
|
|
2639
|
+
};
|
|
2640
|
+
args[args.length - 1] = wrappedCallback;
|
|
2641
|
+
}
|
|
2642
|
+
return super.tool(...args);
|
|
2643
|
+
}
|
|
2644
|
+
};
|
|
2645
|
+
|
|
2646
|
+
// ../mcp-utils/dist/package-utils.js
|
|
2647
|
+
import { readFileSync } from "fs";
|
|
2648
|
+
import { join as join2, dirname } from "path";
|
|
2649
|
+
import { fileURLToPath } from "url";
|
|
2650
|
+
function readPackageJson(importMetaUrl) {
|
|
2651
|
+
const pkg2 = JSON.parse(readFileSync(join2(dirname(fileURLToPath(importMetaUrl)), "../package.json"), "utf-8"));
|
|
2652
|
+
process.env.CP_MCP_MAIN_PKG = `${pkg2.name} v${pkg2.version}`;
|
|
2653
|
+
return pkg2;
|
|
2654
|
+
}
|
|
2655
|
+
function createMcpServer(importMetaUrl, serverInfo, options) {
|
|
2656
|
+
const pkg2 = readPackageJson(importMetaUrl);
|
|
2657
|
+
const fullServerInfo = {
|
|
2658
|
+
...serverInfo,
|
|
2659
|
+
name: serverInfo.name || pkg2.name,
|
|
2660
|
+
version: serverInfo.version || pkg2.version
|
|
2661
|
+
};
|
|
2662
|
+
const createServerFn = () => {
|
|
2663
|
+
return new CPMcpServer(fullServerInfo, options);
|
|
2664
|
+
};
|
|
2665
|
+
const server2 = new CPMcpServer(fullServerInfo, options);
|
|
2666
|
+
server2._createServerFn = createServerFn;
|
|
2667
|
+
return { server: server2, pkg: pkg2 };
|
|
2668
|
+
}
|
|
2669
|
+
|
|
2670
|
+
// ../infra/dist/api-client.js
|
|
2671
|
+
var DEBUG_LOGGABLE_REQUEST_KEYS = debugLoggableKeys([
|
|
2672
|
+
"details-level",
|
|
2673
|
+
"domain",
|
|
2674
|
+
"filter",
|
|
2675
|
+
"layer",
|
|
2676
|
+
"limit",
|
|
2677
|
+
"name",
|
|
2678
|
+
"offset",
|
|
2679
|
+
"order",
|
|
2680
|
+
"package",
|
|
2681
|
+
"show-membership",
|
|
2682
|
+
"targets",
|
|
2683
|
+
"task-id",
|
|
2684
|
+
"type",
|
|
2685
|
+
"uid",
|
|
2686
|
+
"use-object-dictionary"
|
|
2687
|
+
]);
|
|
2688
|
+
var TokenType;
|
|
2689
|
+
(function(TokenType2) {
|
|
2690
|
+
TokenType2["API_KEY"] = "API_KEY";
|
|
2691
|
+
TokenType2["CI_TOKEN"] = "CI_TOKEN";
|
|
2692
|
+
})(TokenType || (TokenType = {}));
|
|
2693
|
+
function getMainPackageUserAgent() {
|
|
2694
|
+
if (process.env.CP_MCP_MAIN_PKG) {
|
|
2695
|
+
if (process.env.CP_MCP_MAIN_PKG.includes("quantum-management-mcp")) {
|
|
2696
|
+
return "mgmt-mcp";
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
return "Check Point MCP API Client";
|
|
2700
|
+
}
|
|
2701
|
+
var ClientResponse = class {
|
|
2702
|
+
constructor(status, response) {
|
|
2703
|
+
this.status = status;
|
|
2704
|
+
this.response = response;
|
|
2705
|
+
}
|
|
2706
|
+
};
|
|
2707
|
+
var APIClientBase = class {
|
|
2708
|
+
constructor(authToken = "", tokenType = TokenType.API_KEY, cloudConnected = false) {
|
|
2709
|
+
this.authToken = authToken;
|
|
2710
|
+
this.tokenType = tokenType;
|
|
2711
|
+
this.cloudConnected = cloudConnected;
|
|
2712
|
+
this.sid = null;
|
|
2713
|
+
this.sessionTimeout = null;
|
|
2714
|
+
this.sessionStart = null;
|
|
2715
|
+
this.isMDS = false;
|
|
2716
|
+
this._externalSid = false;
|
|
2717
|
+
}
|
|
2718
|
+
/**
|
|
2719
|
+
* Create an API client instance - generic method for creating clients
|
|
2720
|
+
*/
|
|
2721
|
+
static create(...args) {
|
|
2722
|
+
return new this(...args);
|
|
2723
|
+
}
|
|
2724
|
+
/**
|
|
2725
|
+
* Get headers for the API requests
|
|
2726
|
+
*/
|
|
2727
|
+
getHeaders() {
|
|
2728
|
+
const headers = {
|
|
2729
|
+
"Content-Type": "application/json",
|
|
2730
|
+
"User-Agent": getMainPackageUserAgent()
|
|
2731
|
+
};
|
|
2732
|
+
if (this.sid) {
|
|
2733
|
+
headers["X-chkp-sid"] = this.sid;
|
|
2734
|
+
}
|
|
2735
|
+
if (this.cloudConnected && this.tokenType === TokenType.CI_TOKEN) {
|
|
2736
|
+
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
2737
|
+
headers["CLOUD-INFRA-TOKEN"] = this.authToken;
|
|
2738
|
+
}
|
|
2739
|
+
return headers;
|
|
2482
2740
|
}
|
|
2483
2741
|
/**
|
|
2484
|
-
*
|
|
2485
|
-
* @param cacheKey The cache key to clear
|
|
2486
|
-
* @param extra Extra context with session information
|
|
2742
|
+
* Get debug mode
|
|
2487
2743
|
*/
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
if (this.sessionData.has(sessionId)) {
|
|
2491
|
-
const sessionInfo = this.sessionData.get(sessionId);
|
|
2492
|
-
sessionInfo.data.delete(cacheKey);
|
|
2493
|
-
sessionInfo.lastAccessed = Date.now();
|
|
2494
|
-
}
|
|
2744
|
+
get debug() {
|
|
2745
|
+
return !!this._debug;
|
|
2495
2746
|
}
|
|
2496
2747
|
/**
|
|
2497
|
-
*
|
|
2498
|
-
* @param cacheKey The cache key to check
|
|
2499
|
-
* @param extra Extra context with session information
|
|
2500
|
-
* @returns true if valid cached data exists, false otherwise
|
|
2748
|
+
* Set debug mode
|
|
2501
2749
|
*/
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
if (!cachedData || !cachedData.expiresAt) {
|
|
2505
|
-
return false;
|
|
2506
|
-
}
|
|
2507
|
-
return Date.now() < cachedData.expiresAt;
|
|
2508
|
-
}
|
|
2509
|
-
};
|
|
2510
|
-
_a = SessionContext;
|
|
2511
|
-
SessionContext.DEFAULT_SESSION_ID = "default";
|
|
2512
|
-
SessionContext.sessionData = /* @__PURE__ */ new Map();
|
|
2513
|
-
SessionContext.SESSION_TIMEOUT_MS = 24 * 60 * 60 * 1e3;
|
|
2514
|
-
SessionContext.CLEANUP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
2515
|
-
SessionContext.MAX_SESSIONS = 1e3;
|
|
2516
|
-
SessionContext.cleanupTimer = null;
|
|
2517
|
-
(() => {
|
|
2518
|
-
_a.startCleanupTimer();
|
|
2519
|
-
})();
|
|
2520
|
-
|
|
2521
|
-
// ../mcp-utils/dist/session-manager.js
|
|
2522
|
-
var DEFAULT_SESSION_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
2523
|
-
var SessionManager = class {
|
|
2524
|
-
constructor() {
|
|
2525
|
-
this.sessions = /* @__PURE__ */ new Map();
|
|
2750
|
+
set debug(value) {
|
|
2751
|
+
this._debug = value;
|
|
2526
2752
|
}
|
|
2527
2753
|
/**
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
sessionId,
|
|
2537
|
-
createdAt: now,
|
|
2538
|
-
lastActive: now,
|
|
2539
|
-
...metadata
|
|
2540
|
-
};
|
|
2541
|
-
this.sessions.set(sessionId, sessionInfo);
|
|
2542
|
-
return sessionInfo;
|
|
2754
|
+
* Set a pre-authenticated session ID provided externally (e.g. via X-chkp-sid header).
|
|
2755
|
+
* When set, the client will skip login and use this SID directly for all requests.
|
|
2756
|
+
*/
|
|
2757
|
+
setExternalSid(sid) {
|
|
2758
|
+
this.sid = sid;
|
|
2759
|
+
this._externalSid = true;
|
|
2760
|
+
this.sessionStart = Date.now();
|
|
2761
|
+
this.sessionTimeout = Number.MAX_SAFE_INTEGER / 1e3;
|
|
2543
2762
|
}
|
|
2544
2763
|
/**
|
|
2545
|
-
*
|
|
2546
|
-
* @param sessionId The session ID
|
|
2547
|
-
* @returns Session info or undefined if not found
|
|
2764
|
+
* Check if this client needs to perform login before making API calls
|
|
2548
2765
|
*/
|
|
2549
|
-
|
|
2550
|
-
if (this.
|
|
2551
|
-
|
|
2766
|
+
needsLogin() {
|
|
2767
|
+
if (this._externalSid) {
|
|
2768
|
+
return false;
|
|
2552
2769
|
}
|
|
2553
|
-
return
|
|
2770
|
+
return true;
|
|
2554
2771
|
}
|
|
2555
2772
|
/**
|
|
2556
|
-
*
|
|
2557
|
-
* @param sessionId The session ID
|
|
2773
|
+
* Check if this client is in an MDS environment
|
|
2558
2774
|
*/
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
session.lastActive = /* @__PURE__ */ new Date();
|
|
2775
|
+
async isMDSEnvironment() {
|
|
2776
|
+
if (!this.hasValidSession()) {
|
|
2777
|
+
await this.login();
|
|
2563
2778
|
}
|
|
2779
|
+
return this.isMDS;
|
|
2564
2780
|
}
|
|
2565
2781
|
/**
|
|
2566
|
-
*
|
|
2567
|
-
* @param sessionId The session ID
|
|
2782
|
+
* Check if the client has a valid session
|
|
2568
2783
|
*/
|
|
2569
|
-
|
|
2570
|
-
this.
|
|
2571
|
-
SessionContext.clearSessionData(sessionId);
|
|
2784
|
+
hasValidSession() {
|
|
2785
|
+
return !!this.sid && !this.isSessionExpired();
|
|
2572
2786
|
}
|
|
2573
2787
|
/**
|
|
2574
|
-
* Get
|
|
2575
|
-
* @returns Array of session info objects
|
|
2788
|
+
* Get the current session ID (for debugging/logging purposes)
|
|
2576
2789
|
*/
|
|
2577
|
-
|
|
2578
|
-
return
|
|
2790
|
+
getSessionId() {
|
|
2791
|
+
return this.sid;
|
|
2579
2792
|
}
|
|
2580
2793
|
/**
|
|
2581
|
-
*
|
|
2582
|
-
*
|
|
2794
|
+
* Create a new API client instance with a specific session ID
|
|
2795
|
+
* Used for domain-specific clients in MDS environments
|
|
2583
2796
|
*/
|
|
2584
|
-
|
|
2585
|
-
|
|
2797
|
+
static createWithSid(originalClient, sid) {
|
|
2798
|
+
const newClient = Object.create(Object.getPrototypeOf(originalClient));
|
|
2799
|
+
Object.assign(newClient, originalClient);
|
|
2800
|
+
newClient.sid = sid;
|
|
2801
|
+
newClient.sessionStart = Date.now();
|
|
2802
|
+
return newClient;
|
|
2586
2803
|
}
|
|
2587
2804
|
/**
|
|
2588
|
-
*
|
|
2589
|
-
* @param timeoutMs Timeout in milliseconds (default: 30 minutes)
|
|
2590
|
-
* @returns Number of sessions removed
|
|
2805
|
+
* Call an API endpoint
|
|
2591
2806
|
*/
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
}
|
|
2604
|
-
};
|
|
2605
|
-
|
|
2606
|
-
// ../mcp-utils/dist/server-utils.js
|
|
2607
|
-
function getHeaderValue(headers, key) {
|
|
2608
|
-
const normalizedKey = key.replace(/_/g, "-");
|
|
2609
|
-
const value = headers[normalizedKey] || headers[normalizedKey.toUpperCase()] || headers[normalizedKey.toLowerCase()];
|
|
2610
|
-
return typeof value === "string" ? value : Array.isArray(value) ? value[0] : void 0;
|
|
2611
|
-
}
|
|
2612
|
-
function createApiRunner(serverModule2) {
|
|
2613
|
-
return async (method, uri, data, extra, domain) => {
|
|
2614
|
-
const apiManager = SessionContext.getAPIManager(serverModule2, extra);
|
|
2615
|
-
return await apiManager.callApi(method, uri, data, domain);
|
|
2616
|
-
};
|
|
2617
|
-
}
|
|
2618
|
-
function wrapServerWithTracking(server2, createServerFn) {
|
|
2619
|
-
const registrations = [];
|
|
2620
|
-
const originalTool = server2.tool?.bind(server2);
|
|
2621
|
-
const originalPrompt = server2.prompt?.bind(server2);
|
|
2622
|
-
const originalResource = server2.resource?.bind(server2);
|
|
2623
|
-
if (originalTool) {
|
|
2624
|
-
server2.tool = function(...args) {
|
|
2625
|
-
registrations.push({ type: "tool", method: "tool", args: [...args] });
|
|
2626
|
-
return originalTool(...args);
|
|
2627
|
-
};
|
|
2628
|
-
}
|
|
2629
|
-
if (originalPrompt) {
|
|
2630
|
-
server2.prompt = function(...args) {
|
|
2631
|
-
registrations.push({ type: "prompt", method: "prompt", args: [...args] });
|
|
2632
|
-
return originalPrompt(...args);
|
|
2633
|
-
};
|
|
2634
|
-
}
|
|
2635
|
-
if (originalResource) {
|
|
2636
|
-
server2.resource = function(...args) {
|
|
2637
|
-
registrations.push({ type: "resource", method: "resource", args: [...args] });
|
|
2638
|
-
return originalResource(...args);
|
|
2639
|
-
};
|
|
2640
|
-
}
|
|
2641
|
-
const createInstance = () => {
|
|
2642
|
-
const newServer = createServerFn();
|
|
2643
|
-
for (const reg of registrations) {
|
|
2644
|
-
if (newServer[reg.method]) {
|
|
2645
|
-
newServer[reg.method](...reg.args);
|
|
2807
|
+
async callApi(method, uri, data, params) {
|
|
2808
|
+
if (this.needsLogin() && (!this.sid || this.isSessionExpired())) {
|
|
2809
|
+
try {
|
|
2810
|
+
await this.login();
|
|
2811
|
+
} catch (error) {
|
|
2812
|
+
if (error instanceof ClientResponse) {
|
|
2813
|
+
console.error(`Login failed with status ${error.status}:`, error.response);
|
|
2814
|
+
return error;
|
|
2815
|
+
}
|
|
2816
|
+
console.error("Login failed with unexpected error:", error);
|
|
2817
|
+
return new ClientResponse(500, { error: "Authentication failed", message: error.message });
|
|
2646
2818
|
}
|
|
2647
2819
|
}
|
|
2648
|
-
|
|
2649
|
-
if (
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
2653
|
-
|
|
2820
|
+
let httpsAgent;
|
|
2821
|
+
if (this instanceof OnPremAPIClient) {
|
|
2822
|
+
httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
2823
|
+
}
|
|
2824
|
+
try {
|
|
2825
|
+
return await this.makeRequest(this.getHost(), method, uri, data, this.getHeaders(), params, httpsAgent);
|
|
2826
|
+
} catch (error) {
|
|
2827
|
+
if ((error.message?.includes("401") || error.response?.status === 401) && error.message?.toLowerCase().includes("session")) {
|
|
2828
|
+
if (this._externalSid) {
|
|
2829
|
+
throw new Error("Pre-authenticated session (X-chkp-sid) has expired. Provide a new session ID.");
|
|
2830
|
+
}
|
|
2831
|
+
console.error("Session expired (401), resetting session and retrying...");
|
|
2832
|
+
this.sid = null;
|
|
2833
|
+
this.sessionStart = null;
|
|
2834
|
+
try {
|
|
2835
|
+
await this.login();
|
|
2836
|
+
} catch (loginError) {
|
|
2837
|
+
if (loginError instanceof ClientResponse) {
|
|
2838
|
+
console.error(`Login retry failed with status ${loginError.status}:`, loginError.response);
|
|
2839
|
+
return loginError;
|
|
2840
|
+
}
|
|
2841
|
+
console.error("Login retry failed with unexpected error:", loginError);
|
|
2842
|
+
throw loginError;
|
|
2843
|
+
}
|
|
2844
|
+
return await this.makeRequest(this.getHost(), method, uri, data, this.getHeaders(), params, httpsAgent);
|
|
2845
|
+
}
|
|
2846
|
+
throw error;
|
|
2654
2847
|
}
|
|
2655
|
-
return newServer;
|
|
2656
|
-
};
|
|
2657
|
-
return { wrappedServer: server2, createInstance };
|
|
2658
|
-
}
|
|
2659
|
-
function createServerModule(server2, Settings2, pkg2, apiManagerClass, toolPolicyCallback, createServerFn) {
|
|
2660
|
-
const settingsManager = new SettingsManager(Settings2);
|
|
2661
|
-
const apiManagerFactory = new APIManagerFactory(apiManagerClass, settingsManager);
|
|
2662
|
-
const sessionManager = new SessionManager();
|
|
2663
|
-
if (toolPolicyCallback && typeof server2.setToolPolicy === "function") {
|
|
2664
|
-
console.error("[createServerModule] Setting tool policy callback on server");
|
|
2665
|
-
server2.setToolPolicy(toolPolicyCallback);
|
|
2666
|
-
}
|
|
2667
|
-
const serverFactory = createServerFn || server2._createServerFn;
|
|
2668
|
-
let createServerInstance;
|
|
2669
|
-
if (serverFactory) {
|
|
2670
|
-
const { wrappedServer, createInstance } = wrapServerWithTracking(server2, serverFactory);
|
|
2671
|
-
createServerInstance = createInstance;
|
|
2672
|
-
console.error("[createServerModule] Server factory enabled - HTTP multi-user support active");
|
|
2673
|
-
} else {
|
|
2674
|
-
console.error("[createServerModule] Warning: No server factory provided - HTTP multi-user may have issues");
|
|
2675
|
-
}
|
|
2676
|
-
return {
|
|
2677
|
-
server: server2,
|
|
2678
|
-
Settings: Settings2,
|
|
2679
|
-
settingsManager,
|
|
2680
|
-
apiManagerFactory,
|
|
2681
|
-
sessionManager,
|
|
2682
|
-
pkg: pkg2,
|
|
2683
|
-
toolPolicyCallback,
|
|
2684
|
-
createServerInstance
|
|
2685
|
-
};
|
|
2686
|
-
}
|
|
2687
|
-
|
|
2688
|
-
// ../mcp-utils/dist/index.js
|
|
2689
|
-
init_ui_dialog();
|
|
2690
|
-
|
|
2691
|
-
// ../mcp-utils/dist/mcp-server.js
|
|
2692
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2693
|
-
var CPMcpServer = class extends McpServer {
|
|
2694
|
-
constructor(serverInfo, options) {
|
|
2695
|
-
super(serverInfo, options);
|
|
2696
|
-
this.mcpName = serverInfo.name;
|
|
2697
|
-
this.mcpVersion = serverInfo.version || "0.0.0";
|
|
2698
2848
|
}
|
|
2699
2849
|
/**
|
|
2700
|
-
*
|
|
2701
|
-
* This should be called after all tools are registered but before connecting
|
|
2702
|
-
* @param callback Function that returns true if a tool should be enabled
|
|
2850
|
+
* Check if the session is expired based on sessionTimeout and sessionStart
|
|
2703
2851
|
*/
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2852
|
+
isSessionExpired() {
|
|
2853
|
+
if (!this.sid || !this.sessionTimeout || !this.sessionStart)
|
|
2854
|
+
return true;
|
|
2855
|
+
const now = Date.now();
|
|
2856
|
+
return now > this.sessionStart + (this.sessionTimeout - 5) * 1e3;
|
|
2857
|
+
}
|
|
2858
|
+
getHeadersForLogin() {
|
|
2859
|
+
return { "Content-Type": "application/json" };
|
|
2707
2860
|
}
|
|
2708
2861
|
/**
|
|
2709
|
-
*
|
|
2710
|
-
*
|
|
2711
|
-
* Needed so the policy can be carried onto the per-session server instances
|
|
2712
|
-
* created for HTTP transport. A typed accessor keeps that transfer honest:
|
|
2713
|
-
* callers do not have to reach into the private field, where a misspelling
|
|
2714
|
-
* would go unnoticed by the compiler.
|
|
2862
|
+
* Login to the API using the API key
|
|
2715
2863
|
*/
|
|
2716
|
-
|
|
2717
|
-
|
|
2864
|
+
async login() {
|
|
2865
|
+
if (this._externalSid) {
|
|
2866
|
+
if (!this.sid)
|
|
2867
|
+
throw new Error("External SID has expired");
|
|
2868
|
+
return this.sid;
|
|
2869
|
+
}
|
|
2870
|
+
const apiTokenHeader = this.tokenType === TokenType.API_KEY ? "api-key" : "ci-token";
|
|
2871
|
+
const loginResp = await this.makeRequest(this.getHost(), "POST", "login", { [apiTokenHeader]: this.authToken }, this.getHeadersForLogin());
|
|
2872
|
+
if (loginResp.status !== 200 || !loginResp.response || !loginResp.response.sid) {
|
|
2873
|
+
throw loginResp;
|
|
2874
|
+
}
|
|
2875
|
+
this.sid = loginResp.response.sid;
|
|
2876
|
+
this.sessionTimeout = loginResp.response["session-timeout"] || null;
|
|
2877
|
+
this.sessionStart = Date.now();
|
|
2878
|
+
if (loginResp.response.uid) {
|
|
2879
|
+
await this.detectMDS(loginResp.response.uid);
|
|
2880
|
+
}
|
|
2881
|
+
return loginResp.response.sid;
|
|
2718
2882
|
}
|
|
2719
2883
|
/**
|
|
2720
|
-
*
|
|
2721
|
-
* This should be called after all tools are registered but before connecting
|
|
2722
|
-
*
|
|
2723
|
-
* Per-tool tracing is behind the debug flag. This used to run once per process
|
|
2724
|
-
* on the template server, where a line per tool was a cheap startup banner.
|
|
2725
|
-
* It now also runs per session under HTTP transport, so unconditional tracing
|
|
2726
|
-
* would scale stderr with sessions x tools and bury the summary. The summary
|
|
2727
|
-
* line always prints — it is the fact worth having for every session.
|
|
2884
|
+
* Detect if this is an MDS environment by checking the session details
|
|
2728
2885
|
*/
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
if (
|
|
2733
|
-
|
|
2886
|
+
async detectMDS(sessionUid, handleSelfSigned = false) {
|
|
2887
|
+
try {
|
|
2888
|
+
let httpsAgent;
|
|
2889
|
+
if (handleSelfSigned) {
|
|
2890
|
+
httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
2734
2891
|
}
|
|
2735
|
-
|
|
2892
|
+
const sessionResp = await this.makeRequest(this.getHost(), "POST", "show-session", { uid: sessionUid }, this.getHeaders(), null, httpsAgent);
|
|
2893
|
+
if (sessionResp.status === 200 && sessionResp.response?.domain?.["domain-type"] === "mds") {
|
|
2894
|
+
this.isMDS = true;
|
|
2895
|
+
}
|
|
2896
|
+
} catch (error) {
|
|
2897
|
+
console.warn("Could not determine MDS status:", error);
|
|
2898
|
+
this.isMDS = false;
|
|
2736
2899
|
}
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2900
|
+
}
|
|
2901
|
+
/**
|
|
2902
|
+
* Make a request to a Check Point API
|
|
2903
|
+
*/
|
|
2904
|
+
async makeRequest(host, method, uri, data, headers = {}, params = null, httpsAgent) {
|
|
2905
|
+
uri = uri.replace(/^\//, "");
|
|
2906
|
+
const url = `${host}/${uri}`;
|
|
2907
|
+
const config = {
|
|
2908
|
+
method: method.toUpperCase(),
|
|
2909
|
+
url,
|
|
2910
|
+
headers,
|
|
2911
|
+
params: params || void 0
|
|
2912
|
+
};
|
|
2913
|
+
if (httpsAgent) {
|
|
2914
|
+
config.httpsAgent = httpsAgent;
|
|
2741
2915
|
}
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
console.error(`[CPMcpServer] Applying tool policy`);
|
|
2745
|
-
console.error(`[CPMcpServer] Found ${toolNames.length} registered tools:`, toolNames);
|
|
2916
|
+
if (method.toUpperCase() !== "GET" && data !== void 0) {
|
|
2917
|
+
config.data = data;
|
|
2746
2918
|
}
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
console.error(
|
|
2919
|
+
console.error(`API Request: ${method} ${url}`);
|
|
2920
|
+
try {
|
|
2921
|
+
const response = await axios(config);
|
|
2922
|
+
return new ClientResponse(response.status, response.data);
|
|
2923
|
+
} catch (error) {
|
|
2924
|
+
if (error.response) {
|
|
2925
|
+
console.error(`\u274C API Error (${error.response.status}):`);
|
|
2926
|
+
console.error("Headers:", error.response.headers);
|
|
2927
|
+
console.error("Data:", error.response.data);
|
|
2928
|
+
if (this.debug) {
|
|
2929
|
+
console.error("Debug mode: Printing request details:");
|
|
2930
|
+
console.error("Request Method:", method);
|
|
2931
|
+
console.error("Request URL:", url);
|
|
2932
|
+
console.error("Request Headers:", debugView(config.headers));
|
|
2933
|
+
console.error("Request Data:", debugView(config.data && typeof config.data === "object" ? config.data : { body: config.data }, DEBUG_LOGGABLE_REQUEST_KEYS));
|
|
2762
2934
|
}
|
|
2763
|
-
enabledCount++;
|
|
2764
2935
|
}
|
|
2936
|
+
if (error.response) {
|
|
2937
|
+
throw new Error(`API request failed: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
|
|
2938
|
+
}
|
|
2939
|
+
throw error;
|
|
2765
2940
|
}
|
|
2766
|
-
console.error(`[CPMcpServer] Policy applied: ${enabledCount}/${toolNames.length} tools enabled, ${disabledCount} disabled`);
|
|
2767
2941
|
}
|
|
2768
|
-
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
return callback({}, callbackArgs[0]);
|
|
2782
|
-
}
|
|
2783
|
-
return callback(...callbackArgs);
|
|
2784
|
-
};
|
|
2785
|
-
args[args.length - 1] = wrappedCallback;
|
|
2942
|
+
};
|
|
2943
|
+
var SmartOneCloudAPIClient = class extends APIClientBase {
|
|
2944
|
+
constructor(authToken, tokenType, s1cUrl, cloudConnected = false) {
|
|
2945
|
+
super(authToken, tokenType, cloudConnected);
|
|
2946
|
+
this.s1cUrl = s1cUrl;
|
|
2947
|
+
}
|
|
2948
|
+
getHost() {
|
|
2949
|
+
return this.s1cUrl;
|
|
2950
|
+
}
|
|
2951
|
+
getHeadersForLogin() {
|
|
2952
|
+
const headers = { "Content-Type": "application/json" };
|
|
2953
|
+
if (this.cloudConnected && this.tokenType === TokenType.CI_TOKEN) {
|
|
2954
|
+
headers["Authorization"] = `Bearer ${this.authToken}`;
|
|
2786
2955
|
}
|
|
2787
|
-
return
|
|
2956
|
+
return headers;
|
|
2957
|
+
}
|
|
2958
|
+
};
|
|
2959
|
+
var OnPremAPIClient = class extends APIClientBase {
|
|
2960
|
+
constructor(apiKey, managementHost, managementPort = "443", username, password, domain) {
|
|
2961
|
+
super(apiKey || "");
|
|
2962
|
+
this.managementHost = managementHost;
|
|
2963
|
+
this.managementPort = managementPort;
|
|
2964
|
+
this.domain = domain;
|
|
2965
|
+
this.username = username;
|
|
2966
|
+
this.password = password;
|
|
2967
|
+
}
|
|
2968
|
+
getHost() {
|
|
2969
|
+
const managementHost = this.managementHost;
|
|
2970
|
+
const port = this.managementPort;
|
|
2971
|
+
return `https://${managementHost}:${port}/web_api`;
|
|
2972
|
+
}
|
|
2973
|
+
/**
|
|
2974
|
+
* Override login() to support both api-key and username/password authentication
|
|
2975
|
+
* and allow self-signed certificates
|
|
2976
|
+
*/
|
|
2977
|
+
async login() {
|
|
2978
|
+
if (this._externalSid) {
|
|
2979
|
+
if (!this.sid)
|
|
2980
|
+
throw new Error("External SID has expired");
|
|
2981
|
+
return this.sid;
|
|
2982
|
+
}
|
|
2983
|
+
const isUsingApiKey = !!this.authToken;
|
|
2984
|
+
const isUsingCredentials = !!(this.username && this.password);
|
|
2985
|
+
if (!isUsingApiKey && !isUsingCredentials) {
|
|
2986
|
+
throw new ClientResponse(401, { message: "Authentication failed: No API key or username/password provided" });
|
|
2987
|
+
}
|
|
2988
|
+
const httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
2989
|
+
const loginPayload = isUsingApiKey ? { "api-key": this.authToken } : { "user": this.username, "password": this.password };
|
|
2990
|
+
if (this.domain) {
|
|
2991
|
+
loginPayload["domain"] = this.domain;
|
|
2992
|
+
}
|
|
2993
|
+
const loginResp = await this.makeRequest(this.getHost(), "POST", "login", loginPayload, { "Content-Type": "application/json" }, null, httpsAgent);
|
|
2994
|
+
if (loginResp.status !== 200 || !loginResp.response || !loginResp.response.sid) {
|
|
2995
|
+
throw loginResp;
|
|
2996
|
+
}
|
|
2997
|
+
this.sid = loginResp.response.sid;
|
|
2998
|
+
this.sessionTimeout = loginResp.response["session-timeout"] || null;
|
|
2999
|
+
this.sessionStart = Date.now();
|
|
3000
|
+
if (loginResp.response.uid) {
|
|
3001
|
+
await this.detectMDS(loginResp.response.uid, true);
|
|
3002
|
+
}
|
|
3003
|
+
return loginResp.response.sid;
|
|
2788
3004
|
}
|
|
2789
3005
|
};
|
|
2790
3006
|
|
|
2791
|
-
// ../
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
import { fileURLToPath } from "url";
|
|
2795
|
-
function readPackageJson(importMetaUrl) {
|
|
2796
|
-
const pkg2 = JSON.parse(readFileSync(join2(dirname(fileURLToPath(importMetaUrl)), "../package.json"), "utf-8"));
|
|
2797
|
-
process.env.CP_MCP_MAIN_PKG = `${pkg2.name} v${pkg2.version}`;
|
|
2798
|
-
return pkg2;
|
|
3007
|
+
// ../infra/dist/string-utils.js
|
|
3008
|
+
function nullOrEmpty(val) {
|
|
3009
|
+
return val === void 0 || val === null || typeof val === "string" && (val.trim() === "" || val === "undefined" || val === "null");
|
|
2799
3010
|
}
|
|
2800
|
-
function
|
|
2801
|
-
const
|
|
2802
|
-
const
|
|
2803
|
-
|
|
2804
|
-
|
|
2805
|
-
|
|
2806
|
-
|
|
2807
|
-
|
|
2808
|
-
|
|
2809
|
-
|
|
2810
|
-
const server2 = new CPMcpServer(fullServerInfo, options);
|
|
2811
|
-
server2._createServerFn = createServerFn;
|
|
2812
|
-
return { server: server2, pkg: pkg2 };
|
|
3011
|
+
function sanitizeData(kwargs) {
|
|
3012
|
+
const data = {};
|
|
3013
|
+
for (const [key, value] of Object.entries(kwargs)) {
|
|
3014
|
+
if (value === null || value === void 0 || value === "" || Array.isArray(value) && value.length === 0) {
|
|
3015
|
+
continue;
|
|
3016
|
+
}
|
|
3017
|
+
const safeKey = key.replace(/_/g, "-");
|
|
3018
|
+
data[safeKey] = value;
|
|
3019
|
+
}
|
|
3020
|
+
return data;
|
|
2813
3021
|
}
|
|
2814
3022
|
|
|
2815
3023
|
// ../infra/dist/api-manager.js
|
|
@@ -3321,7 +3529,9 @@ var Settings = class _Settings {
|
|
|
3321
3529
|
return "STG";
|
|
3322
3530
|
return void 0;
|
|
3323
3531
|
}
|
|
3324
|
-
|
|
3532
|
+
// Takes only what it is given: the environment is read by fromArgs, so
|
|
3533
|
+
// settings built from request headers never pick up the process's values.
|
|
3534
|
+
constructor({ apiKey, username, password, s1cUrl, managementHost, managementPort = "443", cloudInfraToken, cloudConnected = false, sid, clientId, secretKey, region = "EU", devPort = "8006", gatewayUrl } = {}) {
|
|
3325
3535
|
this.region = "EU";
|
|
3326
3536
|
this.devPort = "8006";
|
|
3327
3537
|
this.gatewayUrl = "";
|
|
@@ -3501,19 +3711,20 @@ var Settings = class _Settings {
|
|
|
3501
3711
|
console.error("[Settings.fromArgs] Verbose: WARNING - Args object appears empty, no authentication values found");
|
|
3502
3712
|
}
|
|
3503
3713
|
}
|
|
3714
|
+
const env = process.env;
|
|
3504
3715
|
return new _Settings({
|
|
3505
|
-
apiKey: args.apiKey,
|
|
3506
|
-
username: args.username,
|
|
3507
|
-
password: args.password,
|
|
3508
|
-
s1cUrl: args.s1cUrl,
|
|
3509
|
-
managementHost: args.managementHost,
|
|
3510
|
-
managementPort: args.managementPort,
|
|
3511
|
-
cloudInfraToken: args.cloudInfraToken,
|
|
3512
|
-
cloudConnected: args.cloudConnected,
|
|
3513
|
-
clientId: args.clientId,
|
|
3514
|
-
secretKey: args.secretKey,
|
|
3515
|
-
region: typeof args.region === "string" ? args.region.trim().toUpperCase() : void 0,
|
|
3516
|
-
devPort: args.devPort,
|
|
3716
|
+
apiKey: args.apiKey ?? env.API_KEY,
|
|
3717
|
+
username: args.username ?? env.USERNAME,
|
|
3718
|
+
password: args.password ?? env.PASSWORD,
|
|
3719
|
+
s1cUrl: args.s1cUrl ?? env.S1C_URL,
|
|
3720
|
+
managementHost: args.managementHost ?? env.MANAGEMENT_HOST,
|
|
3721
|
+
managementPort: args.managementPort ?? (env.MANAGEMENT_PORT || void 0),
|
|
3722
|
+
cloudInfraToken: args.cloudInfraToken ?? env.CLOUD_INFRA_TOKEN,
|
|
3723
|
+
cloudConnected: args.cloudConnected ?? env.CLOUD_CONNECTED === "true",
|
|
3724
|
+
clientId: args.clientId ?? env.CLIENT_ID,
|
|
3725
|
+
secretKey: args.secretKey ?? env.SECRET_KEY,
|
|
3726
|
+
region: typeof args.region === "string" ? args.region.trim().toUpperCase() : env.REGION || void 0,
|
|
3727
|
+
devPort: args.devPort ?? (env.DEV_PORT || void 0),
|
|
3517
3728
|
gatewayUrl: args.gatewayUrl
|
|
3518
3729
|
});
|
|
3519
3730
|
}
|
|
@@ -3558,7 +3769,6 @@ var Settings = class _Settings {
|
|
|
3558
3769
|
const hasAnyValue = extractedValues.apiKey || extractedValues.username || extractedValues.password || extractedValues.s1cUrl || extractedValues.managementHost || extractedValues.cloudInfraToken;
|
|
3559
3770
|
if (!hasAnyValue) {
|
|
3560
3771
|
console.error("[Settings.fromHeaders] Verbose: WARNING - No authentication values found in headers");
|
|
3561
|
-
console.error("[Settings.fromHeaders] Verbose: Full headers object (sanitized):", Object.fromEntries(Object.entries(headers).map(([k, v]) => [k, k.toLowerCase().includes("key") || k.toLowerCase().includes("token") || k.toLowerCase().includes("password") ? "***" : v])));
|
|
3562
3772
|
}
|
|
3563
3773
|
}
|
|
3564
3774
|
return new _Settings({
|
|
@@ -3579,6 +3789,17 @@ var Settings = class _Settings {
|
|
|
3579
3789
|
});
|
|
3580
3790
|
}
|
|
3581
3791
|
};
|
|
3792
|
+
Settings.debugLoggableKeys = [
|
|
3793
|
+
"management-host",
|
|
3794
|
+
"management-port",
|
|
3795
|
+
"s1c-url",
|
|
3796
|
+
"gateway-url",
|
|
3797
|
+
"region",
|
|
3798
|
+
"dev-port",
|
|
3799
|
+
"cloud-connected",
|
|
3800
|
+
"write-mode"
|
|
3801
|
+
];
|
|
3802
|
+
Settings.basicKeys = ["REGION"];
|
|
3582
3803
|
|
|
3583
3804
|
// ../infra/dist/external-user-token-manager.js
|
|
3584
3805
|
import axios2 from "axios";
|