@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 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
- var TokenType;
1274
- (function(TokenType2) {
1275
- TokenType2["API_KEY"] = "API_KEY";
1276
- TokenType2["CI_TOKEN"] = "CI_TOKEN";
1277
- })(TokenType || (TokenType = {}));
1278
- function getMainPackageUserAgent() {
1279
- if (process.env.CP_MCP_MAIN_PKG) {
1280
- if (process.env.CP_MCP_MAIN_PKG.includes("quantum-management-mcp")) {
1281
- return "mgmt-mcp";
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 "Check Point MCP API Client";
1301
+ return values;
1285
1302
  }
1286
- var ClientResponse = class {
1287
- constructor(status, response) {
1288
- this.status = status;
1289
- this.response = response;
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
- var APIClientBase = class {
1293
- constructor(authToken = "", tokenType = TokenType.API_KEY, cloudConnected = false) {
1294
- this.authToken = authToken;
1295
- this.tokenType = tokenType;
1296
- this.cloudConnected = cloudConnected;
1297
- this.sid = null;
1298
- this.sessionTimeout = null;
1299
- this.sessionStart = null;
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
- * Create an API client instance - generic method for creating clients
1305
- */
1306
- static create(...args) {
1307
- return new this(...args);
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
- * Get headers for the API requests
1311
- */
1312
- getHeaders() {
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
- * Get debug mode
1446
+ * Creates a new SettingsManager
1447
+ * @param settingsClass The Settings class to use for creating settings instances
1328
1448
  */
1329
- get debug() {
1330
- return !!this._debug;
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
- * Set debug mode
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
- set debug(value) {
1336
- this._debug = value;
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
- * Set a pre-authenticated session ID provided externally (e.g. via X-chkp-sid header).
1340
- * When set, the client will skip login and use this SID directly for all requests.
1341
- */
1342
- setExternalSid(sid) {
1343
- this.sid = sid;
1344
- this._externalSid = true;
1345
- this.sessionStart = Date.now();
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
- * Check if this client needs to perform login before making API calls
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
- needsLogin() {
1352
- if (this._externalSid) {
1353
- return false;
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
- * Check if this client is in an MDS environment
1508
+ * Print settings object for debugging by dynamically discovering its properties
1509
+ * @param settings The settings object to print
1510
+ * @private
1359
1511
  */
1360
- async isMDSEnvironment() {
1361
- if (!this.hasValidSession()) {
1362
- await this.login();
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
- * Check if the client has a valid session
1368
- */
1369
- hasValidSession() {
1370
- return !!this.sid && !this.isSessionExpired();
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
- * Get the current session ID (for debugging/logging purposes)
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
- getSessionId() {
1376
- return this.sid;
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
- * Create a new API client instance with a specific session ID
1380
- * Used for domain-specific clients in MDS environments
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
- static createWithSid(originalClient, sid) {
1383
- const newClient = Object.create(Object.getPrototypeOf(originalClient));
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
- * Call an API endpoint
1553
+ * Create settings from HTTP headers
1554
+ * @param headers HTTP headers
1555
+ * @param sessionId Optional session ID
1556
+ * @returns Settings instance
1391
1557
  */
1392
- async callApi(method, uri, data, params) {
1393
- if (this.needsLogin() && (!this.sid || this.isSessionExpired())) {
1394
- try {
1395
- await this.login();
1396
- } catch (error) {
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
- let httpsAgent;
1406
- if (this instanceof OnPremAPIClient) {
1407
- httpsAgent = new https.Agent({ rejectUnauthorized: false });
1564
+ if (_SettingsManager.globalDebugState) {
1565
+ console.error("=== createFromHeaders Debug Info ===");
1566
+ console.error("Incoming headers:");
1567
+ this.printDebugView(headers);
1408
1568
  }
1409
- try {
1410
- return await this.makeRequest(this.getHost(), method, uri, data, this.getHeaders(), params, httpsAgent);
1411
- } catch (error) {
1412
- if ((error.message?.includes("401") || error.response?.status === 401) && error.message?.toLowerCase().includes("session")) {
1413
- if (this._externalSid) {
1414
- throw new Error("Pre-authenticated session (X-chkp-sid) has expired. Provide a new session ID.");
1415
- }
1416
- console.error("Session expired (401), resetting session and retrying...");
1417
- this.sid = null;
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
- const apiTokenHeader = this.tokenType === TokenType.API_KEY ? "api-key" : "ci-token";
1456
- const loginResp = await this.makeRequest(this.getHost(), "POST", "login", { [apiTokenHeader]: this.authToken }, this.getHeadersForLogin());
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
- this.sid = loginResp.response.sid;
1461
- this.sessionTimeout = loginResp.response["session-timeout"] || null;
1462
- this.sessionStart = Date.now();
1463
- if (loginResp.response.uid) {
1464
- await this.detectMDS(loginResp.response.uid);
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
- return loginResp.response.sid;
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
- * Detect if this is an MDS environment by checking the session details
1615
+ * Clear settings for a session
1616
+ * @param sessionId The session ID to clear
1470
1617
  */
1471
- async detectMDS(sessionUid, handleSelfSigned = false) {
1472
- try {
1473
- let httpsAgent;
1474
- if (handleSelfSigned) {
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
- * Make a request to a Check Point API
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
- async makeRequest(host, method, uri, data, headers = {}, params = null, httpsAgent) {
1490
- uri = uri.replace(/^\//, "");
1491
- const url = `${host}/${uri}`;
1492
- const config = {
1493
- method: method.toUpperCase(),
1494
- url,
1495
- headers,
1496
- params: params || void 0
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
- var SmartOneCloudAPIClient = class extends APIClientBase {
1530
- constructor(authToken, tokenType, s1cUrl, cloudConnected = false) {
1531
- super(authToken, tokenType, cloudConnected);
1532
- this.s1cUrl = s1cUrl;
1533
- }
1534
- getHost() {
1535
- return this.s1cUrl;
1536
- }
1537
- getHeadersForLogin() {
1538
- const headers = { "Content-Type": "application/json" };
1539
- if (this.cloudConnected && this.tokenType === TokenType.CI_TOKEN) {
1540
- headers["Authorization"] = `Bearer ${this.authToken}`;
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
- var OnPremAPIClient = class extends APIClientBase {
1546
- constructor(apiKey, managementHost, managementPort = "443", username, password, domain) {
1547
- super(apiKey || "");
1548
- this.managementHost = managementHost;
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
- getHost() {
1555
- const managementHost = this.managementHost;
1556
- const port = this.managementPort;
1557
- return `https://${managementHost}:${port}/web_api`;
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
- * Override login() to support both api-key and username/password authentication
1561
- * and allow self-signed certificates
1562
- */
1563
- async login() {
1564
- if (this._externalSid) {
1565
- if (!this.sid)
1566
- throw new Error("External SID has expired");
1567
- return this.sid;
1568
- }
1569
- const isUsingApiKey = !!this.authToken;
1570
- const isUsingCredentials = !!(this.username && this.password);
1571
- if (!isUsingApiKey && !isUsingCredentials) {
1572
- throw new ClientResponse(401, { message: "Authentication failed: No API key or username/password provided" });
1573
- }
1574
- const httpsAgent = new https.Agent({ rejectUnauthorized: false });
1575
- const loginPayload = isUsingApiKey ? { "api-key": this.authToken } : { "user": this.username, "password": this.password };
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
- function sanitizeData(kwargs) {
1598
- const data = {};
1599
- for (const [key, value] of Object.entries(kwargs)) {
1600
- if (value === null || value === void 0 || value === "" || Array.isArray(value) && value.length === 0) {
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 if not available
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
- if (!extra)
2315
- return this.DEFAULT_SESSION_ID;
2316
- if (extra.transport && extra.transport.sessionId) {
2317
- return extra.transport.sessionId;
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 session: ${sessionId}, key: ${options.cacheKey}`);
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 session: ${sessionId}, key: ${options.cacheKey}`);
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
- * Clear cached user data for a specific key
2485
- * @param cacheKey The cache key to clear
2486
- * @param extra Extra context with session information
2742
+ * Get debug mode
2487
2743
  */
2488
- static clearUserData(cacheKey, extra) {
2489
- const sessionId = this.getSessionId(extra);
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
- * Check if user data exists and is not expired
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
- static hasValidUserData(cacheKey, extra) {
2503
- const cachedData = this.getData(cacheKey, extra);
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
- * Create a new session
2529
- * @param sessionId The session ID
2530
- * @param metadata Optional metadata to store with the session
2531
- * @returns Session info
2532
- */
2533
- createSession(sessionId, metadata = {}) {
2534
- const now = /* @__PURE__ */ new Date();
2535
- const sessionInfo = {
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
- * Get info for a session
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
- getSession(sessionId) {
2550
- if (this.sessions.has(sessionId)) {
2551
- this.touchSession(sessionId);
2766
+ needsLogin() {
2767
+ if (this._externalSid) {
2768
+ return false;
2552
2769
  }
2553
- return this.sessions.get(sessionId);
2770
+ return true;
2554
2771
  }
2555
2772
  /**
2556
- * Update session activity timestamp
2557
- * @param sessionId The session ID
2773
+ * Check if this client is in an MDS environment
2558
2774
  */
2559
- touchSession(sessionId) {
2560
- const session = this.sessions.get(sessionId);
2561
- if (session) {
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
- * Remove a session
2567
- * @param sessionId The session ID
2782
+ * Check if the client has a valid session
2568
2783
  */
2569
- removeSession(sessionId) {
2570
- this.sessions.delete(sessionId);
2571
- SessionContext.clearSessionData(sessionId);
2784
+ hasValidSession() {
2785
+ return !!this.sid && !this.isSessionExpired();
2572
2786
  }
2573
2787
  /**
2574
- * Get all active sessions
2575
- * @returns Array of session info objects
2788
+ * Get the current session ID (for debugging/logging purposes)
2576
2789
  */
2577
- getAllSessions() {
2578
- return Array.from(this.sessions.values());
2790
+ getSessionId() {
2791
+ return this.sid;
2579
2792
  }
2580
2793
  /**
2581
- * Get count of active sessions
2582
- * @returns Number of active sessions
2794
+ * Create a new API client instance with a specific session ID
2795
+ * Used for domain-specific clients in MDS environments
2583
2796
  */
2584
- getSessionCount() {
2585
- return this.sessions.size;
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
- * Clean up inactive sessions older than the specified timeout
2589
- * @param timeoutMs Timeout in milliseconds (default: 30 minutes)
2590
- * @returns Number of sessions removed
2805
+ * Call an API endpoint
2591
2806
  */
2592
- cleanupInactiveSessions(timeoutMs = DEFAULT_SESSION_TIMEOUT_MS) {
2593
- const now = /* @__PURE__ */ new Date();
2594
- let removedCount = 0;
2595
- for (const [sessionId, session] of this.sessions.entries()) {
2596
- const inactiveTime = now.getTime() - session.lastActive.getTime();
2597
- if (inactiveTime > timeoutMs) {
2598
- this.removeSession(sessionId);
2599
- removedCount++;
2600
- }
2601
- }
2602
- return removedCount;
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
- const toolPolicy = typeof server2.getToolPolicy === "function" ? server2.getToolPolicy() : void 0;
2649
- if (toolPolicy && typeof newServer.setToolPolicy === "function") {
2650
- newServer.setToolPolicy(toolPolicy);
2651
- if (typeof newServer.applyToolPolicy === "function") {
2652
- newServer.applyToolPolicy();
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
- * Set a tool policy callback to filter which tools are available
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
- setToolPolicy(callback) {
2705
- console.error("[CPMcpServer] Setting tool policy callback");
2706
- this.toolPolicyCallback = callback;
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
- * Get the tool policy callback, if one was set.
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
- getToolPolicy() {
2717
- return this.toolPolicyCallback;
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
- * Apply the tool policy by checking all registered tools
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
- applyToolPolicy() {
2730
- const verbose = SettingsManager.globalDebugState === true || SettingsManager.globalDebugState === "true";
2731
- if (!this.toolPolicyCallback) {
2732
- if (verbose) {
2733
- console.error("[CPMcpServer] No tool policy callback set, allowing all tools");
2886
+ async detectMDS(sessionUid, handleSelfSigned = false) {
2887
+ try {
2888
+ let httpsAgent;
2889
+ if (handleSelfSigned) {
2890
+ httpsAgent = new https.Agent({ rejectUnauthorized: false });
2734
2891
  }
2735
- return;
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
- const registeredTools = this._registeredTools;
2738
- if (!registeredTools || typeof registeredTools !== "object") {
2739
- console.error("[CPMcpServer] No tools registered yet");
2740
- return;
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
- const toolNames = Object.keys(registeredTools);
2743
- if (verbose) {
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
- let enabledCount = 0;
2748
- let disabledCount = 0;
2749
- for (const [toolName, tool] of Object.entries(registeredTools)) {
2750
- const isAllowed = this.toolPolicyCallback(toolName);
2751
- if (!isAllowed) {
2752
- if (verbose) {
2753
- console.error(`[CPMcpServer] Tool '${toolName}' is NOT allowed by policy - disabling`);
2754
- }
2755
- if (typeof tool.disable === "function") {
2756
- tool.disable();
2757
- disabledCount++;
2758
- }
2759
- } else {
2760
- if (verbose) {
2761
- console.error(`[CPMcpServer] Tool '${toolName}' is allowed by policy`);
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
- // Override the tool method to wrap callbacks with telemetry
2769
- tool(...args) {
2770
- const callback = args[args.length - 1];
2771
- if (typeof callback === "function") {
2772
- const toolName = args[0];
2773
- const wrappedCallback = async (...callbackArgs) => {
2774
- let extra = callbackArgs[1];
2775
- if (!extra && callbackArgs[0]?.sessionId) {
2776
- extra = callbackArgs[0];
2777
- }
2778
- trackToolCall(this.mcpName, toolName, this.mcpVersion, extra).catch(() => {
2779
- });
2780
- if (callbackArgs.length === 1 && callbackArgs[0]?.sessionId) {
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 super.tool(...args);
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
- // ../mcp-utils/dist/package-utils.js
2792
- import { readFileSync } from "fs";
2793
- import { join as join2, dirname } from "path";
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 createMcpServer(importMetaUrl, serverInfo, options) {
2801
- const pkg2 = readPackageJson(importMetaUrl);
2802
- const fullServerInfo = {
2803
- ...serverInfo,
2804
- name: serverInfo.name || pkg2.name,
2805
- version: serverInfo.version || pkg2.version
2806
- };
2807
- const createServerFn = () => {
2808
- return new CPMcpServer(fullServerInfo, options);
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
- constructor({ apiKey = process.env.API_KEY, username = process.env.USERNAME, password = process.env.PASSWORD, s1cUrl = process.env.S1C_URL, managementHost = process.env.MANAGEMENT_HOST, managementPort = process.env.MANAGEMENT_PORT || "443", cloudInfraToken = process.env.CLOUD_INFRA_TOKEN, cloudConnected = process.env.CLOUD_CONNECTED === "true", sid, clientId = process.env.CLIENT_ID, secretKey = process.env.SECRET_KEY, region = process.env.REGION || "EU", devPort = process.env.DEV_PORT || "8006", gatewayUrl } = {}) {
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";