@chkp/policy-insights-mcp 0.4.1 → 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 +1074 -795
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/package.json.bak +1 -1
package/dist/index.js
CHANGED
|
@@ -1270,583 +1270,464 @@ 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
1718
|
}
|
|
1606
|
-
return data;
|
|
1607
1719
|
}
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
import fs from "fs";
|
|
1614
|
-
import http from "http";
|
|
1615
|
-
import { randomUUID } from "crypto";
|
|
1616
|
-
|
|
1617
|
-
// ../mcp-utils/dist/settings-manager.js
|
|
1618
|
-
var SettingsManager = class _SettingsManager {
|
|
1619
|
-
/**
|
|
1620
|
-
* Creates a new SettingsManager
|
|
1621
|
-
* @param settingsClass The Settings class to use for creating settings instances
|
|
1622
|
-
*/
|
|
1623
|
-
constructor(settingsClass) {
|
|
1624
|
-
this.settingsMap = /* @__PURE__ */ new Map();
|
|
1625
|
-
this.defaultSessionId = "default";
|
|
1626
|
-
this.settingsClass = settingsClass;
|
|
1627
|
-
}
|
|
1628
|
-
/**
|
|
1629
|
-
* Get settings for a specific session
|
|
1630
|
-
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1631
|
-
* @returns Settings instance for the session
|
|
1632
|
-
*/
|
|
1633
|
-
getSettings(sessionId) {
|
|
1634
|
-
const sid = sessionId || this.defaultSessionId;
|
|
1635
|
-
if (!this.settingsMap.has(sid)) {
|
|
1636
|
-
this.settingsMap.set(sid, new this.settingsClass());
|
|
1637
|
-
}
|
|
1638
|
-
return this.settingsMap.get(sid);
|
|
1639
|
-
}
|
|
1640
|
-
/**
|
|
1641
|
-
* Set settings for a specific session
|
|
1642
|
-
* @param settings The settings object to set
|
|
1643
|
-
* @param sessionId The session ID (defaults to 'default' for stdio mode)
|
|
1644
|
-
*/
|
|
1645
|
-
setSettings(settings, sessionId) {
|
|
1646
|
-
const sid = sessionId || this.defaultSessionId;
|
|
1647
|
-
this.settingsMap.set(sid, settings);
|
|
1648
|
-
}
|
|
1649
|
-
/**
|
|
1650
|
-
* Injects debug settings from source into settings object
|
|
1651
|
-
* @param settings The settings object to update
|
|
1652
|
-
* @param source Source object containing debug information
|
|
1653
|
-
* @private
|
|
1654
|
-
*/
|
|
1655
|
-
injectDebug(settings, source) {
|
|
1656
|
-
const debug = source?.debug ?? _SettingsManager.globalDebugState ?? process.env.DEBUG;
|
|
1657
|
-
if (typeof debug !== "undefined") {
|
|
1658
|
-
if (source?.debug !== void 0) {
|
|
1659
|
-
_SettingsManager.globalDebugState = source.debug;
|
|
1660
|
-
}
|
|
1661
|
-
if (typeof settings.set === "function") {
|
|
1662
|
-
settings.set("debug", debug);
|
|
1663
|
-
} else {
|
|
1664
|
-
settings.debug = debug;
|
|
1665
|
-
}
|
|
1666
|
-
if (debug) {
|
|
1667
|
-
console.error("Debug enabled. Source object contents:");
|
|
1668
|
-
console.error(JSON.stringify(source, null, 2));
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
}
|
|
1672
|
-
/**
|
|
1673
|
-
* Print settings object for debugging by dynamically discovering its properties
|
|
1674
|
-
* @param settings The settings object to print
|
|
1675
|
-
* @private
|
|
1676
|
-
*/
|
|
1677
|
-
printSettingsDebug(settings) {
|
|
1678
|
-
if (typeof settings.get === "function") {
|
|
1679
|
-
console.error("Settings (using get method):");
|
|
1680
|
-
if (settings.data && typeof settings.data === "object") {
|
|
1681
|
-
Object.entries(settings.data).forEach(([key, value]) => {
|
|
1682
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
1683
|
-
});
|
|
1684
|
-
} else {
|
|
1685
|
-
console.error(" Unable to enumerate settings properties - no accessible data structure");
|
|
1686
|
-
}
|
|
1687
|
-
} else {
|
|
1688
|
-
console.error("Settings (plain object):");
|
|
1689
|
-
Object.entries(settings).forEach(([key, value]) => {
|
|
1690
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
1691
|
-
});
|
|
1692
|
-
}
|
|
1693
|
-
}
|
|
1694
|
-
/**
|
|
1695
|
-
* Create settings from command-line arguments
|
|
1696
|
-
* @param args Command line arguments
|
|
1697
|
-
* @param sessionId Optional session ID
|
|
1698
|
-
* @returns Settings instance
|
|
1699
|
-
*/
|
|
1700
|
-
createFromArgs(args, sessionId) {
|
|
1701
|
-
const settings = this.settingsClass.fromArgs(args);
|
|
1702
|
-
this.injectDebug(settings, args);
|
|
1703
|
-
this.setSettings(settings, sessionId);
|
|
1704
|
-
return settings;
|
|
1705
|
-
}
|
|
1706
|
-
/**
|
|
1707
|
-
* Create settings from HTTP headers
|
|
1708
|
-
* @param headers HTTP headers
|
|
1709
|
-
* @param sessionId Optional session ID
|
|
1710
|
-
* @returns Settings instance
|
|
1711
|
-
*/
|
|
1712
|
-
createFromHeaders(headers, sessionId) {
|
|
1713
|
-
const verbose = _SettingsManager.globalDebugState;
|
|
1714
|
-
if (verbose) {
|
|
1715
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Starting with sessionId:", sessionId || "(default)");
|
|
1716
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Incoming headers count:", Object.keys(headers).length);
|
|
1717
|
-
}
|
|
1718
|
-
if (_SettingsManager.globalDebugState) {
|
|
1719
|
-
console.error("=== createFromHeaders Debug Info ===");
|
|
1720
|
-
console.error("Incoming headers:");
|
|
1721
|
-
console.error(JSON.stringify(headers, null, 2));
|
|
1722
|
-
}
|
|
1723
|
-
if (verbose && (!headers || Object.keys(headers).length === 0)) {
|
|
1724
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: WARNING - Headers object is empty or undefined");
|
|
1725
|
-
}
|
|
1726
|
-
const normalizedHeaders = {};
|
|
1727
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
1728
|
-
const normalizedKey = key.includes("_") ? key.replace(/_/g, "-") : key;
|
|
1729
|
-
normalizedHeaders[normalizedKey] = value;
|
|
1730
|
-
if (verbose) {
|
|
1731
|
-
console.error(`[SettingsManager.createFromHeaders] Verbose: Header normalized: "${key}" -> "${normalizedKey}"`);
|
|
1732
|
-
}
|
|
1733
|
-
}
|
|
1734
|
-
if (verbose) {
|
|
1735
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Normalized headers count:", Object.keys(normalizedHeaders).length);
|
|
1736
|
-
}
|
|
1737
|
-
if (_SettingsManager.globalDebugState) {
|
|
1738
|
-
console.error("Normalized headers:");
|
|
1739
|
-
console.error(JSON.stringify(normalizedHeaders, null, 2));
|
|
1740
|
-
}
|
|
1741
|
-
const debugHeader = normalizedHeaders["debug"] || normalizedHeaders["Debug"] || normalizedHeaders["DEBUG"];
|
|
1742
|
-
const debugSource = { debug: debugHeader !== void 0 ? debugHeader : _SettingsManager.globalDebugState };
|
|
1743
|
-
if (verbose) {
|
|
1744
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Calling settingsClass.fromHeaders");
|
|
1745
|
-
}
|
|
1746
|
-
const settings = this.settingsClass.fromHeaders(normalizedHeaders);
|
|
1747
|
-
if (verbose) {
|
|
1748
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Settings object created");
|
|
1749
|
-
}
|
|
1750
|
-
this.injectDebug(settings, debugSource);
|
|
1751
|
-
if (_SettingsManager.globalDebugState) {
|
|
1752
|
-
console.error("Final settings object for session:", sessionId || "(default)");
|
|
1753
|
-
this.printSettingsDebug(settings);
|
|
1754
|
-
console.error("=== End createFromHeaders Debug Info ===");
|
|
1755
|
-
}
|
|
1756
|
-
if (verbose) {
|
|
1757
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Storing settings for session:", sessionId || "(default)");
|
|
1758
|
-
}
|
|
1759
|
-
this.setSettings(settings, sessionId);
|
|
1760
|
-
return settings;
|
|
1761
|
-
}
|
|
1762
|
-
/**
|
|
1763
|
-
* Clear settings for a session
|
|
1764
|
-
* @param sessionId The session ID to clear
|
|
1765
|
-
*/
|
|
1766
|
-
clearSession(sessionId) {
|
|
1767
|
-
if (sessionId !== this.defaultSessionId) {
|
|
1768
|
-
this.settingsMap.delete(sessionId);
|
|
1769
|
-
}
|
|
1770
|
-
}
|
|
1771
|
-
};
|
|
1772
|
-
SettingsManager.globalDebugState = void 0;
|
|
1773
|
-
|
|
1774
|
-
// ../mcp-utils/dist/telemetry.js
|
|
1775
|
-
import machineIdPkg from "node-machine-id";
|
|
1776
|
-
import { createHash } from "crypto";
|
|
1777
|
-
var { machineIdSync } = machineIdPkg;
|
|
1778
|
-
var machineId = null;
|
|
1779
|
-
var hashedMachineId = null;
|
|
1780
|
-
var transportType = "stdio";
|
|
1781
|
-
function setTransportType(type) {
|
|
1782
|
-
transportType = type;
|
|
1783
|
-
}
|
|
1784
|
-
function isTelemetryDisabled() {
|
|
1785
|
-
return process.env.TELEMETRY_DISABLED === "true" || process.env.TELEMETRY_DISABLED === "1";
|
|
1786
|
-
}
|
|
1787
|
-
function getTelemetryUrl() {
|
|
1788
|
-
return process.env.TELEMETRY_URL || "https://metrics.security.ai.checkpoint.com/api/v1/metrics/collect";
|
|
1789
|
-
}
|
|
1790
|
-
function hashString(input) {
|
|
1791
|
-
return createHash("sha256").update(input).digest("hex");
|
|
1792
|
-
}
|
|
1793
|
-
function getMachineId() {
|
|
1794
|
-
if (!machineId) {
|
|
1795
|
-
try {
|
|
1796
|
-
machineId = machineIdSync();
|
|
1797
|
-
} catch (error) {
|
|
1798
|
-
console.warn("Failed to get machine ID for telemetry:", error);
|
|
1799
|
-
machineId = "unknown";
|
|
1800
|
-
}
|
|
1801
|
-
}
|
|
1802
|
-
return machineId;
|
|
1803
|
-
}
|
|
1804
|
-
function getHashedMachineId() {
|
|
1805
|
-
if (!hashedMachineId) {
|
|
1806
|
-
hashedMachineId = hashString(getMachineId());
|
|
1807
|
-
}
|
|
1808
|
-
return hashedMachineId;
|
|
1809
|
-
}
|
|
1810
|
-
function calculateChecksum(mcpName, toolName, machineId2, clientVersion) {
|
|
1811
|
-
const data = mcpName + machineId2.slice(0, 16) + toolName + clientVersion;
|
|
1812
|
-
return hashString(data);
|
|
1813
|
-
}
|
|
1814
|
-
async function trackToolCall(mcpName, toolName, clientVersion, extra) {
|
|
1815
|
-
if (isTelemetryDisabled()) {
|
|
1816
|
-
return;
|
|
1817
|
-
}
|
|
1818
|
-
try {
|
|
1819
|
-
const machineId2 = getHashedMachineId();
|
|
1820
|
-
const checksum = calculateChecksum(mcpName, toolName, machineId2, clientVersion);
|
|
1821
|
-
fetch(getTelemetryUrl(), {
|
|
1822
|
-
method: "POST",
|
|
1823
|
-
headers: { "Content-Type": "application/json" },
|
|
1824
|
-
body: JSON.stringify({
|
|
1825
|
-
mcp_name: mcpName,
|
|
1826
|
-
tool_name: toolName,
|
|
1827
|
-
machine_id: machineId2,
|
|
1828
|
-
client_version: clientVersion,
|
|
1829
|
-
transport_type: transportType,
|
|
1830
|
-
checksum
|
|
1831
|
-
})
|
|
1832
|
-
}).catch(() => {
|
|
1833
|
-
});
|
|
1834
|
-
} catch (error) {
|
|
1835
|
-
}
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
// ../mcp-utils/dist/launcher.js
|
|
1839
|
-
async function launchMCPServer(configPath, serverModule2) {
|
|
1840
|
-
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
1841
|
-
const program = new Command();
|
|
1842
|
-
if (config.description) {
|
|
1843
|
-
program.description(config.description);
|
|
1720
|
+
async function launchMCPServer(configPath, serverModule2) {
|
|
1721
|
+
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
1722
|
+
const program = new Command();
|
|
1723
|
+
if (config.description) {
|
|
1724
|
+
program.description(config.description);
|
|
1844
1725
|
}
|
|
1845
1726
|
config.options.forEach((option) => {
|
|
1846
1727
|
const envValue = option.env ? process.env[option.env] : void 0;
|
|
1847
1728
|
const defaultValue = envValue || option.default;
|
|
1848
1729
|
if (option.type === "boolean") {
|
|
1849
|
-
const boolDefault = envValue
|
|
1730
|
+
const boolDefault = booleanOptionDefault(envValue, option.default);
|
|
1850
1731
|
program.option(option.flag, option.description, boolDefault);
|
|
1851
1732
|
} else {
|
|
1852
1733
|
program.option(option.flag, option.description, defaultValue);
|
|
@@ -1870,17 +1751,24 @@ async function launchMCPServer(configPath, serverModule2) {
|
|
|
1870
1751
|
if (options.telemetryUrl) {
|
|
1871
1752
|
process.env.TELEMETRY_URL = options.telemetryUrl;
|
|
1872
1753
|
}
|
|
1754
|
+
mirrorBooleanFlagsToEnv(config, options);
|
|
1755
|
+
const transportType2 = resolveTransportType(options.transport);
|
|
1756
|
+
process.env.MCP_TRANSPORT_TYPE = transportType2;
|
|
1873
1757
|
if (!serverModule2.settingsManager) {
|
|
1874
1758
|
throw new Error("ServerModule must have a settingsManager. Create it with createServerModule.");
|
|
1875
1759
|
}
|
|
1876
1760
|
const settings = serverModule2.settingsManager.createFromArgs(options);
|
|
1761
|
+
serverModule2.settingsManager.setOperatorValues?.(operatorValues(config.options, options));
|
|
1877
1762
|
if (typeof serverModule2.server.applyToolPolicy === "function") {
|
|
1878
1763
|
console.error("[launchMCPServer] Applying tool policy before connecting");
|
|
1879
1764
|
serverModule2.server.applyToolPolicy();
|
|
1880
1765
|
}
|
|
1881
|
-
const transportType2 = (options.transport || process.env.MCP_TRANSPORT_TYPE || "stdio").toLowerCase() === "http" ? "http" : "stdio";
|
|
1882
1766
|
const transportPort = options.transportPort ? parseInt(options.transportPort, 10) : process.env.MCP_TRANSPORT_PORT ? parseInt(process.env.MCP_TRANSPORT_PORT, 10) : 3e3;
|
|
1883
1767
|
if (transportType2 === "http") {
|
|
1768
|
+
const refusal = serverModule2.httpStartupCheck?.();
|
|
1769
|
+
if (refusal) {
|
|
1770
|
+
throw new Error(refusal);
|
|
1771
|
+
}
|
|
1884
1772
|
setTransportType("http");
|
|
1885
1773
|
await launchHTTPServer(config, serverModule2, transportPort);
|
|
1886
1774
|
} else {
|
|
@@ -1929,7 +1817,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
1929
1817
|
if (sessionId && transports[sessionId]) {
|
|
1930
1818
|
const verbose = SettingsManager.globalDebugState;
|
|
1931
1819
|
if (verbose) {
|
|
1932
|
-
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionId);
|
|
1820
|
+
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionLogLabel(sessionId));
|
|
1933
1821
|
}
|
|
1934
1822
|
transport = transports[sessionId];
|
|
1935
1823
|
if (!serverModule2.settingsManager) {
|
|
@@ -1949,7 +1837,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
1949
1837
|
onsessioninitialized: (sid) => {
|
|
1950
1838
|
const verbose = SettingsManager.globalDebugState;
|
|
1951
1839
|
if (verbose) {
|
|
1952
|
-
console.error("[launchHTTPServer] Verbose: New session initialized:", sid);
|
|
1840
|
+
console.error("[launchHTTPServer] Verbose: New session initialized:", sessionLogLabel(sid));
|
|
1953
1841
|
}
|
|
1954
1842
|
transports[sid] = transport;
|
|
1955
1843
|
if (verbose) {
|
|
@@ -2152,7 +2040,6 @@ function headersToEnvVars(headers, config) {
|
|
|
2152
2040
|
}
|
|
2153
2041
|
if (verbose) {
|
|
2154
2042
|
console.error("[headersToEnvVars] Verbose: Final result keys:", Object.keys(result));
|
|
2155
|
-
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])));
|
|
2156
2043
|
}
|
|
2157
2044
|
return result;
|
|
2158
2045
|
}
|
|
@@ -2179,7 +2066,7 @@ var APIManagerFactory = class {
|
|
|
2179
2066
|
const verbose = SettingsManager.globalDebugState;
|
|
2180
2067
|
const sid = sessionId || this.defaultSessionId;
|
|
2181
2068
|
if (verbose) {
|
|
2182
|
-
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sid);
|
|
2069
|
+
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sessionLogLabel(sid));
|
|
2183
2070
|
}
|
|
2184
2071
|
if (!this.apiManagerMap.has(sid)) {
|
|
2185
2072
|
if (verbose) {
|
|
@@ -2277,16 +2164,15 @@ var SessionContext = class {
|
|
|
2277
2164
|
/**
|
|
2278
2165
|
* Get the current session ID from the MCP extra context
|
|
2279
2166
|
* @param extra Extra context passed to MCP tool callbacks
|
|
2280
|
-
* @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
|
|
2281
2169
|
*/
|
|
2282
2170
|
static getSessionId(extra) {
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
if (extra.sessionId) {
|
|
2289
|
-
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");
|
|
2290
2176
|
}
|
|
2291
2177
|
return this.DEFAULT_SESSION_ID;
|
|
2292
2178
|
}
|
|
@@ -2403,10 +2289,10 @@ var SessionContext = class {
|
|
|
2403
2289
|
}
|
|
2404
2290
|
}
|
|
2405
2291
|
}
|
|
2406
|
-
console.error(`Using cached user data for
|
|
2292
|
+
console.error(`Using cached user data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
2407
2293
|
return { cancelled: false, data: dataToReturn2 };
|
|
2408
2294
|
}
|
|
2409
|
-
console.error(`Prompting user for data for
|
|
2295
|
+
console.error(`Prompting user for data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
2410
2296
|
let result;
|
|
2411
2297
|
if (options.showLoginDialog) {
|
|
2412
2298
|
const { showLoginDialog: showLoginDialog2 } = await Promise.resolve().then(() => (init_ui_dialog(), ui_dialog_exports));
|
|
@@ -2450,308 +2336,688 @@ var SessionContext = class {
|
|
|
2450
2336
|
return { cancelled: false, data: dataToReturn };
|
|
2451
2337
|
}
|
|
2452
2338
|
/**
|
|
2453
|
-
* Clear cached user data for a specific key
|
|
2454
|
-
* @param cacheKey The cache key to clear
|
|
2455
|
-
* @param extra Extra context with session information
|
|
2456
|
-
*/
|
|
2457
|
-
static clearUserData(cacheKey, extra) {
|
|
2458
|
-
const sessionId = this.getSessionId(extra);
|
|
2459
|
-
if (this.sessionData.has(sessionId)) {
|
|
2460
|
-
const sessionInfo = this.sessionData.get(sessionId);
|
|
2461
|
-
sessionInfo.data.delete(cacheKey);
|
|
2462
|
-
sessionInfo.lastAccessed = Date.now();
|
|
2463
|
-
}
|
|
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);
|
|
2464
2723
|
}
|
|
2465
2724
|
/**
|
|
2466
|
-
*
|
|
2467
|
-
* @param cacheKey The cache key to check
|
|
2468
|
-
* @param extra Extra context with session information
|
|
2469
|
-
* @returns true if valid cached data exists, false otherwise
|
|
2725
|
+
* Get headers for the API requests
|
|
2470
2726
|
*/
|
|
2471
|
-
|
|
2472
|
-
const
|
|
2473
|
-
|
|
2474
|
-
|
|
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;
|
|
2475
2734
|
}
|
|
2476
|
-
|
|
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;
|
|
2477
2740
|
}
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
SessionContext.CLEANUP_INTERVAL_MS = 60 * 60 * 1e3;
|
|
2484
|
-
SessionContext.MAX_SESSIONS = 1e3;
|
|
2485
|
-
SessionContext.cleanupTimer = null;
|
|
2486
|
-
(() => {
|
|
2487
|
-
_a.startCleanupTimer();
|
|
2488
|
-
})();
|
|
2489
|
-
|
|
2490
|
-
// ../mcp-utils/dist/session-manager.js
|
|
2491
|
-
var DEFAULT_SESSION_TIMEOUT_MS = 15 * 60 * 1e3;
|
|
2492
|
-
var SessionManager = class {
|
|
2493
|
-
constructor() {
|
|
2494
|
-
this.sessions = /* @__PURE__ */ new Map();
|
|
2741
|
+
/**
|
|
2742
|
+
* Get debug mode
|
|
2743
|
+
*/
|
|
2744
|
+
get debug() {
|
|
2745
|
+
return !!this._debug;
|
|
2495
2746
|
}
|
|
2496
2747
|
/**
|
|
2497
|
-
*
|
|
2498
|
-
* @param sessionId The session ID
|
|
2499
|
-
* @param metadata Optional metadata to store with the session
|
|
2500
|
-
* @returns Session info
|
|
2748
|
+
* Set debug mode
|
|
2501
2749
|
*/
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
const sessionInfo = {
|
|
2505
|
-
sessionId,
|
|
2506
|
-
createdAt: now,
|
|
2507
|
-
lastActive: now,
|
|
2508
|
-
...metadata
|
|
2509
|
-
};
|
|
2510
|
-
this.sessions.set(sessionId, sessionInfo);
|
|
2511
|
-
return sessionInfo;
|
|
2750
|
+
set debug(value) {
|
|
2751
|
+
this._debug = value;
|
|
2512
2752
|
}
|
|
2513
2753
|
/**
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
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;
|
|
2762
|
+
}
|
|
2763
|
+
/**
|
|
2764
|
+
* Check if this client needs to perform login before making API calls
|
|
2517
2765
|
*/
|
|
2518
|
-
|
|
2519
|
-
if (this.
|
|
2520
|
-
|
|
2766
|
+
needsLogin() {
|
|
2767
|
+
if (this._externalSid) {
|
|
2768
|
+
return false;
|
|
2521
2769
|
}
|
|
2522
|
-
return
|
|
2770
|
+
return true;
|
|
2523
2771
|
}
|
|
2524
2772
|
/**
|
|
2525
|
-
*
|
|
2526
|
-
* @param sessionId The session ID
|
|
2773
|
+
* Check if this client is in an MDS environment
|
|
2527
2774
|
*/
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
session.lastActive = /* @__PURE__ */ new Date();
|
|
2775
|
+
async isMDSEnvironment() {
|
|
2776
|
+
if (!this.hasValidSession()) {
|
|
2777
|
+
await this.login();
|
|
2532
2778
|
}
|
|
2779
|
+
return this.isMDS;
|
|
2533
2780
|
}
|
|
2534
2781
|
/**
|
|
2535
|
-
*
|
|
2536
|
-
* @param sessionId The session ID
|
|
2782
|
+
* Check if the client has a valid session
|
|
2537
2783
|
*/
|
|
2538
|
-
|
|
2539
|
-
this.
|
|
2540
|
-
SessionContext.clearSessionData(sessionId);
|
|
2784
|
+
hasValidSession() {
|
|
2785
|
+
return !!this.sid && !this.isSessionExpired();
|
|
2541
2786
|
}
|
|
2542
2787
|
/**
|
|
2543
|
-
* Get
|
|
2544
|
-
* @returns Array of session info objects
|
|
2788
|
+
* Get the current session ID (for debugging/logging purposes)
|
|
2545
2789
|
*/
|
|
2546
|
-
|
|
2547
|
-
return
|
|
2790
|
+
getSessionId() {
|
|
2791
|
+
return this.sid;
|
|
2548
2792
|
}
|
|
2549
2793
|
/**
|
|
2550
|
-
*
|
|
2551
|
-
*
|
|
2794
|
+
* Create a new API client instance with a specific session ID
|
|
2795
|
+
* Used for domain-specific clients in MDS environments
|
|
2552
2796
|
*/
|
|
2553
|
-
|
|
2554
|
-
|
|
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;
|
|
2555
2803
|
}
|
|
2556
2804
|
/**
|
|
2557
|
-
*
|
|
2558
|
-
* @param timeoutMs Timeout in milliseconds (default: 30 minutes)
|
|
2559
|
-
* @returns Number of sessions removed
|
|
2805
|
+
* Call an API endpoint
|
|
2560
2806
|
*/
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
}
|
|
2573
|
-
};
|
|
2574
|
-
|
|
2575
|
-
// ../mcp-utils/dist/server-utils.js
|
|
2576
|
-
function getHeaderValue(headers, key) {
|
|
2577
|
-
const normalizedKey = key.replace(/_/g, "-");
|
|
2578
|
-
const value = headers[normalizedKey] || headers[normalizedKey.toUpperCase()] || headers[normalizedKey.toLowerCase()];
|
|
2579
|
-
return typeof value === "string" ? value : Array.isArray(value) ? value[0] : void 0;
|
|
2580
|
-
}
|
|
2581
|
-
function createApiRunner(serverModule2) {
|
|
2582
|
-
return async (method, uri, data, extra, domain) => {
|
|
2583
|
-
const apiManager = SessionContext.getAPIManager(serverModule2, extra);
|
|
2584
|
-
return await apiManager.callApi(method, uri, data, domain);
|
|
2585
|
-
};
|
|
2586
|
-
}
|
|
2587
|
-
function wrapServerWithTracking(server2, createServerFn) {
|
|
2588
|
-
const registrations = [];
|
|
2589
|
-
const originalTool = server2.tool?.bind(server2);
|
|
2590
|
-
const originalPrompt = server2.prompt?.bind(server2);
|
|
2591
|
-
const originalResource = server2.resource?.bind(server2);
|
|
2592
|
-
if (originalTool) {
|
|
2593
|
-
server2.tool = function(...args) {
|
|
2594
|
-
registrations.push({ type: "tool", method: "tool", args: [...args] });
|
|
2595
|
-
return originalTool(...args);
|
|
2596
|
-
};
|
|
2597
|
-
}
|
|
2598
|
-
if (originalPrompt) {
|
|
2599
|
-
server2.prompt = function(...args) {
|
|
2600
|
-
registrations.push({ type: "prompt", method: "prompt", args: [...args] });
|
|
2601
|
-
return originalPrompt(...args);
|
|
2602
|
-
};
|
|
2603
|
-
}
|
|
2604
|
-
if (originalResource) {
|
|
2605
|
-
server2.resource = function(...args) {
|
|
2606
|
-
registrations.push({ type: "resource", method: "resource", args: [...args] });
|
|
2607
|
-
return originalResource(...args);
|
|
2608
|
-
};
|
|
2609
|
-
}
|
|
2610
|
-
const createInstance = () => {
|
|
2611
|
-
const newServer = createServerFn();
|
|
2612
|
-
for (const reg of registrations) {
|
|
2613
|
-
if (newServer[reg.method]) {
|
|
2614
|
-
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 });
|
|
2615
2818
|
}
|
|
2616
2819
|
}
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
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;
|
|
2622
2847
|
}
|
|
2623
|
-
return newServer;
|
|
2624
|
-
};
|
|
2625
|
-
return { wrappedServer: server2, createInstance };
|
|
2626
|
-
}
|
|
2627
|
-
function createServerModule(server2, Settings2, pkg2, apiManagerClass, toolPolicyCallback, createServerFn) {
|
|
2628
|
-
const settingsManager = new SettingsManager(Settings2);
|
|
2629
|
-
const apiManagerFactory = new APIManagerFactory(apiManagerClass, settingsManager);
|
|
2630
|
-
const sessionManager = new SessionManager();
|
|
2631
|
-
if (toolPolicyCallback && typeof server2.setToolPolicy === "function") {
|
|
2632
|
-
console.error("[createServerModule] Setting tool policy callback on server");
|
|
2633
|
-
server2.setToolPolicy(toolPolicyCallback);
|
|
2634
2848
|
}
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2849
|
+
/**
|
|
2850
|
+
* Check if the session is expired based on sessionTimeout and sessionStart
|
|
2851
|
+
*/
|
|
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;
|
|
2643
2857
|
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
Settings: Settings2,
|
|
2647
|
-
settingsManager,
|
|
2648
|
-
apiManagerFactory,
|
|
2649
|
-
sessionManager,
|
|
2650
|
-
pkg: pkg2,
|
|
2651
|
-
toolPolicyCallback,
|
|
2652
|
-
createServerInstance
|
|
2653
|
-
};
|
|
2654
|
-
}
|
|
2655
|
-
|
|
2656
|
-
// ../mcp-utils/dist/index.js
|
|
2657
|
-
init_ui_dialog();
|
|
2658
|
-
|
|
2659
|
-
// ../mcp-utils/dist/mcp-server.js
|
|
2660
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2661
|
-
var CPMcpServer = class extends McpServer {
|
|
2662
|
-
constructor(serverInfo, options) {
|
|
2663
|
-
super(serverInfo, options);
|
|
2664
|
-
this.mcpName = serverInfo.name;
|
|
2665
|
-
this.mcpVersion = serverInfo.version || "0.0.0";
|
|
2858
|
+
getHeadersForLogin() {
|
|
2859
|
+
return { "Content-Type": "application/json" };
|
|
2666
2860
|
}
|
|
2667
2861
|
/**
|
|
2668
|
-
*
|
|
2669
|
-
* This should be called after all tools are registered but before connecting
|
|
2670
|
-
* @param callback Function that returns true if a tool should be enabled
|
|
2862
|
+
* Login to the API using the API key
|
|
2671
2863
|
*/
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
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;
|
|
2675
2882
|
}
|
|
2676
2883
|
/**
|
|
2677
|
-
*
|
|
2678
|
-
* This should be called after all tools are registered but before connecting
|
|
2884
|
+
* Detect if this is an MDS environment by checking the session details
|
|
2679
2885
|
*/
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2886
|
+
async detectMDS(sessionUid, handleSelfSigned = false) {
|
|
2887
|
+
try {
|
|
2888
|
+
let httpsAgent;
|
|
2889
|
+
if (handleSelfSigned) {
|
|
2890
|
+
httpsAgent = new https.Agent({ rejectUnauthorized: false });
|
|
2891
|
+
}
|
|
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;
|
|
2684
2899
|
}
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
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;
|
|
2690
2915
|
}
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
const
|
|
2697
|
-
|
|
2698
|
-
|
|
2699
|
-
|
|
2700
|
-
|
|
2701
|
-
|
|
2916
|
+
if (method.toUpperCase() !== "GET" && data !== void 0) {
|
|
2917
|
+
config.data = data;
|
|
2918
|
+
}
|
|
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));
|
|
2702
2934
|
}
|
|
2703
|
-
} else {
|
|
2704
|
-
console.error(`[CPMcpServer] Tool '${toolName}' is allowed by policy`);
|
|
2705
|
-
enabledCount++;
|
|
2706
2935
|
}
|
|
2936
|
+
if (error.response) {
|
|
2937
|
+
throw new Error(`API request failed: ${error.response.status} - ${JSON.stringify(error.response.data)}`);
|
|
2938
|
+
}
|
|
2939
|
+
throw error;
|
|
2707
2940
|
}
|
|
2708
|
-
console.error(`[CPMcpServer] Policy applied: ${enabledCount}/${toolNames.length} tools enabled, ${disabledCount} disabled`);
|
|
2709
2941
|
}
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
return callback({}, callbackArgs[0]);
|
|
2724
|
-
}
|
|
2725
|
-
return callback(...callbackArgs);
|
|
2726
|
-
};
|
|
2727
|
-
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}`;
|
|
2728
2955
|
}
|
|
2729
|
-
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;
|
|
2730
3004
|
}
|
|
2731
3005
|
};
|
|
2732
3006
|
|
|
2733
|
-
// ../
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
import { fileURLToPath } from "url";
|
|
2737
|
-
function readPackageJson(importMetaUrl) {
|
|
2738
|
-
const pkg2 = JSON.parse(readFileSync(join2(dirname(fileURLToPath(importMetaUrl)), "../package.json"), "utf-8"));
|
|
2739
|
-
process.env.CP_MCP_MAIN_PKG = `${pkg2.name} v${pkg2.version}`;
|
|
2740
|
-
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");
|
|
2741
3010
|
}
|
|
2742
|
-
function
|
|
2743
|
-
const
|
|
2744
|
-
const
|
|
2745
|
-
|
|
2746
|
-
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
const server2 = new CPMcpServer(fullServerInfo, options);
|
|
2753
|
-
server2._createServerFn = createServerFn;
|
|
2754
|
-
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;
|
|
2755
3021
|
}
|
|
2756
3022
|
|
|
2757
3023
|
// ../infra/dist/api-manager.js
|
|
@@ -3263,7 +3529,9 @@ var Settings = class _Settings {
|
|
|
3263
3529
|
return "STG";
|
|
3264
3530
|
return void 0;
|
|
3265
3531
|
}
|
|
3266
|
-
|
|
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 } = {}) {
|
|
3267
3535
|
this.region = "EU";
|
|
3268
3536
|
this.devPort = "8006";
|
|
3269
3537
|
this.gatewayUrl = "";
|
|
@@ -3443,19 +3711,20 @@ var Settings = class _Settings {
|
|
|
3443
3711
|
console.error("[Settings.fromArgs] Verbose: WARNING - Args object appears empty, no authentication values found");
|
|
3444
3712
|
}
|
|
3445
3713
|
}
|
|
3714
|
+
const env = process.env;
|
|
3446
3715
|
return new _Settings({
|
|
3447
|
-
apiKey: args.apiKey,
|
|
3448
|
-
username: args.username,
|
|
3449
|
-
password: args.password,
|
|
3450
|
-
s1cUrl: args.s1cUrl,
|
|
3451
|
-
managementHost: args.managementHost,
|
|
3452
|
-
managementPort: args.managementPort,
|
|
3453
|
-
cloudInfraToken: args.cloudInfraToken,
|
|
3454
|
-
cloudConnected: args.cloudConnected,
|
|
3455
|
-
clientId: args.clientId,
|
|
3456
|
-
secretKey: args.secretKey,
|
|
3457
|
-
region: typeof args.region === "string" ? args.region.trim().toUpperCase() : void 0,
|
|
3458
|
-
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),
|
|
3459
3728
|
gatewayUrl: args.gatewayUrl
|
|
3460
3729
|
});
|
|
3461
3730
|
}
|
|
@@ -3500,7 +3769,6 @@ var Settings = class _Settings {
|
|
|
3500
3769
|
const hasAnyValue = extractedValues.apiKey || extractedValues.username || extractedValues.password || extractedValues.s1cUrl || extractedValues.managementHost || extractedValues.cloudInfraToken;
|
|
3501
3770
|
if (!hasAnyValue) {
|
|
3502
3771
|
console.error("[Settings.fromHeaders] Verbose: WARNING - No authentication values found in headers");
|
|
3503
|
-
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])));
|
|
3504
3772
|
}
|
|
3505
3773
|
}
|
|
3506
3774
|
return new _Settings({
|
|
@@ -3521,6 +3789,17 @@ var Settings = class _Settings {
|
|
|
3521
3789
|
});
|
|
3522
3790
|
}
|
|
3523
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"];
|
|
3524
3803
|
|
|
3525
3804
|
// ../infra/dist/external-user-token-manager.js
|
|
3526
3805
|
import axios2 from "axios";
|