@jupiterone/jupiterone-mcp
Version:
Model Context Protocol server for JupiterOne account rules and rule details
103 lines • 3.41 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.redactJ1ql = redactJ1ql;
exports.truncateReason = truncateReason;
exports.summarizeInput = summarizeInput;
exports.summarizeResult = summarizeResult;
/**
* Redacts string literals in a J1QL query, preserving structure (entity types, operators,
* property names) so query *shape* is captured for usage analytics without literal values.
*
* Ported from query-engine's `redactCypher` (sdk-graph/src/cypher/redact.ts), adapted for J1QL
* (single- and double-quoted literals). The patterns span escaped quotes (`\'` / `\"`) so a
* literal is always replaced in full; imperfect boundaries only ever over-redact, never leak.
*/
function redactJ1ql(query) {
return query
.replace(/'(?:[^'\\]|\\.)*'/g, "'[REDACTED]'")
.replace(/"(?:[^"\\]|\\.)*"/g, '"[REDACTED]"');
}
const REASON_MAX = 500;
function truncateReason(reason) {
return reason.length > REASON_MAX ? `${reason.slice(0, REASON_MAX)}…` : reason;
}
// Allowlist of scalar inputs safe to log verbatim. Everything not listed is dropped (default-deny),
// which keeps sensitive payloads out: action headers/endpoints/recipients/body, integration config,
// templates, J1QL variables/flags/scopeFilters, rule operations, and the raw widget input.
const SAFE_INPUT_KEYS = [
'ruleId',
'dashboardId',
'integrationJobId',
'integrationInstanceId',
'jobId',
'definitionId',
'rawDataKey',
'limit',
'size',
'pollingInterval',
'type',
'status',
'name',
'timestamp',
'beginTimestamp',
'endTimestamp',
'tag',
'includeConfig',
'includeDeleted',
];
/** Allowlisted, sanitized summary of tool inputs for usage telemetry. */
function summarizeInput(params) {
const out = {};
for (const key of SAFE_INPUT_KEYS) {
if (params[key] !== undefined)
out[key] = params[key];
}
if (typeof params.query === 'string')
out.query = redactJ1ql(params.query);
// The cursor is an opaque pagination token — record only that paging was requested.
if (params.cursor !== undefined)
out.hasCursor = true;
return out;
}
const COLLECTION_KEYS = [
'data',
'rules',
'instances',
'jobs',
'definitions',
'events',
'evaluations',
'activeAlerts',
'dashboards',
];
/** Result metadata (counts, pagination, status) derived from the structured payload. */
function summarizeResult(result) {
const out = { isError: !!result.isError };
const sc = result.structuredContent;
if (!sc || typeof sc !== 'object' || Array.isArray(sc))
return out;
const obj = sc;
if (typeof obj.status === 'string')
out.status = obj.status;
const explicit = obj.total ?? obj.returned ?? obj.totalCount;
if (typeof explicit === 'number') {
out.resultCount = explicit;
}
else {
for (const key of COLLECTION_KEYS) {
if (Array.isArray(obj[key])) {
out.resultCount = obj[key].length;
break;
}
}
}
const pageInfo = obj.pageInfo;
if (pageInfo && typeof pageInfo === 'object' && 'hasNextPage' in pageInfo) {
out.hasNextPage = !!pageInfo.hasNextPage;
}
else if (typeof obj.cursor === 'string') {
out.hasNextPage = true;
}
return out;
}
//# sourceMappingURL=usage.js.map