@chkp/harmony-email-mcp 0.1.1 → 0.1.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/README.md +2 -2
- package/dist/index.js +671 -319
- package/dist/package.json +1 -1
- package/package.json +1 -1
- package/package.json.bak +1 -1
package/dist/index.js
CHANGED
|
@@ -365,6 +365,84 @@ var init_ui_dialog = __esm({
|
|
|
365
365
|
}
|
|
366
366
|
});
|
|
367
367
|
|
|
368
|
+
// ../mcp-utils/dist/cli-options.js
|
|
369
|
+
function booleanOptionDefault(envValue, optionDefault) {
|
|
370
|
+
return envValue === "true" || optionDefault === "true";
|
|
371
|
+
}
|
|
372
|
+
function resolveTransportType(transportOption, env = process.env) {
|
|
373
|
+
return (transportOption || env.MCP_TRANSPORT_TYPE || "stdio").toLowerCase() === "http" ? "http" : "stdio";
|
|
374
|
+
}
|
|
375
|
+
function optionKey(flag) {
|
|
376
|
+
const long = flag.split(/[,\s]+/).find((part) => part.startsWith("--"));
|
|
377
|
+
if (!long)
|
|
378
|
+
return void 0;
|
|
379
|
+
const negated = long.startsWith("--no-");
|
|
380
|
+
return {
|
|
381
|
+
key: long.replace(/^--(no-)?/, "").replace(/-([a-z])/g, (_match, char) => char.toUpperCase()),
|
|
382
|
+
negated
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
function operatorValues(options, parsed, env = process.env) {
|
|
386
|
+
const values = { ...env };
|
|
387
|
+
for (const option of options) {
|
|
388
|
+
const derived = option.env ? optionKey(option.flag) : void 0;
|
|
389
|
+
if (!derived || derived.negated)
|
|
390
|
+
continue;
|
|
391
|
+
const value = parsed[derived.key];
|
|
392
|
+
if (value !== void 0)
|
|
393
|
+
values[option.env] = value;
|
|
394
|
+
}
|
|
395
|
+
return values;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// ../mcp-utils/dist/debug-view.js
|
|
399
|
+
import { createHash } from "node:crypto";
|
|
400
|
+
var BUILTIN_LOGGABLE_KEYS = [
|
|
401
|
+
"accept",
|
|
402
|
+
"accept-encoding",
|
|
403
|
+
"accept-language",
|
|
404
|
+
"connection",
|
|
405
|
+
"content-length",
|
|
406
|
+
"content-type",
|
|
407
|
+
"host",
|
|
408
|
+
"mcp-protocol-version",
|
|
409
|
+
"traceparent",
|
|
410
|
+
"user-agent",
|
|
411
|
+
"x-correlation-id",
|
|
412
|
+
"x-gw-auth-method",
|
|
413
|
+
"x-request-id",
|
|
414
|
+
// Launcher options
|
|
415
|
+
"debug",
|
|
416
|
+
"telemetry",
|
|
417
|
+
"telemetry-url",
|
|
418
|
+
"transport",
|
|
419
|
+
"transport-port"
|
|
420
|
+
];
|
|
421
|
+
function normalizeDebugKey(key) {
|
|
422
|
+
const split = /[-_]/.test(key) ? key : key.replace(/([a-z][0-9]*)([A-Z])/g, "$1-$2");
|
|
423
|
+
return split.replace(/_/g, "-").toLowerCase();
|
|
424
|
+
}
|
|
425
|
+
function debugLoggableKeys(extra = []) {
|
|
426
|
+
return new Set([...BUILTIN_LOGGABLE_KEYS, ...extra].map(normalizeDebugKey));
|
|
427
|
+
}
|
|
428
|
+
function describe(key, value, loggable) {
|
|
429
|
+
if (value === void 0 || value === null || value === "")
|
|
430
|
+
return "(unset)";
|
|
431
|
+
if (loggable.has(normalizeDebugKey(key))) {
|
|
432
|
+
return typeof value === "string" ? value : JSON.stringify(value);
|
|
433
|
+
}
|
|
434
|
+
const text = typeof value === "string" ? value : Array.isArray(value) ? value.join(", ") : void 0;
|
|
435
|
+
return text === void 0 ? "(hidden)" : `(hidden, ${text.length} chars)`;
|
|
436
|
+
}
|
|
437
|
+
function debugView(record, loggable = debugLoggableKeys()) {
|
|
438
|
+
return Object.fromEntries(Object.entries(record ?? {}).map(([key, value]) => [key, describe(key, value, loggable)]));
|
|
439
|
+
}
|
|
440
|
+
function sessionLogLabel(sessionId) {
|
|
441
|
+
if (!sessionId || sessionId === "default")
|
|
442
|
+
return "default";
|
|
443
|
+
return `session#${createHash("sha256").update(sessionId).digest("hex").slice(0, 8)}`;
|
|
444
|
+
}
|
|
445
|
+
|
|
368
446
|
// ../mcp-utils/dist/launcher.js
|
|
369
447
|
import { Command } from "commander";
|
|
370
448
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
@@ -373,6 +451,89 @@ import fs from "fs";
|
|
|
373
451
|
import http from "http";
|
|
374
452
|
import { randomUUID } from "crypto";
|
|
375
453
|
|
|
454
|
+
// ../mcp-utils/dist/connection-source.js
|
|
455
|
+
function hasValue(value) {
|
|
456
|
+
return value !== void 0 && value !== null && value !== "" && !(Array.isArray(value) && value.length === 0);
|
|
457
|
+
}
|
|
458
|
+
function headersRead(fromHeaders, headers) {
|
|
459
|
+
const read = /* @__PURE__ */ new Set();
|
|
460
|
+
const recording = new Proxy(headers, {
|
|
461
|
+
get(target, prop, receiver) {
|
|
462
|
+
const value = Reflect.get(target, prop, receiver);
|
|
463
|
+
if (typeof prop === "string" && hasValue(value))
|
|
464
|
+
read.add(prop);
|
|
465
|
+
return value;
|
|
466
|
+
}
|
|
467
|
+
});
|
|
468
|
+
try {
|
|
469
|
+
fromHeaders(recording);
|
|
470
|
+
} catch {
|
|
471
|
+
}
|
|
472
|
+
return read;
|
|
473
|
+
}
|
|
474
|
+
function keySet(keys = []) {
|
|
475
|
+
return new Set(keys.map(normalizeDebugKey));
|
|
476
|
+
}
|
|
477
|
+
function chooseConnectionSource(read, basicKeys) {
|
|
478
|
+
for (const key of read) {
|
|
479
|
+
if (!basicKeys.has(normalizeDebugKey(key)))
|
|
480
|
+
return "caller";
|
|
481
|
+
}
|
|
482
|
+
return "operator";
|
|
483
|
+
}
|
|
484
|
+
function basicOnly(headers, basicKeys) {
|
|
485
|
+
return Object.fromEntries(Object.entries(headers).filter(([key]) => basicKeys.has(normalizeDebugKey(key))));
|
|
486
|
+
}
|
|
487
|
+
function mergeHeaders(base, overrides) {
|
|
488
|
+
const merged = {};
|
|
489
|
+
const index = /* @__PURE__ */ new Map();
|
|
490
|
+
for (const [key, value] of [...Object.entries(base), ...Object.entries(overrides)]) {
|
|
491
|
+
const id = normalizeDebugKey(key);
|
|
492
|
+
const previous = index.get(id);
|
|
493
|
+
if (previous !== void 0)
|
|
494
|
+
delete merged[previous];
|
|
495
|
+
index.set(id, key);
|
|
496
|
+
merged[key] = value;
|
|
497
|
+
}
|
|
498
|
+
return merged;
|
|
499
|
+
}
|
|
500
|
+
function operatorHeaders(values) {
|
|
501
|
+
const headers = {};
|
|
502
|
+
for (const [name, value] of Object.entries(values)) {
|
|
503
|
+
if (!hasValue(value))
|
|
504
|
+
continue;
|
|
505
|
+
headers[name.replace(/_/g, "-")] = Array.isArray(value) ? value.map(String) : String(value);
|
|
506
|
+
}
|
|
507
|
+
return headers;
|
|
508
|
+
}
|
|
509
|
+
function canonicalizeAliases(headers, aliases) {
|
|
510
|
+
if (aliases.size === 0)
|
|
511
|
+
return headers;
|
|
512
|
+
const canonical = new Set([...aliases.values()].map(normalizeDebugKey));
|
|
513
|
+
const present = new Set(Object.keys(headers).map(normalizeDebugKey).filter((key) => canonical.has(key)));
|
|
514
|
+
const result = {};
|
|
515
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
516
|
+
const target = aliases.get(normalizeDebugKey(key));
|
|
517
|
+
if (target === void 0) {
|
|
518
|
+
result[key] = value;
|
|
519
|
+
} else if (!present.has(normalizeDebugKey(target))) {
|
|
520
|
+
result[target] = value;
|
|
521
|
+
present.add(normalizeDebugKey(target));
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
525
|
+
}
|
|
526
|
+
function aliasMap(aliases = {}) {
|
|
527
|
+
return new Map(Object.entries(aliases).map(([alias, target]) => [normalizeDebugKey(alias), target]));
|
|
528
|
+
}
|
|
529
|
+
function sessionHeaders(source, callerHeaders, operator, basicKeys, operatorSettingsOverHttp) {
|
|
530
|
+
if (source === "caller") {
|
|
531
|
+
return mergeHeaders(basicOnly(operator, basicKeys), callerHeaders);
|
|
532
|
+
}
|
|
533
|
+
const base = operatorSettingsOverHttp ? operator : basicOnly(operator, basicKeys);
|
|
534
|
+
return mergeHeaders(base, basicOnly(callerHeaders, basicKeys));
|
|
535
|
+
}
|
|
536
|
+
|
|
376
537
|
// ../mcp-utils/dist/settings-manager.js
|
|
377
538
|
var SettingsManager = class _SettingsManager {
|
|
378
539
|
/**
|
|
@@ -382,7 +543,13 @@ var SettingsManager = class _SettingsManager {
|
|
|
382
543
|
constructor(settingsClass) {
|
|
383
544
|
this.settingsMap = /* @__PURE__ */ new Map();
|
|
384
545
|
this.defaultSessionId = "default";
|
|
546
|
+
this.operatorValues = {};
|
|
547
|
+
this.sessionSources = /* @__PURE__ */ new Map();
|
|
385
548
|
this.settingsClass = settingsClass;
|
|
549
|
+
this.loggableKeys = debugLoggableKeys(settingsClass?.debugLoggableKeys ?? []);
|
|
550
|
+
this.basicKeys = keySet(settingsClass?.basicKeys ?? []);
|
|
551
|
+
this.headerAliases = aliasMap(settingsClass?.headerAliases);
|
|
552
|
+
this.operatorSettingsOverHttp = settingsClass?.operatorSettingsOverHttp !== false;
|
|
386
553
|
}
|
|
387
554
|
/**
|
|
388
555
|
* Get settings for a specific session
|
|
@@ -409,12 +576,15 @@ var SettingsManager = class _SettingsManager {
|
|
|
409
576
|
* Injects debug settings from source into settings object
|
|
410
577
|
* @param settings The settings object to update
|
|
411
578
|
* @param source Source object containing debug information
|
|
579
|
+
* @param scope 'process' when the operator set debug (CLI/env), which also
|
|
580
|
+
* updates the process-wide state; 'session' when a caller set it through a
|
|
581
|
+
* header, which affects only that session's settings
|
|
412
582
|
* @private
|
|
413
583
|
*/
|
|
414
|
-
injectDebug(settings, source) {
|
|
584
|
+
injectDebug(settings, source, scope) {
|
|
415
585
|
const debug = source?.debug ?? _SettingsManager.globalDebugState ?? process.env.DEBUG;
|
|
416
586
|
if (typeof debug !== "undefined") {
|
|
417
|
-
if (source?.debug !== void 0) {
|
|
587
|
+
if (scope === "process" && source?.debug !== void 0) {
|
|
418
588
|
_SettingsManager.globalDebugState = source.debug;
|
|
419
589
|
}
|
|
420
590
|
if (typeof settings.set === "function") {
|
|
@@ -423,8 +593,8 @@ var SettingsManager = class _SettingsManager {
|
|
|
423
593
|
settings.debug = debug;
|
|
424
594
|
}
|
|
425
595
|
if (debug) {
|
|
426
|
-
console.error("Debug enabled. Source
|
|
427
|
-
|
|
596
|
+
console.error("Debug enabled. Source:");
|
|
597
|
+
this.printDebugView(source);
|
|
428
598
|
}
|
|
429
599
|
}
|
|
430
600
|
}
|
|
@@ -437,19 +607,21 @@ var SettingsManager = class _SettingsManager {
|
|
|
437
607
|
if (typeof settings.get === "function") {
|
|
438
608
|
console.error("Settings (using get method):");
|
|
439
609
|
if (settings.data && typeof settings.data === "object") {
|
|
440
|
-
|
|
441
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
442
|
-
});
|
|
610
|
+
this.printDebugView(settings.data);
|
|
443
611
|
} else {
|
|
444
612
|
console.error(" Unable to enumerate settings properties - no accessible data structure");
|
|
445
613
|
}
|
|
446
614
|
} else {
|
|
447
615
|
console.error("Settings (plain object):");
|
|
448
|
-
|
|
449
|
-
console.error(` ${key}: ${JSON.stringify(value)}`);
|
|
450
|
-
});
|
|
616
|
+
this.printDebugView(settings);
|
|
451
617
|
}
|
|
452
618
|
}
|
|
619
|
+
/** Print allowlisted values; everything else as "(hidden, N chars)". */
|
|
620
|
+
printDebugView(record) {
|
|
621
|
+
Object.entries(debugView(record, this.loggableKeys)).forEach(([key, value]) => {
|
|
622
|
+
console.error(` ${key}: ${value}`);
|
|
623
|
+
});
|
|
624
|
+
}
|
|
453
625
|
/**
|
|
454
626
|
* Create settings from command-line arguments
|
|
455
627
|
* @param args Command line arguments
|
|
@@ -458,10 +630,19 @@ var SettingsManager = class _SettingsManager {
|
|
|
458
630
|
*/
|
|
459
631
|
createFromArgs(args, sessionId) {
|
|
460
632
|
const settings = this.settingsClass.fromArgs(args);
|
|
461
|
-
this.injectDebug(settings, args);
|
|
633
|
+
this.injectDebug(settings, args, "process");
|
|
462
634
|
this.setSettings(settings, sessionId);
|
|
463
635
|
return settings;
|
|
464
636
|
}
|
|
637
|
+
/**
|
|
638
|
+
* Record the operator's values (environment variables and parsed CLI
|
|
639
|
+
* options, keyed by environment-variable name). HTTP sessions take basic
|
|
640
|
+
* keys from them when the caller doesn't send its own, and their whole
|
|
641
|
+
* connection set when the caller sends none of it.
|
|
642
|
+
*/
|
|
643
|
+
setOperatorValues(values) {
|
|
644
|
+
this.operatorValues = canonicalizeAliases(operatorHeaders(values), this.headerAliases);
|
|
645
|
+
}
|
|
465
646
|
/**
|
|
466
647
|
* Create settings from HTTP headers
|
|
467
648
|
* @param headers HTTP headers
|
|
@@ -471,13 +652,13 @@ var SettingsManager = class _SettingsManager {
|
|
|
471
652
|
createFromHeaders(headers, sessionId) {
|
|
472
653
|
const verbose = _SettingsManager.globalDebugState;
|
|
473
654
|
if (verbose) {
|
|
474
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Starting with
|
|
655
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Starting with session:", sessionLogLabel(sessionId));
|
|
475
656
|
console.error("[SettingsManager.createFromHeaders] Verbose: Incoming headers count:", Object.keys(headers).length);
|
|
476
657
|
}
|
|
477
658
|
if (_SettingsManager.globalDebugState) {
|
|
478
659
|
console.error("=== createFromHeaders Debug Info ===");
|
|
479
660
|
console.error("Incoming headers:");
|
|
480
|
-
|
|
661
|
+
this.printDebugView(headers);
|
|
481
662
|
}
|
|
482
663
|
if (verbose && (!headers || Object.keys(headers).length === 0)) {
|
|
483
664
|
console.error("[SettingsManager.createFromHeaders] Verbose: WARNING - Headers object is empty or undefined");
|
|
@@ -494,26 +675,32 @@ var SettingsManager = class _SettingsManager {
|
|
|
494
675
|
console.error("[SettingsManager.createFromHeaders] Verbose: Normalized headers count:", Object.keys(normalizedHeaders).length);
|
|
495
676
|
}
|
|
496
677
|
if (_SettingsManager.globalDebugState) {
|
|
497
|
-
console.error("Normalized
|
|
498
|
-
console.error(JSON.stringify(normalizedHeaders, null, 2));
|
|
678
|
+
console.error("Normalized header names:", Object.keys(normalizedHeaders));
|
|
499
679
|
}
|
|
500
680
|
const debugHeader = normalizedHeaders["debug"] || normalizedHeaders["Debug"] || normalizedHeaders["DEBUG"];
|
|
501
|
-
const
|
|
681
|
+
const requestedDebug = Array.isArray(debugHeader) ? debugHeader[0] : debugHeader;
|
|
682
|
+
const debugSource = {
|
|
683
|
+
debug: requestedDebug !== void 0 ? requestedDebug.toLowerCase() === "true" : _SettingsManager.globalDebugState
|
|
684
|
+
};
|
|
685
|
+
const callerHeaders = canonicalizeAliases(normalizedHeaders, this.headerAliases);
|
|
686
|
+
const source = this.connectionSource(callerHeaders, sessionId);
|
|
687
|
+
const inputHeaders = sessionHeaders(source, callerHeaders, this.operatorValues, this.basicKeys, this.operatorSettingsOverHttp);
|
|
502
688
|
if (verbose) {
|
|
689
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Connection settings source:", source);
|
|
503
690
|
console.error("[SettingsManager.createFromHeaders] Verbose: Calling settingsClass.fromHeaders");
|
|
504
691
|
}
|
|
505
|
-
const settings = this.settingsClass.fromHeaders(
|
|
692
|
+
const settings = this.settingsClass.fromHeaders(inputHeaders);
|
|
506
693
|
if (verbose) {
|
|
507
694
|
console.error("[SettingsManager.createFromHeaders] Verbose: Settings object created");
|
|
508
695
|
}
|
|
509
|
-
this.injectDebug(settings, debugSource);
|
|
696
|
+
this.injectDebug(settings, debugSource, "session");
|
|
510
697
|
if (_SettingsManager.globalDebugState) {
|
|
511
|
-
console.error("Final settings object for session:", sessionId
|
|
698
|
+
console.error("Final settings object for session:", sessionLogLabel(sessionId));
|
|
512
699
|
this.printSettingsDebug(settings);
|
|
513
700
|
console.error("=== End createFromHeaders Debug Info ===");
|
|
514
701
|
}
|
|
515
702
|
if (verbose) {
|
|
516
|
-
console.error("[SettingsManager.createFromHeaders] Verbose: Storing settings for session:", sessionId
|
|
703
|
+
console.error("[SettingsManager.createFromHeaders] Verbose: Storing settings for session:", sessionLogLabel(sessionId));
|
|
517
704
|
}
|
|
518
705
|
this.setSettings(settings, sessionId);
|
|
519
706
|
return settings;
|
|
@@ -525,14 +712,28 @@ var SettingsManager = class _SettingsManager {
|
|
|
525
712
|
clearSession(sessionId) {
|
|
526
713
|
if (sessionId !== this.defaultSessionId) {
|
|
527
714
|
this.settingsMap.delete(sessionId);
|
|
715
|
+
this.sessionSources.delete(sessionId);
|
|
528
716
|
}
|
|
529
717
|
}
|
|
718
|
+
/**
|
|
719
|
+
* The session's connection source: decided by the request that creates the
|
|
720
|
+
* session and kept for its lifetime, so a later request cannot switch it.
|
|
721
|
+
*/
|
|
722
|
+
connectionSource(headers, sessionId) {
|
|
723
|
+
const known = sessionId ? this.sessionSources.get(sessionId) : void 0;
|
|
724
|
+
if (known)
|
|
725
|
+
return known;
|
|
726
|
+
const source = chooseConnectionSource(headersRead((h) => this.settingsClass.fromHeaders(h), headers), this.basicKeys);
|
|
727
|
+
if (sessionId)
|
|
728
|
+
this.sessionSources.set(sessionId, source);
|
|
729
|
+
return source;
|
|
730
|
+
}
|
|
530
731
|
};
|
|
531
732
|
SettingsManager.globalDebugState = void 0;
|
|
532
733
|
|
|
533
734
|
// ../mcp-utils/dist/telemetry.js
|
|
534
735
|
import machineIdPkg from "node-machine-id";
|
|
535
|
-
import { createHash } from "crypto";
|
|
736
|
+
import { createHash as createHash2 } from "crypto";
|
|
536
737
|
var { machineIdSync } = machineIdPkg;
|
|
537
738
|
var machineId = null;
|
|
538
739
|
var hashedMachineId = null;
|
|
@@ -547,7 +748,7 @@ function getTelemetryUrl() {
|
|
|
547
748
|
return process.env.TELEMETRY_URL || "https://metrics.security.ai.checkpoint.com/api/v1/metrics/collect";
|
|
548
749
|
}
|
|
549
750
|
function hashString(input) {
|
|
550
|
-
return
|
|
751
|
+
return createHash2("sha256").update(input).digest("hex");
|
|
551
752
|
}
|
|
552
753
|
function getMachineId() {
|
|
553
754
|
if (!machineId) {
|
|
@@ -595,6 +796,21 @@ async function trackToolCall(mcpName, toolName, clientVersion, extra) {
|
|
|
595
796
|
}
|
|
596
797
|
|
|
597
798
|
// ../mcp-utils/dist/launcher.js
|
|
799
|
+
function mirrorBooleanFlagsToEnv(config, options) {
|
|
800
|
+
for (const option of config.options) {
|
|
801
|
+
if (option.type !== "boolean" || !option.env)
|
|
802
|
+
continue;
|
|
803
|
+
const derived = optionKey(option.flag);
|
|
804
|
+
if (!derived)
|
|
805
|
+
continue;
|
|
806
|
+
if (derived.negated) {
|
|
807
|
+
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.`);
|
|
808
|
+
}
|
|
809
|
+
if (options[derived.key] === true) {
|
|
810
|
+
process.env[option.env] = "true";
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
598
814
|
async function launchMCPServer(configPath, serverModule2) {
|
|
599
815
|
const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
600
816
|
const program = new Command();
|
|
@@ -605,7 +821,7 @@ async function launchMCPServer(configPath, serverModule2) {
|
|
|
605
821
|
const envValue = option.env ? process.env[option.env] : void 0;
|
|
606
822
|
const defaultValue = envValue || option.default;
|
|
607
823
|
if (option.type === "boolean") {
|
|
608
|
-
const boolDefault = envValue
|
|
824
|
+
const boolDefault = booleanOptionDefault(envValue, option.default);
|
|
609
825
|
program.option(option.flag, option.description, boolDefault);
|
|
610
826
|
} else {
|
|
611
827
|
program.option(option.flag, option.description, defaultValue);
|
|
@@ -629,17 +845,24 @@ async function launchMCPServer(configPath, serverModule2) {
|
|
|
629
845
|
if (options.telemetryUrl) {
|
|
630
846
|
process.env.TELEMETRY_URL = options.telemetryUrl;
|
|
631
847
|
}
|
|
848
|
+
mirrorBooleanFlagsToEnv(config, options);
|
|
849
|
+
const transportType2 = resolveTransportType(options.transport);
|
|
850
|
+
process.env.MCP_TRANSPORT_TYPE = transportType2;
|
|
632
851
|
if (!serverModule2.settingsManager) {
|
|
633
852
|
throw new Error("ServerModule must have a settingsManager. Create it with createServerModule.");
|
|
634
853
|
}
|
|
635
854
|
const settings = serverModule2.settingsManager.createFromArgs(options);
|
|
855
|
+
serverModule2.settingsManager.setOperatorValues?.(operatorValues(config.options, options));
|
|
636
856
|
if (typeof serverModule2.server.applyToolPolicy === "function") {
|
|
637
857
|
console.error("[launchMCPServer] Applying tool policy before connecting");
|
|
638
858
|
serverModule2.server.applyToolPolicy();
|
|
639
859
|
}
|
|
640
|
-
const transportType2 = (options.transport || process.env.MCP_TRANSPORT_TYPE || "stdio").toLowerCase() === "http" ? "http" : "stdio";
|
|
641
860
|
const transportPort = options.transportPort ? parseInt(options.transportPort, 10) : process.env.MCP_TRANSPORT_PORT ? parseInt(process.env.MCP_TRANSPORT_PORT, 10) : 3e3;
|
|
642
861
|
if (transportType2 === "http") {
|
|
862
|
+
const refusal = serverModule2.httpStartupCheck?.();
|
|
863
|
+
if (refusal) {
|
|
864
|
+
throw new Error(refusal);
|
|
865
|
+
}
|
|
643
866
|
setTransportType("http");
|
|
644
867
|
await launchHTTPServer(config, serverModule2, transportPort);
|
|
645
868
|
} else {
|
|
@@ -688,7 +911,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
688
911
|
if (sessionId && transports[sessionId]) {
|
|
689
912
|
const verbose = SettingsManager.globalDebugState;
|
|
690
913
|
if (verbose) {
|
|
691
|
-
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionId);
|
|
914
|
+
console.error("[launchHTTPServer] Verbose: Reusing existing transport for session:", sessionLogLabel(sessionId));
|
|
692
915
|
}
|
|
693
916
|
transport = transports[sessionId];
|
|
694
917
|
if (!serverModule2.settingsManager) {
|
|
@@ -708,7 +931,7 @@ async function launchHTTPServer(config, serverModule2, port) {
|
|
|
708
931
|
onsessioninitialized: (sid) => {
|
|
709
932
|
const verbose = SettingsManager.globalDebugState;
|
|
710
933
|
if (verbose) {
|
|
711
|
-
console.error("[launchHTTPServer] Verbose: New session initialized:", sid);
|
|
934
|
+
console.error("[launchHTTPServer] Verbose: New session initialized:", sessionLogLabel(sid));
|
|
712
935
|
}
|
|
713
936
|
transports[sid] = transport;
|
|
714
937
|
if (verbose) {
|
|
@@ -911,7 +1134,6 @@ function headersToEnvVars(headers, config) {
|
|
|
911
1134
|
}
|
|
912
1135
|
if (verbose) {
|
|
913
1136
|
console.error("[headersToEnvVars] Verbose: Final result keys:", Object.keys(result));
|
|
914
|
-
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])));
|
|
915
1137
|
}
|
|
916
1138
|
return result;
|
|
917
1139
|
}
|
|
@@ -938,7 +1160,7 @@ var APIManagerFactory = class {
|
|
|
938
1160
|
const verbose = SettingsManager.globalDebugState;
|
|
939
1161
|
const sid = sessionId || this.defaultSessionId;
|
|
940
1162
|
if (verbose) {
|
|
941
|
-
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sid);
|
|
1163
|
+
console.error("[APIManagerFactory.getAPIManager] Verbose: Getting API manager for session:", sessionLogLabel(sid));
|
|
942
1164
|
}
|
|
943
1165
|
if (!this.apiManagerMap.has(sid)) {
|
|
944
1166
|
if (verbose) {
|
|
@@ -1036,16 +1258,15 @@ var SessionContext = class {
|
|
|
1036
1258
|
/**
|
|
1037
1259
|
* Get the current session ID from the MCP extra context
|
|
1038
1260
|
* @param extra Extra context passed to MCP tool callbacks
|
|
1039
|
-
* @returns The session ID or DEFAULT_SESSION_ID
|
|
1261
|
+
* @returns The session ID, or DEFAULT_SESSION_ID under stdio
|
|
1262
|
+
* @throws Under HTTP transport when the context carries no session ID
|
|
1040
1263
|
*/
|
|
1041
1264
|
static getSessionId(extra) {
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
if (extra.sessionId) {
|
|
1048
|
-
return extra.sessionId;
|
|
1265
|
+
const sessionId = extra?.transport?.sessionId || extra?.sessionId;
|
|
1266
|
+
if (sessionId)
|
|
1267
|
+
return sessionId;
|
|
1268
|
+
if (process.env.MCP_TRANSPORT_TYPE === "http") {
|
|
1269
|
+
throw new Error("No MCP session in this request context; HTTP transport requires one");
|
|
1049
1270
|
}
|
|
1050
1271
|
return this.DEFAULT_SESSION_ID;
|
|
1051
1272
|
}
|
|
@@ -1162,10 +1383,10 @@ var SessionContext = class {
|
|
|
1162
1383
|
}
|
|
1163
1384
|
}
|
|
1164
1385
|
}
|
|
1165
|
-
console.error(`Using cached user data for
|
|
1386
|
+
console.error(`Using cached user data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
1166
1387
|
return { cancelled: false, data: dataToReturn2 };
|
|
1167
1388
|
}
|
|
1168
|
-
console.error(`Prompting user for data for
|
|
1389
|
+
console.error(`Prompting user for data for ${sessionLogLabel(sessionId)}, key: ${options.cacheKey}`);
|
|
1169
1390
|
let result;
|
|
1170
1391
|
if (options.showLoginDialog) {
|
|
1171
1392
|
const { showLoginDialog: showLoginDialog2 } = await Promise.resolve().then(() => (init_ui_dialog(), ui_dialog_exports));
|
|
@@ -1367,10 +1588,11 @@ function wrapServerWithTracking(server2, createServerFn) {
|
|
|
1367
1588
|
newServer[reg.method](...reg.args);
|
|
1368
1589
|
}
|
|
1369
1590
|
}
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1591
|
+
const toolPolicy = typeof server2.getToolPolicy === "function" ? server2.getToolPolicy() : void 0;
|
|
1592
|
+
if (toolPolicy && typeof newServer.setToolPolicy === "function") {
|
|
1593
|
+
newServer.setToolPolicy(toolPolicy);
|
|
1594
|
+
if (typeof newServer.applyToolPolicy === "function") {
|
|
1595
|
+
newServer.applyToolPolicy();
|
|
1374
1596
|
}
|
|
1375
1597
|
}
|
|
1376
1598
|
return newServer;
|
|
@@ -1426,35 +1648,61 @@ var CPMcpServer = class extends McpServer {
|
|
|
1426
1648
|
console.error("[CPMcpServer] Setting tool policy callback");
|
|
1427
1649
|
this.toolPolicyCallback = callback;
|
|
1428
1650
|
}
|
|
1651
|
+
/**
|
|
1652
|
+
* Get the tool policy callback, if one was set.
|
|
1653
|
+
*
|
|
1654
|
+
* Needed so the policy can be carried onto the per-session server instances
|
|
1655
|
+
* created for HTTP transport. A typed accessor keeps that transfer honest:
|
|
1656
|
+
* callers do not have to reach into the private field, where a misspelling
|
|
1657
|
+
* would go unnoticed by the compiler.
|
|
1658
|
+
*/
|
|
1659
|
+
getToolPolicy() {
|
|
1660
|
+
return this.toolPolicyCallback;
|
|
1661
|
+
}
|
|
1429
1662
|
/**
|
|
1430
1663
|
* Apply the tool policy by checking all registered tools
|
|
1431
1664
|
* This should be called after all tools are registered but before connecting
|
|
1665
|
+
*
|
|
1666
|
+
* Per-tool tracing is behind the debug flag. This used to run once per process
|
|
1667
|
+
* on the template server, where a line per tool was a cheap startup banner.
|
|
1668
|
+
* It now also runs per session under HTTP transport, so unconditional tracing
|
|
1669
|
+
* would scale stderr with sessions x tools and bury the summary. The summary
|
|
1670
|
+
* line always prints — it is the fact worth having for every session.
|
|
1432
1671
|
*/
|
|
1433
1672
|
applyToolPolicy() {
|
|
1673
|
+
const verbose = SettingsManager.globalDebugState === true || SettingsManager.globalDebugState === "true";
|
|
1434
1674
|
if (!this.toolPolicyCallback) {
|
|
1435
|
-
|
|
1675
|
+
if (verbose) {
|
|
1676
|
+
console.error("[CPMcpServer] No tool policy callback set, allowing all tools");
|
|
1677
|
+
}
|
|
1436
1678
|
return;
|
|
1437
1679
|
}
|
|
1438
|
-
console.error("[CPMcpServer] Applying tool policy");
|
|
1439
1680
|
const registeredTools = this._registeredTools;
|
|
1440
1681
|
if (!registeredTools || typeof registeredTools !== "object") {
|
|
1441
1682
|
console.error("[CPMcpServer] No tools registered yet");
|
|
1442
1683
|
return;
|
|
1443
1684
|
}
|
|
1444
1685
|
const toolNames = Object.keys(registeredTools);
|
|
1445
|
-
|
|
1686
|
+
if (verbose) {
|
|
1687
|
+
console.error(`[CPMcpServer] Applying tool policy`);
|
|
1688
|
+
console.error(`[CPMcpServer] Found ${toolNames.length} registered tools:`, toolNames);
|
|
1689
|
+
}
|
|
1446
1690
|
let enabledCount = 0;
|
|
1447
1691
|
let disabledCount = 0;
|
|
1448
1692
|
for (const [toolName, tool] of Object.entries(registeredTools)) {
|
|
1449
1693
|
const isAllowed = this.toolPolicyCallback(toolName);
|
|
1450
1694
|
if (!isAllowed) {
|
|
1451
|
-
|
|
1695
|
+
if (verbose) {
|
|
1696
|
+
console.error(`[CPMcpServer] Tool '${toolName}' is NOT allowed by policy - disabling`);
|
|
1697
|
+
}
|
|
1452
1698
|
if (typeof tool.disable === "function") {
|
|
1453
1699
|
tool.disable();
|
|
1454
1700
|
disabledCount++;
|
|
1455
1701
|
}
|
|
1456
1702
|
} else {
|
|
1457
|
-
|
|
1703
|
+
if (verbose) {
|
|
1704
|
+
console.error(`[CPMcpServer] Tool '${toolName}' is allowed by policy`);
|
|
1705
|
+
}
|
|
1458
1706
|
enabledCount++;
|
|
1459
1707
|
}
|
|
1460
1708
|
}
|
|
@@ -1792,7 +2040,7 @@ function unwrapSingleton(data, where) {
|
|
|
1792
2040
|
}
|
|
1793
2041
|
|
|
1794
2042
|
// src/core/providers/avanan.ts
|
|
1795
|
-
import { createHash as
|
|
2043
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
1796
2044
|
var V1_PREFIX = "/v1.0";
|
|
1797
2045
|
var AUTH_PATH = "/v1.0/auth";
|
|
1798
2046
|
var REGION_HOSTS = {
|
|
@@ -1815,7 +2063,7 @@ function avananSignature(reqId, appId, date, secret, requestPath) {
|
|
|
1815
2063
|
if (requestPath !== null) parts.push(requestPath);
|
|
1816
2064
|
parts.push(secret);
|
|
1817
2065
|
const base64 = Buffer.from(parts.join(""), "utf8").toString("base64");
|
|
1818
|
-
return
|
|
2066
|
+
return createHash3("sha256").update(base64, "utf8").digest("hex");
|
|
1819
2067
|
}
|
|
1820
2068
|
function formatAvananDate(now) {
|
|
1821
2069
|
return `${now.toISOString().replace("Z", "")}000`;
|
|
@@ -2708,6 +2956,251 @@ function neverReachedUpstream(error) {
|
|
|
2708
2956
|
return code !== null && PRE_FLIGHT_ERROR_CODES.has(code);
|
|
2709
2957
|
}
|
|
2710
2958
|
|
|
2959
|
+
// src/tools/shared/schemas.ts
|
|
2960
|
+
import { z as z2 } from "zod";
|
|
2961
|
+
function orNull(value) {
|
|
2962
|
+
return value ?? null;
|
|
2963
|
+
}
|
|
2964
|
+
function compact(obj) {
|
|
2965
|
+
return Object.fromEntries(
|
|
2966
|
+
Object.entries(obj).filter(
|
|
2967
|
+
([, value]) => value !== null && value !== void 0
|
|
2968
|
+
)
|
|
2969
|
+
);
|
|
2970
|
+
}
|
|
2971
|
+
var looseString = z2.unknown().transform((v) => typeof v === "string" ? v : null);
|
|
2972
|
+
var looseRecord = z2.unknown().transform(
|
|
2973
|
+
(v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null
|
|
2974
|
+
);
|
|
2975
|
+
var SEVERITY_BY_DIGIT = {
|
|
2976
|
+
"1": "lowest",
|
|
2977
|
+
"2": "low",
|
|
2978
|
+
"3": "medium",
|
|
2979
|
+
"4": "high",
|
|
2980
|
+
"5": "critical"
|
|
2981
|
+
};
|
|
2982
|
+
function normalizeSeverity(value) {
|
|
2983
|
+
if (typeof value !== "string") return null;
|
|
2984
|
+
return SEVERITY_BY_DIGIT[value] ?? (value || null);
|
|
2985
|
+
}
|
|
2986
|
+
var eventSchema = z2.object({
|
|
2987
|
+
eventId: z2.unknown(),
|
|
2988
|
+
type: looseString,
|
|
2989
|
+
state: looseString,
|
|
2990
|
+
severity: z2.unknown(),
|
|
2991
|
+
saas: looseString,
|
|
2992
|
+
description: looseString,
|
|
2993
|
+
entityId: looseString,
|
|
2994
|
+
eventCreated: looseString,
|
|
2995
|
+
confidenceIndicator: looseString
|
|
2996
|
+
}).passthrough().transform((raw) => ({
|
|
2997
|
+
eventId: typeof raw.eventId === "string" ? raw.eventId : String(raw.eventId ?? ""),
|
|
2998
|
+
type: raw.type,
|
|
2999
|
+
state: raw.state,
|
|
3000
|
+
severity: normalizeSeverity(raw.severity),
|
|
3001
|
+
saas: raw.saas,
|
|
3002
|
+
description: raw.description,
|
|
3003
|
+
entityId: raw.entityId,
|
|
3004
|
+
eventCreated: raw.eventCreated,
|
|
3005
|
+
confidenceIndicator: raw.confidenceIndicator
|
|
3006
|
+
}));
|
|
3007
|
+
function toEvent(raw) {
|
|
3008
|
+
return eventSchema.parse(raw);
|
|
3009
|
+
}
|
|
3010
|
+
var sectoolResultSchema = z2.object({
|
|
3011
|
+
entityId: looseString,
|
|
3012
|
+
entityType: looseString,
|
|
3013
|
+
payload: looseRecord,
|
|
3014
|
+
score: looseString,
|
|
3015
|
+
securityResultEntityId: looseString,
|
|
3016
|
+
securityResultEntityType: looseString,
|
|
3017
|
+
statusCode: looseString,
|
|
3018
|
+
statusDescription: looseString,
|
|
3019
|
+
verdict: z2.unknown().transform((v) => typeof v === "string" ? v : "unknown")
|
|
3020
|
+
}).passthrough().transform((raw) => ({
|
|
3021
|
+
entityId: raw.entityId,
|
|
3022
|
+
entityType: raw.entityType,
|
|
3023
|
+
payload: raw.payload,
|
|
3024
|
+
score: raw.score,
|
|
3025
|
+
securityResultEntityId: raw.securityResultEntityId,
|
|
3026
|
+
securityResultEntityType: raw.securityResultEntityType,
|
|
3027
|
+
statusCode: raw.statusCode,
|
|
3028
|
+
statusDescription: raw.statusDescription,
|
|
3029
|
+
verdict: raw.verdict
|
|
3030
|
+
}));
|
|
3031
|
+
var engineResultsSchema = z2.array(sectoolResultSchema).nullish().transform((v) => orNull(v));
|
|
3032
|
+
var entitySecurityResultSchema = z2.object({
|
|
3033
|
+
combinedVerdict: looseRecord,
|
|
3034
|
+
ap: engineResultsSchema,
|
|
3035
|
+
dlp: engineResultsSchema,
|
|
3036
|
+
clicktimeProtection: engineResultsSchema,
|
|
3037
|
+
shadowIt: engineResultsSchema,
|
|
3038
|
+
av: engineResultsSchema
|
|
3039
|
+
}).passthrough().transform((raw) => ({
|
|
3040
|
+
combinedVerdict: raw.combinedVerdict,
|
|
3041
|
+
ap: raw.ap,
|
|
3042
|
+
dlp: raw.dlp,
|
|
3043
|
+
clicktimeProtection: raw.clicktimeProtection,
|
|
3044
|
+
shadowIt: raw.shadowIt,
|
|
3045
|
+
av: raw.av
|
|
3046
|
+
}));
|
|
3047
|
+
var entityActionSchema = z2.object({
|
|
3048
|
+
entityActionName: z2.string(),
|
|
3049
|
+
entityActionDate: looseString,
|
|
3050
|
+
entityActionResponseCode: looseString,
|
|
3051
|
+
entityActionResponseText: looseString,
|
|
3052
|
+
entityActionState: looseString
|
|
3053
|
+
}).passthrough().transform((raw) => ({
|
|
3054
|
+
entityActionName: raw.entityActionName,
|
|
3055
|
+
entityActionDate: raw.entityActionDate,
|
|
3056
|
+
entityActionResponseCode: raw.entityActionResponseCode,
|
|
3057
|
+
entityActionResponseText: raw.entityActionResponseText,
|
|
3058
|
+
entityActionState: raw.entityActionState
|
|
3059
|
+
}));
|
|
3060
|
+
var entityInfoSchema = z2.object({
|
|
3061
|
+
entityId: z2.string(),
|
|
3062
|
+
customerId: looseString,
|
|
3063
|
+
saas: looseString,
|
|
3064
|
+
saasEntityType: looseString,
|
|
3065
|
+
entityCreated: looseString,
|
|
3066
|
+
entityUpdated: looseString,
|
|
3067
|
+
entityActionState: looseString
|
|
3068
|
+
}).passthrough().transform((raw) => ({
|
|
3069
|
+
entityId: raw.entityId,
|
|
3070
|
+
customerId: raw.customerId,
|
|
3071
|
+
saas: raw.saas,
|
|
3072
|
+
saasEntityType: raw.saasEntityType,
|
|
3073
|
+
entityCreated: raw.entityCreated,
|
|
3074
|
+
entityUpdated: raw.entityUpdated,
|
|
3075
|
+
entityActionState: raw.entityActionState
|
|
3076
|
+
}));
|
|
3077
|
+
var entitySchema = z2.object({
|
|
3078
|
+
entityInfo: entityInfoSchema,
|
|
3079
|
+
saasInfo: looseRecord,
|
|
3080
|
+
entityPayload: looseRecord,
|
|
3081
|
+
entitySecurityResult: entitySecurityResultSchema.nullish().transform((v) => orNull(v)),
|
|
3082
|
+
entityActions: z2.array(entityActionSchema).nullish(),
|
|
3083
|
+
entityAvailableActions: z2.array(z2.string()).nullish()
|
|
3084
|
+
}).passthrough().transform((raw) => ({
|
|
3085
|
+
entityInfo: raw.entityInfo,
|
|
3086
|
+
saasInfo: raw.saasInfo,
|
|
3087
|
+
entityPayload: raw.entityPayload,
|
|
3088
|
+
entitySecurityResult: raw.entitySecurityResult,
|
|
3089
|
+
entityActions: raw.entityActions ?? [],
|
|
3090
|
+
entityAvailableActions: raw.entityAvailableActions ?? []
|
|
3091
|
+
}));
|
|
3092
|
+
function toEntity(raw) {
|
|
3093
|
+
return entitySchema.parse(raw);
|
|
3094
|
+
}
|
|
3095
|
+
function toEntitySummary(raw) {
|
|
3096
|
+
const {
|
|
3097
|
+
entityPayload: _payload,
|
|
3098
|
+
saasInfo: _saasInfo,
|
|
3099
|
+
...rest
|
|
3100
|
+
} = toEntity(raw);
|
|
3101
|
+
return rest;
|
|
3102
|
+
}
|
|
3103
|
+
var TASK_STATUSES = [
|
|
3104
|
+
"init",
|
|
3105
|
+
"inprogress",
|
|
3106
|
+
"completed",
|
|
3107
|
+
"failed",
|
|
3108
|
+
"stopped",
|
|
3109
|
+
"paused"
|
|
3110
|
+
];
|
|
3111
|
+
var taskSchema = z2.object({
|
|
3112
|
+
taskId: z2.string(),
|
|
3113
|
+
status: z2.enum(TASK_STATUSES),
|
|
3114
|
+
actor: looseString,
|
|
3115
|
+
startedAt: looseString,
|
|
3116
|
+
finishedAt: looseString
|
|
3117
|
+
}).passthrough().transform((raw) => ({
|
|
3118
|
+
taskId: raw.taskId,
|
|
3119
|
+
status: raw.status,
|
|
3120
|
+
actor: raw.actor,
|
|
3121
|
+
startedAt: raw.startedAt,
|
|
3122
|
+
finishedAt: raw.finishedAt
|
|
3123
|
+
}));
|
|
3124
|
+
function toTask(raw) {
|
|
3125
|
+
return taskSchema.parse(raw);
|
|
3126
|
+
}
|
|
3127
|
+
var EXCEPTION_TYPES = [
|
|
3128
|
+
"whitelist",
|
|
3129
|
+
"blacklist",
|
|
3130
|
+
"spam_whitelist"
|
|
3131
|
+
];
|
|
3132
|
+
var AP_EXCEPTION_CRITERIA = [
|
|
3133
|
+
["senderEmail", "senderEmailMatching"],
|
|
3134
|
+
["senderName", "senderNameMatching"],
|
|
3135
|
+
["senderDomain", "senderDomainMatching"],
|
|
3136
|
+
["senderIp", null],
|
|
3137
|
+
["senderClientIp", null],
|
|
3138
|
+
["recipient", "recipientMatching"],
|
|
3139
|
+
["domain", null],
|
|
3140
|
+
["linkDomains", "linkDomainMatching"],
|
|
3141
|
+
["subject", "subjectMatching"],
|
|
3142
|
+
["attachmentMd5", null]
|
|
3143
|
+
];
|
|
3144
|
+
var nonEmpty = (v) => typeof v === "string" && v !== "";
|
|
3145
|
+
function exceptionIdOf(row) {
|
|
3146
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) return null;
|
|
3147
|
+
const { id, entityId } = row;
|
|
3148
|
+
for (const v of [id, entityId]) {
|
|
3149
|
+
if (nonEmpty(v)) return v;
|
|
3150
|
+
if (typeof v === "number") return String(v);
|
|
3151
|
+
}
|
|
3152
|
+
return null;
|
|
3153
|
+
}
|
|
3154
|
+
function withExceptionId(raw) {
|
|
3155
|
+
const id = exceptionIdOf(raw);
|
|
3156
|
+
return id === null ? raw : { ...raw, id };
|
|
3157
|
+
}
|
|
3158
|
+
var apExceptionRowSchema = z2.preprocess(
|
|
3159
|
+
withExceptionId,
|
|
3160
|
+
z2.object({
|
|
3161
|
+
id: z2.string(),
|
|
3162
|
+
comment: looseString,
|
|
3163
|
+
actionNeeded: looseString,
|
|
3164
|
+
ignoringSpfCheck: z2.unknown().transform((v) => {
|
|
3165
|
+
if (typeof v === "boolean") return v;
|
|
3166
|
+
if (v === 1 || v === "true") return true;
|
|
3167
|
+
if (v === 0 || v === "false") return false;
|
|
3168
|
+
return null;
|
|
3169
|
+
}),
|
|
3170
|
+
editedBy: looseString,
|
|
3171
|
+
addedBy: looseString,
|
|
3172
|
+
updateTime: looseString
|
|
3173
|
+
}).passthrough()
|
|
3174
|
+
);
|
|
3175
|
+
function criteriaOf(row) {
|
|
3176
|
+
const match = {};
|
|
3177
|
+
for (const [field, modeField] of AP_EXCEPTION_CRITERIA) {
|
|
3178
|
+
const value = row[field];
|
|
3179
|
+
if (value === null || value === void 0 || value === "" || Array.isArray(value) && value.length === 0) {
|
|
3180
|
+
continue;
|
|
3181
|
+
}
|
|
3182
|
+
const mode = modeField ? row[modeField] : null;
|
|
3183
|
+
match[field] = {
|
|
3184
|
+
value,
|
|
3185
|
+
matching: typeof mode === "string" ? mode : null
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
return match;
|
|
3189
|
+
}
|
|
3190
|
+
function toApException(raw, type) {
|
|
3191
|
+
const row = apExceptionRowSchema.parse(raw);
|
|
3192
|
+
return {
|
|
3193
|
+
id: row.id,
|
|
3194
|
+
type,
|
|
3195
|
+
match: criteriaOf(row),
|
|
3196
|
+
comment: row.comment,
|
|
3197
|
+
actionNeeded: row.actionNeeded,
|
|
3198
|
+
ignoringSpfCheck: row.ignoringSpfCheck,
|
|
3199
|
+
actor: nonEmpty(row.editedBy) ? row.editedBy : row.addedBy,
|
|
3200
|
+
updatedAt: row.updateTime
|
|
3201
|
+
};
|
|
3202
|
+
}
|
|
3203
|
+
|
|
2711
3204
|
// src/check.ts
|
|
2712
3205
|
function maskId(value) {
|
|
2713
3206
|
return value.length <= 8 ? `${value.slice(0, 2)}\u2026` : `${value.slice(0, 6)}\u2026`;
|
|
@@ -2732,8 +3225,8 @@ function firstExceptionId(whitelist, blacklist) {
|
|
|
2732
3225
|
["blacklist", blacklist]
|
|
2733
3226
|
];
|
|
2734
3227
|
for (const [excType, rows] of candidates) {
|
|
2735
|
-
const value = rows?.[0]
|
|
2736
|
-
if (
|
|
3228
|
+
const value = exceptionIdOf(rows?.[0]);
|
|
3229
|
+
if (value !== null) return [excType, value];
|
|
2737
3230
|
}
|
|
2738
3231
|
return [null, null];
|
|
2739
3232
|
}
|
|
@@ -3061,7 +3554,7 @@ query tools.
|
|
|
3061
3554
|
`;
|
|
3062
3555
|
|
|
3063
3556
|
// src/prompts/index.ts
|
|
3064
|
-
import { z as
|
|
3557
|
+
import { z as z4 } from "zod";
|
|
3065
3558
|
|
|
3066
3559
|
// src/content/glossary.ts
|
|
3067
3560
|
var GLOSSARY = {
|
|
@@ -3435,7 +3928,7 @@ var GLOSSARY = {
|
|
|
3435
3928
|
};
|
|
3436
3929
|
|
|
3437
3930
|
// src/tools/shared/result.ts
|
|
3438
|
-
import { z as
|
|
3931
|
+
import { z as z3 } from "zod";
|
|
3439
3932
|
function jsonResult(payload) {
|
|
3440
3933
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
3441
3934
|
}
|
|
@@ -3449,7 +3942,7 @@ function errorResult(tool, error) {
|
|
|
3449
3942
|
isError: true
|
|
3450
3943
|
};
|
|
3451
3944
|
}
|
|
3452
|
-
if (error instanceof
|
|
3945
|
+
if (error instanceof z3.ZodError) {
|
|
3453
3946
|
const detail = error.issues.map(
|
|
3454
3947
|
(issue) => `${issue.path.join(".") || "input"}: ${issue.message}`
|
|
3455
3948
|
).join("; ");
|
|
@@ -3739,7 +4232,7 @@ function registerPrompts(server2) {
|
|
|
3739
4232
|
"security_activity_summary",
|
|
3740
4233
|
ACTIVITY_DESCRIPTION,
|
|
3741
4234
|
{
|
|
3742
|
-
time_window:
|
|
4235
|
+
time_window: z4.string().optional().describe(
|
|
3743
4236
|
'Rolling window, e.g. "last 24 hours" or "this week".'
|
|
3744
4237
|
)
|
|
3745
4238
|
},
|
|
@@ -3752,8 +4245,8 @@ function registerPrompts(server2) {
|
|
|
3752
4245
|
{
|
|
3753
4246
|
// Deliberately free-form, so model-invented synonyms ("open",
|
|
3754
4247
|
// "active") still land on the pending branch.
|
|
3755
|
-
mode:
|
|
3756
|
-
time_window:
|
|
4248
|
+
mode: z4.string().optional().describe("pending, resolved, or trend."),
|
|
4249
|
+
time_window: z4.string().optional().describe("Rolling window for the resolved and trend modes.")
|
|
3757
4250
|
},
|
|
3758
4251
|
(args) => promptMessage(
|
|
3759
4252
|
restoreTemplate(
|
|
@@ -3767,7 +4260,7 @@ function registerPrompts(server2) {
|
|
|
3767
4260
|
"single_email_investigation",
|
|
3768
4261
|
SINGLE_DESCRIPTION,
|
|
3769
4262
|
{
|
|
3770
|
-
entity_id:
|
|
4263
|
+
entity_id: z4.string().describe("The HEC entity id to investigate.")
|
|
3771
4264
|
},
|
|
3772
4265
|
(args) => promptMessage(singleTemplate(args.entity_id ?? ""))
|
|
3773
4266
|
);
|
|
@@ -3854,48 +4347,19 @@ function firstOf(...values) {
|
|
|
3854
4347
|
return values.find((v) => v !== void 0 && v !== "");
|
|
3855
4348
|
}
|
|
3856
4349
|
var Settings = class _Settings {
|
|
4350
|
+
// Takes only what it is given; fromArgs reads the environment.
|
|
3857
4351
|
constructor({
|
|
3858
|
-
domain
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
),
|
|
3870
|
-
authMethod = firstOf(
|
|
3871
|
-
process.env.HEC_AUTH_METHOD,
|
|
3872
|
-
process.env.SMARTAPI_MCP_AUTH_METHOD
|
|
3873
|
-
),
|
|
3874
|
-
region = firstOf(
|
|
3875
|
-
process.env.HEC_REGION,
|
|
3876
|
-
process.env.SMARTAPI_MCP_REGION
|
|
3877
|
-
),
|
|
3878
|
-
scope = firstOf(process.env.HEC_SCOPE, process.env.SMARTAPI_MCP_SCOPE),
|
|
3879
|
-
requestTimeout = firstOf(
|
|
3880
|
-
process.env.HEC_REQUEST_TIMEOUT,
|
|
3881
|
-
process.env.SMARTAPI_MCP_REQUEST_TIMEOUT
|
|
3882
|
-
),
|
|
3883
|
-
maxRetries = firstOf(
|
|
3884
|
-
process.env.HEC_MAX_RETRIES,
|
|
3885
|
-
process.env.SMARTAPI_MCP_MAX_RETRIES
|
|
3886
|
-
),
|
|
3887
|
-
retryBaseSeconds = firstOf(
|
|
3888
|
-
process.env.HEC_RETRY_BASE_SECONDS,
|
|
3889
|
-
process.env.SMARTAPI_MCP_RETRY_BASE_SECONDS
|
|
3890
|
-
),
|
|
3891
|
-
maxConcurrency = firstOf(
|
|
3892
|
-
process.env.HEC_MAX_CONCURRENCY,
|
|
3893
|
-
process.env.SMARTAPI_MCP_MAX_CONCURRENCY
|
|
3894
|
-
),
|
|
3895
|
-
actionBatchLimit = firstOf(
|
|
3896
|
-
process.env.HEC_ACTION_BATCH_LIMIT,
|
|
3897
|
-
process.env.SMARTAPI_MCP_ACTION_BATCH_LIMIT
|
|
3898
|
-
)
|
|
4352
|
+
domain,
|
|
4353
|
+
clientId,
|
|
4354
|
+
secret,
|
|
4355
|
+
authMethod,
|
|
4356
|
+
region,
|
|
4357
|
+
scope,
|
|
4358
|
+
requestTimeout,
|
|
4359
|
+
maxRetries,
|
|
4360
|
+
retryBaseSeconds,
|
|
4361
|
+
maxConcurrency,
|
|
4362
|
+
actionBatchLimit
|
|
3899
4363
|
} = {}) {
|
|
3900
4364
|
this.domain = "";
|
|
3901
4365
|
this.clientId = "";
|
|
@@ -3920,6 +4384,67 @@ var Settings = class _Settings {
|
|
|
3920
4384
|
"actionBatchLimit"
|
|
3921
4385
|
);
|
|
3922
4386
|
}
|
|
4387
|
+
static {
|
|
4388
|
+
/**
|
|
4389
|
+
* Keys whose values debug output may print (see debugView in mcp-utils).
|
|
4390
|
+
* Anything not listed, including every credential, is shown hidden.
|
|
4391
|
+
* Lists both the header/CLI names (hec-*) and the property names.
|
|
4392
|
+
*/
|
|
4393
|
+
this.debugLoggableKeys = [
|
|
4394
|
+
"hec-domain",
|
|
4395
|
+
"domain",
|
|
4396
|
+
"hec-region",
|
|
4397
|
+
"region",
|
|
4398
|
+
"hec-scope",
|
|
4399
|
+
"scope",
|
|
4400
|
+
"hec-auth-method",
|
|
4401
|
+
"auth-method",
|
|
4402
|
+
"hec-request-timeout",
|
|
4403
|
+
"request-timeout",
|
|
4404
|
+
"hec-max-retries",
|
|
4405
|
+
"max-retries",
|
|
4406
|
+
"hec-retry-base-seconds",
|
|
4407
|
+
"retry-base-seconds",
|
|
4408
|
+
"hec-max-concurrency",
|
|
4409
|
+
"max-concurrency",
|
|
4410
|
+
"hec-action-batch-limit",
|
|
4411
|
+
"action-batch-limit"
|
|
4412
|
+
];
|
|
4413
|
+
}
|
|
4414
|
+
static {
|
|
4415
|
+
/**
|
|
4416
|
+
* Headers an HTTP session may mix with the operator's values (see
|
|
4417
|
+
* connection-source in mcp-utils): the numeric tunables, which are
|
|
4418
|
+
* deployment-wide rather than per tenant, under both spellings.
|
|
4419
|
+
*/
|
|
4420
|
+
this.basicKeys = [
|
|
4421
|
+
"HEC-REQUEST-TIMEOUT",
|
|
4422
|
+
"HEC-MAX-RETRIES",
|
|
4423
|
+
"HEC-RETRY-BASE-SECONDS",
|
|
4424
|
+
"HEC-MAX-CONCURRENCY",
|
|
4425
|
+
"HEC-ACTION-BATCH-LIMIT"
|
|
4426
|
+
];
|
|
4427
|
+
}
|
|
4428
|
+
static {
|
|
4429
|
+
/**
|
|
4430
|
+
* The Python server's names for the tunables (alias -> canonical), so a
|
|
4431
|
+
* caller's SMARTAPI-MCP-* header overrides the operator's HEC_* value.
|
|
4432
|
+
*/
|
|
4433
|
+
this.headerAliases = {
|
|
4434
|
+
"SMARTAPI-MCP-REQUEST-TIMEOUT": "HEC-REQUEST-TIMEOUT",
|
|
4435
|
+
"SMARTAPI-MCP-MAX-RETRIES": "HEC-MAX-RETRIES",
|
|
4436
|
+
"SMARTAPI-MCP-RETRY-BASE-SECONDS": "HEC-RETRY-BASE-SECONDS",
|
|
4437
|
+
"SMARTAPI-MCP-MAX-CONCURRENCY": "HEC-MAX-CONCURRENCY",
|
|
4438
|
+
"SMARTAPI-MCP-ACTION-BATCH-LIMIT": "HEC-ACTION-BATCH-LIMIT"
|
|
4439
|
+
};
|
|
4440
|
+
}
|
|
4441
|
+
static {
|
|
4442
|
+
/**
|
|
4443
|
+
* An HTTP session never uses the operator's tenant: a client must not be
|
|
4444
|
+
* able to act as whichever tenant the operator configured.
|
|
4445
|
+
*/
|
|
4446
|
+
this.operatorSettingsOverHttp = false;
|
|
4447
|
+
}
|
|
3923
4448
|
/**
|
|
3924
4449
|
* Under HTTP transport credentials arrive per request as headers, so the
|
|
3925
4450
|
* process starts with none and validating at boot would be wrong.
|
|
@@ -3936,30 +4461,27 @@ var Settings = class _Settings {
|
|
|
3936
4461
|
return true;
|
|
3937
4462
|
}
|
|
3938
4463
|
static fromArgs(options) {
|
|
4464
|
+
const env = process.env;
|
|
3939
4465
|
return new _Settings({
|
|
3940
|
-
domain: options.hecDomain,
|
|
3941
|
-
clientId: options.hecClientId,
|
|
3942
|
-
secret: options.hecSecret,
|
|
3943
|
-
authMethod: options.hecAuthMethod,
|
|
3944
|
-
region: options.hecRegion,
|
|
3945
|
-
scope: options.hecScope,
|
|
3946
|
-
requestTimeout: options.hecRequestTimeout,
|
|
3947
|
-
maxRetries: options.hecMaxRetries,
|
|
3948
|
-
retryBaseSeconds: options.hecRetryBaseSeconds,
|
|
3949
|
-
maxConcurrency: options.hecMaxConcurrency,
|
|
3950
|
-
actionBatchLimit: options.hecActionBatchLimit
|
|
4466
|
+
domain: options.hecDomain ?? firstOf(env.HEC_DOMAIN, env.SMARTAPI_MCP_DOMAIN),
|
|
4467
|
+
clientId: options.hecClientId ?? firstOf(env.HEC_CLIENT_ID, env.SMARTAPI_MCP_CLIENT_ID),
|
|
4468
|
+
secret: options.hecSecret ?? firstOf(env.HEC_SECRET, env.SMARTAPI_MCP_SECRET),
|
|
4469
|
+
authMethod: options.hecAuthMethod ?? firstOf(env.HEC_AUTH_METHOD, env.SMARTAPI_MCP_AUTH_METHOD),
|
|
4470
|
+
region: options.hecRegion ?? firstOf(env.HEC_REGION, env.SMARTAPI_MCP_REGION),
|
|
4471
|
+
scope: options.hecScope ?? firstOf(env.HEC_SCOPE, env.SMARTAPI_MCP_SCOPE),
|
|
4472
|
+
requestTimeout: options.hecRequestTimeout ?? firstOf(env.HEC_REQUEST_TIMEOUT, env.SMARTAPI_MCP_REQUEST_TIMEOUT),
|
|
4473
|
+
maxRetries: options.hecMaxRetries ?? firstOf(env.HEC_MAX_RETRIES, env.SMARTAPI_MCP_MAX_RETRIES),
|
|
4474
|
+
retryBaseSeconds: options.hecRetryBaseSeconds ?? firstOf(env.HEC_RETRY_BASE_SECONDS, env.SMARTAPI_MCP_RETRY_BASE_SECONDS),
|
|
4475
|
+
maxConcurrency: options.hecMaxConcurrency ?? firstOf(env.HEC_MAX_CONCURRENCY, env.SMARTAPI_MCP_MAX_CONCURRENCY),
|
|
4476
|
+
actionBatchLimit: options.hecActionBatchLimit ?? firstOf(env.HEC_ACTION_BATCH_LIMIT, env.SMARTAPI_MCP_ACTION_BATCH_LIMIT)
|
|
3951
4477
|
});
|
|
3952
4478
|
}
|
|
3953
4479
|
/**
|
|
3954
|
-
* Per-request settings, built from headers alone.
|
|
3955
|
-
*
|
|
3956
|
-
*
|
|
3957
|
-
*
|
|
3958
|
-
*
|
|
3959
|
-
* with no credentials inherit the server process's own tenant and act as
|
|
3960
|
-
* it, so the empty string is what makes a header-less request fail closed.
|
|
3961
|
-
* The numeric tunables are deployment-wide, not per tenant, so they keep
|
|
3962
|
-
* their defaults.
|
|
4480
|
+
* Per-request settings, built from headers alone. A missing tenant-scoped
|
|
4481
|
+
* header leaves its field empty, so a request without credentials fails
|
|
4482
|
+
* closed. The numeric tunables are deployment-wide, not per tenant: they
|
|
4483
|
+
* are basic keys, so the operator's values apply when the caller sends
|
|
4484
|
+
* none.
|
|
3963
4485
|
*/
|
|
3964
4486
|
static fromHeaders(headers) {
|
|
3965
4487
|
return new _Settings({
|
|
@@ -3969,11 +4491,26 @@ var Settings = class _Settings {
|
|
|
3969
4491
|
authMethod: getHeaderValue(headers, "HEC-AUTH-METHOD") ?? "",
|
|
3970
4492
|
region: getHeaderValue(headers, "HEC-REGION") ?? "",
|
|
3971
4493
|
scope: getHeaderValue(headers, "HEC-SCOPE") ?? "",
|
|
3972
|
-
requestTimeout:
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
4494
|
+
requestTimeout: firstOf(
|
|
4495
|
+
getHeaderValue(headers, "HEC-REQUEST-TIMEOUT"),
|
|
4496
|
+
getHeaderValue(headers, "SMARTAPI-MCP-REQUEST-TIMEOUT")
|
|
4497
|
+
),
|
|
4498
|
+
maxRetries: firstOf(
|
|
4499
|
+
getHeaderValue(headers, "HEC-MAX-RETRIES"),
|
|
4500
|
+
getHeaderValue(headers, "SMARTAPI-MCP-MAX-RETRIES")
|
|
4501
|
+
),
|
|
4502
|
+
retryBaseSeconds: firstOf(
|
|
4503
|
+
getHeaderValue(headers, "HEC-RETRY-BASE-SECONDS"),
|
|
4504
|
+
getHeaderValue(headers, "SMARTAPI-MCP-RETRY-BASE-SECONDS")
|
|
4505
|
+
),
|
|
4506
|
+
maxConcurrency: firstOf(
|
|
4507
|
+
getHeaderValue(headers, "HEC-MAX-CONCURRENCY"),
|
|
4508
|
+
getHeaderValue(headers, "SMARTAPI-MCP-MAX-CONCURRENCY")
|
|
4509
|
+
),
|
|
4510
|
+
actionBatchLimit: firstOf(
|
|
4511
|
+
getHeaderValue(headers, "HEC-ACTION-BATCH-LIMIT"),
|
|
4512
|
+
getHeaderValue(headers, "SMARTAPI-MCP-ACTION-BATCH-LIMIT")
|
|
4513
|
+
)
|
|
3977
4514
|
});
|
|
3978
4515
|
}
|
|
3979
4516
|
};
|
|
@@ -3981,198 +4518,6 @@ var Settings = class _Settings {
|
|
|
3981
4518
|
// src/tools/actions.ts
|
|
3982
4519
|
import { z as z5 } from "zod";
|
|
3983
4520
|
|
|
3984
|
-
// src/tools/shared/schemas.ts
|
|
3985
|
-
import { z as z4 } from "zod";
|
|
3986
|
-
function orNull(value) {
|
|
3987
|
-
return value ?? null;
|
|
3988
|
-
}
|
|
3989
|
-
function compact(obj) {
|
|
3990
|
-
return Object.fromEntries(
|
|
3991
|
-
Object.entries(obj).filter(
|
|
3992
|
-
([, value]) => value !== null && value !== void 0
|
|
3993
|
-
)
|
|
3994
|
-
);
|
|
3995
|
-
}
|
|
3996
|
-
var looseString = z4.unknown().transform((v) => typeof v === "string" ? v : null);
|
|
3997
|
-
var looseRecord = z4.unknown().transform(
|
|
3998
|
-
(v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : null
|
|
3999
|
-
);
|
|
4000
|
-
var SEVERITY_BY_DIGIT = {
|
|
4001
|
-
"1": "lowest",
|
|
4002
|
-
"2": "low",
|
|
4003
|
-
"3": "medium",
|
|
4004
|
-
"4": "high",
|
|
4005
|
-
"5": "critical"
|
|
4006
|
-
};
|
|
4007
|
-
function normalizeSeverity(value) {
|
|
4008
|
-
if (typeof value !== "string") return null;
|
|
4009
|
-
return SEVERITY_BY_DIGIT[value] ?? (value || null);
|
|
4010
|
-
}
|
|
4011
|
-
var eventSchema = z4.object({
|
|
4012
|
-
eventId: z4.unknown(),
|
|
4013
|
-
type: looseString,
|
|
4014
|
-
state: looseString,
|
|
4015
|
-
severity: z4.unknown(),
|
|
4016
|
-
saas: looseString,
|
|
4017
|
-
description: looseString,
|
|
4018
|
-
entityId: looseString,
|
|
4019
|
-
eventCreated: looseString,
|
|
4020
|
-
confidenceIndicator: looseString
|
|
4021
|
-
}).passthrough().transform((raw) => ({
|
|
4022
|
-
eventId: typeof raw.eventId === "string" ? raw.eventId : String(raw.eventId ?? ""),
|
|
4023
|
-
type: raw.type,
|
|
4024
|
-
state: raw.state,
|
|
4025
|
-
severity: normalizeSeverity(raw.severity),
|
|
4026
|
-
saas: raw.saas,
|
|
4027
|
-
description: raw.description,
|
|
4028
|
-
entityId: raw.entityId,
|
|
4029
|
-
eventCreated: raw.eventCreated,
|
|
4030
|
-
confidenceIndicator: raw.confidenceIndicator
|
|
4031
|
-
}));
|
|
4032
|
-
function toEvent(raw) {
|
|
4033
|
-
return eventSchema.parse(raw);
|
|
4034
|
-
}
|
|
4035
|
-
var sectoolResultSchema = z4.object({
|
|
4036
|
-
entityId: looseString,
|
|
4037
|
-
entityType: looseString,
|
|
4038
|
-
payload: looseRecord,
|
|
4039
|
-
score: looseString,
|
|
4040
|
-
securityResultEntityId: looseString,
|
|
4041
|
-
securityResultEntityType: looseString,
|
|
4042
|
-
statusCode: looseString,
|
|
4043
|
-
statusDescription: looseString,
|
|
4044
|
-
verdict: z4.unknown().transform((v) => typeof v === "string" ? v : "unknown")
|
|
4045
|
-
}).passthrough().transform((raw) => ({
|
|
4046
|
-
entityId: raw.entityId,
|
|
4047
|
-
entityType: raw.entityType,
|
|
4048
|
-
payload: raw.payload,
|
|
4049
|
-
score: raw.score,
|
|
4050
|
-
securityResultEntityId: raw.securityResultEntityId,
|
|
4051
|
-
securityResultEntityType: raw.securityResultEntityType,
|
|
4052
|
-
statusCode: raw.statusCode,
|
|
4053
|
-
statusDescription: raw.statusDescription,
|
|
4054
|
-
verdict: raw.verdict
|
|
4055
|
-
}));
|
|
4056
|
-
var engineResultsSchema = z4.array(sectoolResultSchema).nullish().transform((v) => orNull(v));
|
|
4057
|
-
var entitySecurityResultSchema = z4.object({
|
|
4058
|
-
combinedVerdict: looseRecord,
|
|
4059
|
-
ap: engineResultsSchema,
|
|
4060
|
-
dlp: engineResultsSchema,
|
|
4061
|
-
clicktimeProtection: engineResultsSchema,
|
|
4062
|
-
shadowIt: engineResultsSchema,
|
|
4063
|
-
av: engineResultsSchema
|
|
4064
|
-
}).passthrough().transform((raw) => ({
|
|
4065
|
-
combinedVerdict: raw.combinedVerdict,
|
|
4066
|
-
ap: raw.ap,
|
|
4067
|
-
dlp: raw.dlp,
|
|
4068
|
-
clicktimeProtection: raw.clicktimeProtection,
|
|
4069
|
-
shadowIt: raw.shadowIt,
|
|
4070
|
-
av: raw.av
|
|
4071
|
-
}));
|
|
4072
|
-
var entityActionSchema = z4.object({
|
|
4073
|
-
entityActionName: z4.string(),
|
|
4074
|
-
entityActionDate: looseString,
|
|
4075
|
-
entityActionResponseCode: looseString,
|
|
4076
|
-
entityActionResponseText: looseString,
|
|
4077
|
-
entityActionState: looseString
|
|
4078
|
-
}).passthrough().transform((raw) => ({
|
|
4079
|
-
entityActionName: raw.entityActionName,
|
|
4080
|
-
entityActionDate: raw.entityActionDate,
|
|
4081
|
-
entityActionResponseCode: raw.entityActionResponseCode,
|
|
4082
|
-
entityActionResponseText: raw.entityActionResponseText,
|
|
4083
|
-
entityActionState: raw.entityActionState
|
|
4084
|
-
}));
|
|
4085
|
-
var entityInfoSchema = z4.object({
|
|
4086
|
-
entityId: z4.string(),
|
|
4087
|
-
customerId: looseString,
|
|
4088
|
-
saas: looseString,
|
|
4089
|
-
saasEntityType: looseString,
|
|
4090
|
-
entityCreated: looseString,
|
|
4091
|
-
entityUpdated: looseString,
|
|
4092
|
-
entityActionState: looseString
|
|
4093
|
-
}).passthrough().transform((raw) => ({
|
|
4094
|
-
entityId: raw.entityId,
|
|
4095
|
-
customerId: raw.customerId,
|
|
4096
|
-
saas: raw.saas,
|
|
4097
|
-
saasEntityType: raw.saasEntityType,
|
|
4098
|
-
entityCreated: raw.entityCreated,
|
|
4099
|
-
entityUpdated: raw.entityUpdated,
|
|
4100
|
-
entityActionState: raw.entityActionState
|
|
4101
|
-
}));
|
|
4102
|
-
var entitySchema = z4.object({
|
|
4103
|
-
entityInfo: entityInfoSchema,
|
|
4104
|
-
saasInfo: looseRecord,
|
|
4105
|
-
entityPayload: looseRecord,
|
|
4106
|
-
entitySecurityResult: entitySecurityResultSchema.nullish().transform((v) => orNull(v)),
|
|
4107
|
-
entityActions: z4.array(entityActionSchema).nullish(),
|
|
4108
|
-
entityAvailableActions: z4.array(z4.string()).nullish()
|
|
4109
|
-
}).passthrough().transform((raw) => ({
|
|
4110
|
-
entityInfo: raw.entityInfo,
|
|
4111
|
-
saasInfo: raw.saasInfo,
|
|
4112
|
-
entityPayload: raw.entityPayload,
|
|
4113
|
-
entitySecurityResult: raw.entitySecurityResult,
|
|
4114
|
-
entityActions: raw.entityActions ?? [],
|
|
4115
|
-
entityAvailableActions: raw.entityAvailableActions ?? []
|
|
4116
|
-
}));
|
|
4117
|
-
function toEntity(raw) {
|
|
4118
|
-
return entitySchema.parse(raw);
|
|
4119
|
-
}
|
|
4120
|
-
function toEntitySummary(raw) {
|
|
4121
|
-
const {
|
|
4122
|
-
entityPayload: _payload,
|
|
4123
|
-
saasInfo: _saasInfo,
|
|
4124
|
-
...rest
|
|
4125
|
-
} = toEntity(raw);
|
|
4126
|
-
return rest;
|
|
4127
|
-
}
|
|
4128
|
-
var TASK_STATUSES = [
|
|
4129
|
-
"init",
|
|
4130
|
-
"inprogress",
|
|
4131
|
-
"completed",
|
|
4132
|
-
"failed",
|
|
4133
|
-
"stopped",
|
|
4134
|
-
"paused"
|
|
4135
|
-
];
|
|
4136
|
-
var taskSchema = z4.object({
|
|
4137
|
-
taskId: z4.string(),
|
|
4138
|
-
status: z4.enum(TASK_STATUSES),
|
|
4139
|
-
actor: looseString,
|
|
4140
|
-
startedAt: looseString,
|
|
4141
|
-
finishedAt: looseString
|
|
4142
|
-
}).passthrough().transform((raw) => ({
|
|
4143
|
-
taskId: raw.taskId,
|
|
4144
|
-
status: raw.status,
|
|
4145
|
-
actor: raw.actor,
|
|
4146
|
-
startedAt: raw.startedAt,
|
|
4147
|
-
finishedAt: raw.finishedAt
|
|
4148
|
-
}));
|
|
4149
|
-
function toTask(raw) {
|
|
4150
|
-
return taskSchema.parse(raw);
|
|
4151
|
-
}
|
|
4152
|
-
var EXCEPTION_TYPES = [
|
|
4153
|
-
"whitelist",
|
|
4154
|
-
"blacklist",
|
|
4155
|
-
"spam_whitelist"
|
|
4156
|
-
];
|
|
4157
|
-
var apExceptionSchema = z4.object({
|
|
4158
|
-
id: z4.string(),
|
|
4159
|
-
type: z4.enum(EXCEPTION_TYPES).nullish().transform((v) => orNull(v)),
|
|
4160
|
-
value: looseString,
|
|
4161
|
-
actor: looseString,
|
|
4162
|
-
createdAt: looseString,
|
|
4163
|
-
updatedAt: looseString
|
|
4164
|
-
}).passthrough().transform((raw) => ({
|
|
4165
|
-
id: raw.id,
|
|
4166
|
-
type: raw.type,
|
|
4167
|
-
value: raw.value,
|
|
4168
|
-
actor: raw.actor,
|
|
4169
|
-
createdAt: raw.createdAt,
|
|
4170
|
-
updatedAt: raw.updatedAt
|
|
4171
|
-
}));
|
|
4172
|
-
function toApException(raw) {
|
|
4173
|
-
return apExceptionSchema.parse(raw);
|
|
4174
|
-
}
|
|
4175
|
-
|
|
4176
4521
|
// src/tools/shared/session.ts
|
|
4177
4522
|
function apiFor(serverModule2, extra) {
|
|
4178
4523
|
return SessionContext.getAPIManager(
|
|
@@ -5241,6 +5586,7 @@ WHEN TO USE:
|
|
|
5241
5586
|
PURPOSE:
|
|
5242
5587
|
- \`whitelist\` always allows, \`blacklist\` always blocks, \`spam_whitelist\` allows through the spam filter only
|
|
5243
5588
|
- Each entry can match by sender email, domain or IP, recipient, subject, link domain, or attachment hash
|
|
5589
|
+
- Each entry returns \`id\`, \`type\`, \`match\` (only the criteria that are set, each as {value, matching}; matching is exact, contains, endswith...), \`comment\`, \`actionNeeded\` (the verdict the entry applies, e.g. phishing), \`ignoringSpfCheck\`, \`actor\` (who last edited it) and \`updatedAt\`
|
|
5244
5590
|
- Read-only`;
|
|
5245
5591
|
var GET_DESCRIPTION = `Fetch one Anti-Phishing exception entry by id.
|
|
5246
5592
|
|
|
@@ -5248,7 +5594,8 @@ WHEN TO USE:
|
|
|
5248
5594
|
- Drilling into a specific entry surfaced by \`list_ap_exceptions\`
|
|
5249
5595
|
|
|
5250
5596
|
PURPOSE:
|
|
5251
|
-
- \`exc_id\` is the entry id from \`list_ap_exceptions\`; \`exc_type\` must match the list it came from
|
|
5597
|
+
- \`exc_id\` is the entry \`id\` from \`list_ap_exceptions\`; \`exc_type\` must match the list it came from
|
|
5598
|
+
- Returns the same fields as a \`list_ap_exceptions\` entry
|
|
5252
5599
|
- Read-only`;
|
|
5253
5600
|
var excTypeSchema = z11.enum(EXCEPTION_TYPES).describe(
|
|
5254
5601
|
"Which exception list to read: whitelist, blacklist or spam_whitelist."
|
|
@@ -5266,7 +5613,11 @@ function registerExceptionTools(server2, serverModule2) {
|
|
|
5266
5613
|
args.exc_type,
|
|
5267
5614
|
args.scope
|
|
5268
5615
|
);
|
|
5269
|
-
return {
|
|
5616
|
+
return {
|
|
5617
|
+
exceptions: rows.map(
|
|
5618
|
+
(row) => toApException(row, args.exc_type)
|
|
5619
|
+
)
|
|
5620
|
+
};
|
|
5270
5621
|
})
|
|
5271
5622
|
);
|
|
5272
5623
|
registerTool(
|
|
@@ -5285,7 +5636,8 @@ function registerExceptionTools(server2, serverModule2) {
|
|
|
5285
5636
|
args.exc_type,
|
|
5286
5637
|
args.exc_id,
|
|
5287
5638
|
args.scope
|
|
5288
|
-
)
|
|
5639
|
+
),
|
|
5640
|
+
args.exc_type
|
|
5289
5641
|
);
|
|
5290
5642
|
})
|
|
5291
5643
|
);
|