@pmoses-s1/s1-secops-mcp 1.3.7 → 1.3.8

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 CHANGED
@@ -73,7 +73,7 @@ Add this to `claude_desktop_config.json` (or `.mcp.json` for Claude Code):
73
73
  "mcpServers": {
74
74
  "s1-secops-mcp": {
75
75
  "command": "npx",
76
- "args": ["-y", "@pmoses-s1/s1-secops-mcp@1.3.7"],
76
+ "args": ["-y", "@pmoses-s1/s1-secops-mcp@1.3.8"],
77
77
  "env": {
78
78
  "S1_CONSOLE_URL": "https://usea1-yourorg.sentinelone.net",
79
79
  "S1_CONSOLE_API_TOKEN": "eyJ...",
package/deploy/README.md CHANGED
@@ -57,7 +57,7 @@ Or, equivalently, by package name without the install:
57
57
  "mcpServers": {
58
58
  "s1-secops-mcp": {
59
59
  "command": "npx",
60
- "args": ["-y", "@pmoses-s1/s1-secops-mcp@1.3.7"]
60
+ "args": ["-y", "@pmoses-s1/s1-secops-mcp@1.3.8"]
61
61
  }
62
62
  }
63
63
  }
@@ -376,7 +376,7 @@ Both block the W+X memory mappings V8 needs to JIT JavaScript. Adding them cause
376
376
 
377
377
  These are supported but not first-class:
378
378
 
379
- - **Docker / docker-compose.** Not shipped in this version. The single-file Node binary doesn't need it. If you want a container, the install is `FROM node:20-alpine` + `RUN npm install -g @pmoses-s1/s1-secops-mcp@1.3.7` + `CMD ["s1-secops-mcp", "--transport", "http", "--host", "0.0.0.0"]`. Mount creds at `/etc/s1-secops-mcp/credentials.json` and tokens at `/etc/s1-secops-mcp/bearer-tokens.json`.
379
+ - **Docker / docker-compose.** Not shipped in this version. The single-file Node binary doesn't need it. If you want a container, the install is `FROM node:20-alpine` + `RUN npm install -g @pmoses-s1/s1-secops-mcp@1.3.8` + `CMD ["s1-secops-mcp", "--transport", "http", "--host", "0.0.0.0"]`. Mount creds at `/etc/s1-secops-mcp/credentials.json` and tokens at `/etc/s1-secops-mcp/bearer-tokens.json`.
380
380
 
381
381
  - **External bridge (`supergateway`, `mcp-proxy`).** Pre-1.1.0 deployments used these to wrap the stdio-only server. They still work; this server's native HTTP mode is functionally equivalent and removes the extra process. Prefer native unless you have a specific reason.
382
382
 
package/lib/s1.js CHANGED
@@ -643,21 +643,18 @@ export async function uamSetStatus(alertId, status) {
643
643
  }
644
644
  if (action.failure?.length) {
645
645
  const f = action.failure[0];
646
- // errorMessage says WHAT failed, not WHY. `Missing UAM manage permissions`
647
- // is also what a not-offered action returns: alerts ingested via the UAM
648
- // Alert Interface (/v1/alerts) expose only addNote and eventSearch, while
649
- // the same token sets status on a native alert successfully (measured).
650
- // So ask alertAvailableActions before reporting a cause, and never let the
651
- // caller conclude "the token lacks permission" from the string alone.
646
+ // errorMessage names the failure, not the cause. Ask alertAvailableActions,
647
+ // which is filtered by the caller's permissions AND the alert type.
652
648
  let hint = '';
653
649
  try {
654
650
  const avail = await uamAvailableActions(alertId);
655
651
  const ids = avail.map((a) => a.id);
656
652
  if (!ids.includes('S1/alert/statusUpdate')) {
657
- hint = ' | alertAvailableActions: statusUpdate is NOT OFFERED for this '
658
- + `alert type (available: ${ids.join(', ') || 'none'}). This is a `
659
- + 'capability limit of the alert, not a token scope; a new token '
660
- + 'will not help.';
653
+ hint = ' | alertAvailableActions: statusUpdate is NOT OFFERED to this '
654
+ + `caller for this alert (available: ${ids.join(', ') || 'none'}). `
655
+ + 'Availability is filtered by the caller\'s permissions and the '
656
+ + 'alert type: check the service user\'s UAM permissions. A '
657
+ + 'console user session may still be able to perform it.';
661
658
  } else {
662
659
  const a = avail.find((x) => x.id === 'S1/alert/statusUpdate');
663
660
  hint = a?.isDisabled
@@ -94,7 +94,7 @@ const PROMPTS = [
94
94
 
95
95
  export const SERVER_INFO = {
96
96
  name: 's1-secops-mcp-server',
97
- version: '1.3.7',
97
+ version: '1.3.8',
98
98
  };
99
99
 
100
100
  export const PROTOCOL_VERSION = '2024-11-05';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pmoses-s1/s1-secops-mcp",
3
- "version": "1.3.7",
3
+ "version": "1.3.8",
4
4
  "description": "MCP server orchestrating SentinelOne skills, APIs, and SOC analyst context. Stdio or Streamable HTTP transport with per-user bearer auth for team deployments.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -346,7 +346,7 @@ export const tools = [
346
346
  // ─── uam_available_actions ────────────────────────────────────────────────
347
347
  {
348
348
  name: 'uam_available_actions',
349
- description: `Ask the API which actions can be triggered on a UAM alert, with isDisabled and disabledReason per action. This is the authoritative capability answer and the ONLY correct way to explain a refused write. A refused action returns errorMessage "Missing UAM manage permissions" whether the token lacks a scope OR the action is simply not offered for that alert type, and those need opposite responses. Measured on one tenant with one token: an alert ingested via the UAM Alert Interface (/v1/alerts) offers only S1/alert/addNote and S1/alert/eventSearch, so uam_set_status can never work on it and no token change helps; a native STAR / third-party / correlation alert offers S1/alert/statusUpdate and S1/alert/analystVerdictUpdate and the same token applies them successfully. Call this before concluding anything about permissions, and before a bulk write you cannot undo. Availability is also scope-sensitive: the S1/incident/* actions report INCIDENT_ACTIONS_ONLY_AVAILABLE_FROM_SITE_VIEW under ACCOUNT scope and are enabled under SITE, so pass scopeIds/scopeType when you care about a site-scoped action. Read-only.`,
349
+ description: `Ask the API which actions can be triggered on a UAM alert, with isDisabled and disabledReason per action. This is the authoritative capability answer and the ONLY correct way to explain a refused write. Availability is filtered by the caller's permissions AND the alert type: one service-user token is offered S1/alert/statusUpdate on a native STAR alert and not on an alert ingested via the UAM Alert Interface (/v1/alerts), where only S1/alert/addNote and S1/alert/eventSearch are listed, while a console user session performs the identical mutation on either. So an action missing here means this identity lacks the permission for this alert type, not that it is impossible: check the service user's UAM permissions. Call this before concluding anything about permissions, and before a bulk write you cannot undo. Availability is also scope-sensitive: the S1/incident/* actions report INCIDENT_ACTIONS_ONLY_AVAILABLE_FROM_SITE_VIEW under ACCOUNT scope and are enabled under SITE, so pass scopeIds/scopeType when you care about a site-scoped action. Read-only.`,
350
350
  inputSchema: {
351
351
  type: 'object',
352
352
  properties: {