@pmoses-s1/sentinelone-mcp 1.0.0 → 1.1.0
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/CHANGELOG.md +44 -0
- package/README.md +187 -115
- package/deploy/README.md +277 -0
- package/deploy/caddy/Caddyfile.example +99 -0
- package/deploy/install.sh +265 -0
- package/deploy/systemd/sentinelone-mcp.service +57 -0
- package/index.js +136 -312
- package/lib/auth.js +161 -0
- package/lib/credentials.js +18 -6
- package/lib/http-transport.js +223 -0
- package/lib/s1.js +1 -1
- package/lib/server-core.js +265 -0
- package/lib/stdio-transport.js +77 -0
- package/lib/uam-ingest.js +1 -1
- package/package.json +10 -4
- package/scripts/regen-readme-tools-table.mjs +142 -0
- package/scripts/test-mac.sh +179 -0
- package/tools/hyperautomation.js +1 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.1.0 — 2026-05-28
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Streamable HTTP transport.** New `--transport http` mode (default stays `stdio`). Single-endpoint POST `/mcp` per the MCP 2024-11-05 spec, plus `/healthz` for load balancer probes. Implementation is pure `node:http`, no new dependencies.
|
|
7
|
+
- **Per-user bearer token auth.** New `MCP_BEARER_TOKENS_FILE` env var pointing at a `{ "<name>": "<token>" }` JSON file gives each team member a stable name in audit logs and supports rotation. SIGHUP reloads tokens without dropping connections. `MCP_BEARER_TOKENS` env var (comma-separated raw tokens) is a fallback for small or quick-test setups.
|
|
8
|
+
- **Audit logging.** Every authenticated HTTP request emits `[audit] <ts> | <name> | <method> | <param-summary> | <status>` to stderr; systemd captures it via journald.
|
|
9
|
+
- **`S1_CREDS_FILE` credential resolver.** Highest-priority explicit path for credentials, useful for VM deployments and secret-store integrations (Vault, Doppler, 1Password Connect, sealed-secrets).
|
|
10
|
+
- **Deploy artifacts** under `deploy/`:
|
|
11
|
+
- `install.sh` — one-shot installer for Mac and Linux. `--user` mode for individuals, `--server` mode for Linux VMs (creates `mcp` system user, generates an initial bearer token, installs systemd unit, starts the service).
|
|
12
|
+
- `systemd/sentinelone-mcp.service` — hardened unit with `NoNewPrivileges`, `ProtectSystem=strict`, `MemoryDenyWriteExecute`, SIGHUP-as-reload.
|
|
13
|
+
- `caddy/Caddyfile.example` — TLS reverse proxy template with bearer header gate and streaming-friendly flush.
|
|
14
|
+
- `README.md` — full topology guide (single-user local, single-user HTTP, team VM-hosted) with day-2 operations.
|
|
15
|
+
- **Test suite.** Three new files under `tests/`, runnable via `npm test`:
|
|
16
|
+
- `smoke.test.mjs` — source-of-truth tool inventory (26 tools by name).
|
|
17
|
+
- `stdio-transport.test.mjs` — JSON-RPC round trip via spawned stdio process.
|
|
18
|
+
- `http-transport.test.mjs` — HTTP transport end-to-end, bearer auth happy/sad paths.
|
|
19
|
+
- **README auto-regenerator** at `scripts/regen-readme-tools-table.mjs`. `npm run regen:readme` keeps the README table in sync with `ALL_TOOLS`. `npm run regen:readme -- --check` fails when stale (suitable for CI).
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
- **README tool table.** Previous count was 19; actual is 26. Auto-generated now.
|
|
23
|
+
- **Header comment in `index.js`.** Previously said 21; updated to 26.
|
|
24
|
+
- **`purple_ai_query`** removed from the documentation. The tool itself was removed 2026-05-03 because the underlying API requires a browser-session `teamToken` that service-account API tokens never obtain. The README, `index.js`, and `docs/mcp-tools.md` no longer reference it.
|
|
25
|
+
- **`uam_set_status` documentation.** Doc previously said valid status values include `CLOSED`. The source enum is `NEW`, `IN_PROGRESS`, `RESOLVED`; doc now matches.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
- **Refactored** dispatch out of `index.js` into `lib/server-core.js` so both transports use one code path. `lib/stdio-transport.js` is the extracted stdio loop; `lib/http-transport.js` is new.
|
|
29
|
+
- **package.json**:
|
|
30
|
+
- `version` 1.0.0 → 1.1.0
|
|
31
|
+
- new scripts: `start:http`, `test`, `regen:readme`
|
|
32
|
+
- new files included in the npm tarball: `deploy/`, `scripts/`, `CHANGELOG.md`
|
|
33
|
+
|
|
34
|
+
### Compatibility
|
|
35
|
+
- Default invocation is unchanged: `npx -y @pmoses-s1/sentinelone-mcp` still produces a stdio MCP server with identical behavior to 1.0.0.
|
|
36
|
+
- Existing `claude_desktop_config.json` and `.mcp.json` configs work without modification.
|
|
37
|
+
- The 26 tools, 2 resources, and 2 prompts are unchanged from the late-1.0.0 line; only the documentation now matches reality.
|
|
38
|
+
|
|
39
|
+
## 1.0.0 — 2026-05-07
|
|
40
|
+
|
|
41
|
+
Initial public release.
|
|
42
|
+
- 19 tools across PowerQuery, S1 Mgmt REST, UAM, SDL API, Hyperautomation.
|
|
43
|
+
- stdio transport only.
|
|
44
|
+
- Credentials via env vars or auto-discovered `credentials.json`.
|
package/README.md
CHANGED
|
@@ -1,180 +1,229 @@
|
|
|
1
1
|
# SentinelOne MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Model Context Protocol server orchestrating the SentinelOne Management Console, Singularity Data Lake, UAM Alert Interface, and Hyperautomation APIs. Pure Node.js 18+, zero external dependencies. Supports both stdio (for Claude Desktop / Cowork / Claude Code) and Streamable HTTP (for team-shared VM deployments) transports.
|
|
4
|
+
|
|
5
|
+
- **Single-user, local:** install with `npx`, plug into Claude Desktop in 30 seconds.
|
|
6
|
+
- **Team, VM-hosted:** install on one Linux box, per-user bearer tokens, audit logs, SIGHUP-reloadable rotation.
|
|
7
|
+
|
|
8
|
+
See **[deploy/README.md](./deploy/README.md)** for the full deployment walkthrough across all three topologies.
|
|
4
9
|
|
|
5
10
|
## What this exposes
|
|
6
11
|
|
|
7
|
-
|
|
12
|
+
<!-- BEGIN AUTO-GENERATED TOOLS TABLE -->
|
|
13
|
+
**26 tools** across PowerQuery, Mgmt Console, SDL API, Hyperautomation, and UAM Ingest:
|
|
8
14
|
|
|
9
15
|
| Group | Tool | Skill |
|
|
10
16
|
|-------|------|-------|
|
|
11
17
|
| PowerQuery | `powerquery_enumerate_sources` | sentinelone-powerquery |
|
|
12
18
|
| PowerQuery | `powerquery_run` | sentinelone-powerquery |
|
|
13
19
|
| PowerQuery | `powerquery_schema_discover` | sentinelone-powerquery |
|
|
20
|
+
| Mgmt Console | `purple_ai_alert_summary` | sentinelone-mgmt-console-api |
|
|
21
|
+
| Mgmt Console | `s1_api_delete` | sentinelone-mgmt-console-api |
|
|
14
22
|
| Mgmt Console | `s1_api_get` | sentinelone-mgmt-console-api |
|
|
23
|
+
| Mgmt Console | `s1_api_patch` | sentinelone-mgmt-console-api |
|
|
15
24
|
| Mgmt Console | `s1_api_post` | sentinelone-mgmt-console-api |
|
|
16
|
-
| Mgmt Console | `
|
|
17
|
-
| Mgmt Console | `uam_list_alerts` | sentinelone-mgmt-console-api |
|
|
18
|
-
| Mgmt Console | `uam_get_alert` | sentinelone-mgmt-console-api |
|
|
25
|
+
| Mgmt Console | `s1_api_put` | sentinelone-mgmt-console-api |
|
|
19
26
|
| Mgmt Console | `uam_add_note` | sentinelone-mgmt-console-api |
|
|
27
|
+
| Mgmt Console | `uam_get_alert` | sentinelone-mgmt-console-api |
|
|
28
|
+
| Mgmt Console | `uam_list_alerts` | sentinelone-mgmt-console-api |
|
|
20
29
|
| Mgmt Console | `uam_set_status` | sentinelone-mgmt-console-api |
|
|
21
|
-
| SDL API | `
|
|
30
|
+
| SDL API | `sdl_delete_file` | sentinelone-sdl-api |
|
|
22
31
|
| SDL API | `sdl_get_file` | sentinelone-sdl-api / sdl-dashboard / sdl-log-parser |
|
|
32
|
+
| SDL API | `sdl_list_files` | sentinelone-sdl-api / sdl-dashboard / sdl-log-parser |
|
|
23
33
|
| SDL API | `sdl_put_file` | sentinelone-sdl-api / sdl-dashboard / sdl-log-parser |
|
|
24
|
-
| SDL API | `sdl_delete_file` | sentinelone-sdl-api |
|
|
25
34
|
| SDL API | `sdl_upload_logs` | sentinelone-sdl-api / sdl-log-parser |
|
|
26
|
-
| Hyperautomation | `
|
|
35
|
+
| Hyperautomation | `ha_archive_workflow` | sentinelone-hyperautomation |
|
|
36
|
+
| Hyperautomation | `ha_export_workflow` | sentinelone-hyperautomation |
|
|
27
37
|
| Hyperautomation | `ha_get_workflow` | sentinelone-hyperautomation |
|
|
28
38
|
| Hyperautomation | `ha_import_workflow` | sentinelone-hyperautomation |
|
|
29
|
-
| Hyperautomation | `
|
|
39
|
+
| Hyperautomation | `ha_list_workflows` | sentinelone-hyperautomation |
|
|
40
|
+
| UAM Ingest | `uam_ingest_alert` | sentinelone-mgmt-console-api (UAM Alert Interface) |
|
|
41
|
+
| UAM Ingest | `uam_post_alert` | sentinelone-mgmt-console-api (UAM Alert Interface) |
|
|
42
|
+
| UAM Ingest | `uam_post_indicators` | sentinelone-mgmt-console-api (UAM Alert Interface) |
|
|
43
|
+
<!-- END AUTO-GENERATED TOOLS TABLE -->
|
|
30
44
|
|
|
31
45
|
**2 resources:**
|
|
32
|
-
- `sentinelone://soc-context
|
|
33
|
-
- `sentinelone://credentials-status
|
|
46
|
+
- `sentinelone://soc-context` — `CLAUDE.md`, the Principal SOC Analyst operating instructions.
|
|
47
|
+
- `sentinelone://credentials-status` — which credentials are configured and which API surfaces are available.
|
|
34
48
|
|
|
35
49
|
**2 prompts:**
|
|
36
|
-
- `soc_analyst
|
|
37
|
-
- `session_init
|
|
50
|
+
- `soc_analyst` — embeds `CLAUDE.md` as a system prompt; call at session start.
|
|
51
|
+
- `session_init` — structured init: enumerate sources + triage alerts in parallel.
|
|
38
52
|
|
|
39
|
-
##
|
|
53
|
+
## Quick install
|
|
40
54
|
|
|
41
|
-
|
|
42
|
-
- No `npm install` needed: zero external dependencies
|
|
55
|
+
Two paths, pick one:
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
### Easiest: `npx` via Claude Desktop / Claude Code / Cowork
|
|
45
58
|
|
|
46
|
-
|
|
59
|
+
Add this to `claude_desktop_config.json` (or `.mcp.json` for Claude Code):
|
|
47
60
|
|
|
48
|
-
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"sentinelone-mcp": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["-y", "@pmoses-s1/sentinelone-mcp@1.1.0"],
|
|
67
|
+
"env": {
|
|
68
|
+
"S1_CONSOLE_URL": "https://usea1-yourorg.sentinelone.net",
|
|
69
|
+
"S1_CONSOLE_API_TOKEN": "eyJ...",
|
|
70
|
+
"S1_HEC_INGEST_URL": "https://ingest.us1.sentinelone.net",
|
|
71
|
+
"SDL_XDR_URL": "https://xdr.us1.sentinelone.net",
|
|
72
|
+
"SDL_LOG_READ_KEY": "...",
|
|
73
|
+
"SDL_LOG_WRITE_KEY": "...",
|
|
74
|
+
"SDL_CONFIG_READ_KEY": "...",
|
|
75
|
+
"SDL_CONFIG_WRITE_KEY": "..."
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
```
|
|
49
81
|
|
|
50
|
-
|
|
51
|
-
|----------|-------------|
|
|
52
|
-
| `S1_CONSOLE_URL` | Your console URL, e.g. `https://usea1-acme.sentinelone.net` |
|
|
53
|
-
| `S1_CONSOLE_API_TOKEN` | Management Console API token (Settings → Users → Service Users) |
|
|
54
|
-
| `S1_HEC_INGEST_URL` | HEC ingest host, e.g. `https://ingest.us1.sentinelone.net` |
|
|
55
|
-
| `SDL_XDR_URL` | SDL tenant URL, e.g. `https://xdr.us1.sentinelone.net` |
|
|
56
|
-
| `SDL_LOG_WRITE_KEY` | SDL Log Write key (required for `sdl_upload_logs` only) |
|
|
57
|
-
| `SDL_LOG_READ_KEY` | SDL Log Read key (required for SDL query operations) |
|
|
58
|
-
| `SDL_CONFIG_WRITE_KEY` | SDL Config Write key (required for `sdl_put_file`) |
|
|
59
|
-
| `SDL_CONFIG_READ_KEY` | SDL Config Read key (required for `sdl_list_files`, `sdl_get_file`) |
|
|
82
|
+
Restart Claude Desktop. `npx -y` caches the package on first launch.
|
|
60
83
|
|
|
61
|
-
|
|
84
|
+
### Reproducible: install script
|
|
62
85
|
|
|
63
86
|
```bash
|
|
64
|
-
|
|
65
|
-
npx -y @pmoses-s1/sentinelone-mcp
|
|
66
|
-
|
|
67
|
-
# Or from a local clone (development)
|
|
68
|
-
node /path/to/claude-skills/sentinelone-mcp/index.js
|
|
87
|
+
curl -fsSL https://raw.githubusercontent.com/pmoses-s1/claude-skills/main/sentinelone-mcp/deploy/install.sh | bash
|
|
69
88
|
```
|
|
70
89
|
|
|
71
|
-
|
|
90
|
+
This sets up a per-user npm prefix if needed, installs the package, drops a credentials skeleton at `~/.config/sentinelone/credentials.json` (mode 0600), and prints the wiring instructions for Claude Desktop.
|
|
72
91
|
|
|
73
|
-
|
|
92
|
+
For VM deployments, the same script in `--server` mode does everything (system user, systemd unit, initial bearer token, service start). See [deploy/README.md](./deploy/README.md).
|
|
74
93
|
|
|
75
|
-
|
|
94
|
+
## Credentials
|
|
76
95
|
|
|
77
|
-
|
|
96
|
+
`S1_CONSOLE_URL` and `S1_CONSOLE_API_TOKEN` are sufficient for the PowerQuery, Mgmt Console REST, Purple AI summary, and UAM tools (16 of the 26).
|
|
78
97
|
|
|
79
|
-
|
|
98
|
+
`S1_HEC_INGEST_URL` is **required** for the three UAM Ingest tools (`uam_ingest_alert`, `uam_post_indicators`, `uam_post_alert`). Without it those tools error at call time, the rest still work.
|
|
80
99
|
|
|
81
|
-
|
|
100
|
+
`SDL_*` keys gate the SDL tools as follows:
|
|
82
101
|
|
|
83
|
-
|
|
102
|
+
| Variable | Description | Required for |
|
|
103
|
+
|----------|-------------|--------------|
|
|
104
|
+
| `S1_CONSOLE_URL` | Console URL, e.g. `https://usea1-acme.sentinelone.net` | All Mgmt + PowerQuery tools |
|
|
105
|
+
| `S1_CONSOLE_API_TOKEN` | Mgmt Console API token (Settings → Users → Service Users) | All Mgmt + PowerQuery + UAM tools |
|
|
106
|
+
| `S1_HEC_INGEST_URL` | HEC ingest host, e.g. `https://ingest.us1.sentinelone.net` | `uam_ingest_alert`, `uam_post_indicators`, `uam_post_alert` |
|
|
107
|
+
| `SDL_XDR_URL` | SDL tenant URL, e.g. `https://xdr.us1.sentinelone.net` | All `sdl_*` tools and `powerquery_schema_discover` |
|
|
108
|
+
| `SDL_LOG_READ_KEY` | SDL Log Read key | SDL query operations |
|
|
109
|
+
| `SDL_LOG_WRITE_KEY` | SDL Log Write key (console JWT NOT accepted by this endpoint) | `sdl_upload_logs` |
|
|
110
|
+
| `SDL_CONFIG_READ_KEY` | SDL Config Read key | `sdl_list_files`, `sdl_get_file` |
|
|
111
|
+
| `SDL_CONFIG_WRITE_KEY` | SDL Config Write key | `sdl_put_file`, `sdl_delete_file` |
|
|
84
112
|
|
|
85
|
-
|
|
113
|
+
### Credential resolution order (highest priority wins)
|
|
86
114
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
"S1_CONSOLE_URL": "https://usea1-yourorg.sentinelone.net",
|
|
95
|
-
"S1_CONSOLE_API_TOKEN": "eyJ...your-api-token...",
|
|
96
|
-
"S1_HEC_INGEST_URL": "https://ingest.us1.sentinelone.net",
|
|
97
|
-
"SDL_XDR_URL": "https://xdr.us1.sentinelone.net",
|
|
98
|
-
"SDL_LOG_WRITE_KEY": "0Z1Fy0...",
|
|
99
|
-
"SDL_LOG_READ_KEY": "0tzj...",
|
|
100
|
-
"SDL_CONFIG_WRITE_KEY": "0mXas6PD...",
|
|
101
|
-
"SDL_CONFIG_READ_KEY": "0MQTx..."
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
115
|
+
1. Environment variables (set in `claude_desktop_config.json` `env`, systemd `EnvironmentFile`, or your shell).
|
|
116
|
+
2. `S1_CREDS_FILE` — explicit path to a JSON file (recommended for VM deployments and secret-store integrations).
|
|
117
|
+
3. `COWORK_WORKSPACE/credentials.json`.
|
|
118
|
+
4. Walk-up from the current working directory looking for `credentials.json`.
|
|
119
|
+
5. `~/mnt/<folder>/credentials.json` (Cowork workspace mounts).
|
|
120
|
+
6. `$CLAUDE_CONFIG_DIR/sentinelone/credentials.json`.
|
|
121
|
+
7. `~/.config/sentinelone/credentials.json`.
|
|
107
122
|
|
|
108
|
-
|
|
123
|
+
The server logs the resolved credential source at startup so you can diagnose surprise overrides.
|
|
109
124
|
|
|
110
|
-
|
|
125
|
+
## Transport modes
|
|
111
126
|
|
|
112
|
-
###
|
|
127
|
+
### stdio (default)
|
|
113
128
|
|
|
114
|
-
|
|
129
|
+
The transport used by Claude Desktop, Claude Code, Claude Cowork, and any other client launched via `npx` / `node index.js`.
|
|
115
130
|
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
"sentinelone-mcp": {
|
|
120
|
-
"command": "npx",
|
|
121
|
-
"args": ["-y", "@pmoses-s1/sentinelone-mcp"],
|
|
122
|
-
"env": {
|
|
123
|
-
"S1_CONSOLE_URL": "https://usea1-yourorg.sentinelone.net",
|
|
124
|
-
"S1_CONSOLE_API_TOKEN": "eyJ...your-api-token..."
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
131
|
+
```bash
|
|
132
|
+
sentinelone-mcp # auto-discovers credentials
|
|
133
|
+
node index.js # same as above, from a local clone
|
|
129
134
|
```
|
|
130
135
|
|
|
131
|
-
###
|
|
132
|
-
|
|
133
|
-
If you are developing the MCP server itself, replace the `npx` invocation with a path to your clone:
|
|
136
|
+
### Streamable HTTP
|
|
134
137
|
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
138
|
+
```bash
|
|
139
|
+
sentinelone-mcp --transport http # 127.0.0.1:8765/mcp, no auth
|
|
140
|
+
sentinelone-mcp --transport http --host 0.0.0.0 # all interfaces, no auth (loud warning)
|
|
141
|
+
MCP_BEARER_TOKENS_FILE=/etc/sentinelone-mcp/bearer-tokens.json \
|
|
142
|
+
sentinelone-mcp --transport http --host 0.0.0.0 # team mode with per-user tokens
|
|
141
143
|
```
|
|
142
144
|
|
|
143
|
-
|
|
145
|
+
Configuration via flags or environment variables:
|
|
146
|
+
|
|
147
|
+
| Flag | Env var | Default | Purpose |
|
|
148
|
+
|------|---------|---------|---------|
|
|
149
|
+
| `--transport` | `MCP_TRANSPORT` | `stdio` | `stdio` or `http`. |
|
|
150
|
+
| `--host` | `MCP_HTTP_HOST` | `127.0.0.1` | HTTP bind address. Use `0.0.0.0` for cross-host access. |
|
|
151
|
+
| `--port` | `MCP_HTTP_PORT` | `8765` | HTTP port. |
|
|
152
|
+
| `--path` | `MCP_HTTP_PATH` | `/mcp` | MCP endpoint path. |
|
|
153
|
+
|
|
154
|
+
In HTTP mode the server exposes:
|
|
155
|
+
|
|
156
|
+
- `POST /mcp` — accepts JSON-RPC, returns JSON-RPC. The MCP entry point.
|
|
157
|
+
- `GET /healthz` — returns `200 ok`. For load balancer probes; no auth.
|
|
158
|
+
|
|
159
|
+
### Team auth: bearer tokens
|
|
144
160
|
|
|
145
|
-
|
|
161
|
+
To enable team auth, set one of:
|
|
146
162
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
3. Restart Claude Desktop
|
|
163
|
+
- `MCP_BEARER_TOKENS_FILE=/path/to/file.json` (recommended). The file is `{ "<name>": "<token>", ... }`. Names appear in audit logs; revoking a user is a one-line edit. SIGHUP reloads without restart.
|
|
164
|
+
- `MCP_BEARER_TOKENS="token1,token2,..."` (fallback, no per-user names).
|
|
150
165
|
|
|
151
|
-
|
|
166
|
+
Token rotation:
|
|
152
167
|
|
|
153
|
-
|
|
168
|
+
```bash
|
|
169
|
+
sudo vim /etc/sentinelone-mcp/bearer-tokens.json # add/remove entries
|
|
170
|
+
sudo systemctl reload sentinelone-mcp # SIGHUP, no connection drops
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
If neither env var is set, HTTP transport runs **without** authentication and the server logs a warning at startup. That's acceptable for `--host 127.0.0.1` single-user use; never use it on `0.0.0.0` in production.
|
|
174
|
+
|
|
175
|
+
### Audit log
|
|
176
|
+
|
|
177
|
+
Every authenticated HTTP request emits a structured stderr line that systemd captures via journald:
|
|
154
178
|
|
|
155
|
-
|
|
179
|
+
```
|
|
180
|
+
[audit] 2026-05-28T15:01:22.413Z | alice | tools/call | name=powerquery_run | 200 ok
|
|
181
|
+
[audit] 2026-05-28T15:01:34.221Z | bob | tools/list | - | 200 ok
|
|
182
|
+
[audit] 2026-05-28T17:03:11.221Z | - | - | - | 401 unauthorized
|
|
183
|
+
```
|
|
156
184
|
|
|
157
|
-
|
|
158
|
-
2. Call `powerquery_enumerate_sources` to discover active SDL data sources (mandatory: never assume sources from a prior session).
|
|
159
|
-
3. In parallel, call `uam_list_alerts` with `filter="status=OPEN"` to pull active alerts.
|
|
185
|
+
## CLI reference
|
|
160
186
|
|
|
161
|
-
|
|
187
|
+
```
|
|
188
|
+
sentinelone-mcp [options]
|
|
189
|
+
|
|
190
|
+
OPTIONS
|
|
191
|
+
--transport <stdio|http> Transport. Default: stdio.
|
|
192
|
+
--host <host> HTTP bind address. Default: 127.0.0.1.
|
|
193
|
+
--port <port> HTTP port. Default: 8765.
|
|
194
|
+
--path <path> HTTP MCP endpoint path. Default: /mcp.
|
|
195
|
+
-h, --help Show help.
|
|
196
|
+
-v, --version Show server version.
|
|
197
|
+
```
|
|
162
198
|
|
|
163
199
|
## Architecture
|
|
164
200
|
|
|
165
201
|
```
|
|
166
202
|
sentinelone-mcp/
|
|
167
|
-
index.js
|
|
203
|
+
index.js Entry: flag parsing + transport selection
|
|
168
204
|
lib/
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
205
|
+
server-core.js Tool registry, JSON-RPC dispatch (transport-agnostic)
|
|
206
|
+
stdio-transport.js stdin/stdout JSON-RPC loop
|
|
207
|
+
http-transport.js Streamable HTTP (node:http, zero deps)
|
|
208
|
+
auth.js Bearer token allowlist with SIGHUP reload
|
|
209
|
+
credentials.js S1 + SDL credential resolution
|
|
210
|
+
s1.js Mgmt REST + LRQ PowerQuery + Purple AI + UAM GraphQL
|
|
211
|
+
sdl.js SDL config files + V1 query + uploadLogs
|
|
212
|
+
uam-ingest.js HEC alert/indicator ingestion
|
|
172
213
|
tools/
|
|
173
|
-
powerquery.js
|
|
174
|
-
mgmt-console.js
|
|
175
|
-
sdl-api.js
|
|
176
|
-
hyperautomation.js
|
|
177
|
-
|
|
214
|
+
powerquery.js PowerQuery enumerate/run/schema-discover
|
|
215
|
+
mgmt-console.js S1 REST verbs + Purple AI summary + UAM
|
|
216
|
+
sdl-api.js SDL config file + log ingestion tools
|
|
217
|
+
hyperautomation.js Hyperautomation list/get/import/export/archive
|
|
218
|
+
uam-ingest.js UAM Alert Interface ingestion tools
|
|
219
|
+
deploy/
|
|
220
|
+
install.sh One-shot installer (Mac and Linux)
|
|
221
|
+
systemd/ Service unit for Linux VM deployments
|
|
222
|
+
caddy/ TLS reverse proxy template
|
|
223
|
+
README.md Deployment walkthrough
|
|
224
|
+
scripts/
|
|
225
|
+
regen-readme-tools-table.mjs Tools-table regenerator (no drift)
|
|
226
|
+
tests/ Smoke + stdio + HTTP test suites (node --test)
|
|
178
227
|
```
|
|
179
228
|
|
|
180
229
|
## Auth patterns (implemented)
|
|
@@ -185,15 +234,38 @@ sentinelone-mcp/
|
|
|
185
234
|
| LRQ PowerQuery | `Authorization: Bearer <jwt>` | Same token, different prefix |
|
|
186
235
|
| Purple AI GraphQL | `Authorization: ApiToken <jwt>` | `S1_CONSOLE_API_TOKEN` |
|
|
187
236
|
| UAM GraphQL | `Authorization: ApiToken <jwt>` | `S1_CONSOLE_API_TOKEN` |
|
|
237
|
+
| UAM HEC ingest | `Authorization: Bearer <jwt>` | `S1_CONSOLE_API_TOKEN` |
|
|
188
238
|
| SDL config ops | `Authorization: Bearer <key>` | `SDL_CONFIG_WRITE_KEY` or console JWT |
|
|
189
239
|
| SDL uploadLogs | `Authorization: Bearer <key>` | `SDL_LOG_WRITE_KEY` only (console JWT rejected) |
|
|
190
240
|
|
|
241
|
+
## Testing
|
|
242
|
+
|
|
243
|
+
```bash
|
|
244
|
+
npm test
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Three test suites under `tests/`:
|
|
248
|
+
|
|
249
|
+
- `smoke.test.mjs` — introspects `ALL_TOOLS` directly, no spawning. Asserts 26 tools by name; catches any drift between code and the README regenerator.
|
|
250
|
+
- `stdio-transport.test.mjs` — spawns the server in stdio mode, exercises `initialize`, `tools/list`, `resources/list`, `prompts/list`, and error handling.
|
|
251
|
+
- `http-transport.test.mjs` — spawns in HTTP mode on a random ephemeral port, exercises `/healthz`, `POST /mcp`, both auth-required and auth-optional flows, and the env-var token fallback.
|
|
252
|
+
|
|
253
|
+
The smoke suite is the source of truth for the tool count and is what `scripts/regen-readme-tools-table.mjs` derives the README table from. If the table goes stale, `npm run regen:readme -- --check` fails CI; `npm run regen:readme` fixes it.
|
|
254
|
+
|
|
191
255
|
## Updating CLAUDE.md
|
|
192
256
|
|
|
193
|
-
The `sentinelone://soc-context` resource and `soc_analyst` prompt load CLAUDE.md at server startup. Resolution order
|
|
257
|
+
The `sentinelone://soc-context` resource and `soc_analyst` prompt load `CLAUDE.md` at server startup. Resolution order:
|
|
258
|
+
|
|
259
|
+
1. `S1_CLAUDE_MD_PATH` env var (explicit absolute path).
|
|
260
|
+
2. `<cwd>/CLAUDE.md` — your Cowork project folder, when launched from there.
|
|
261
|
+
3. Same-dir / parent / grandparent of the server's `index.js` — when running from a git clone.
|
|
262
|
+
|
|
263
|
+
For npx installs without a CLAUDE.md nearby, set `S1_CLAUDE_MD_PATH` in the `env` block of `claude_desktop_config.json` to point at the one in your Cowork project folder. Restart Claude Desktop to pick up edits.
|
|
264
|
+
|
|
265
|
+
## Removed tools
|
|
266
|
+
|
|
267
|
+
`purple_ai_query` and `purple_ai_investigate` were removed on 2026-05-03. Both required a browser-session `teamToken` from `/sdl/v2/graphql` that service-account API tokens never obtain (returns `AsimovError` / `SERVICE_ERROR`). Use `mcp__purple-mcp__purple_ai` instead, which holds the right credentials.
|
|
194
268
|
|
|
195
|
-
|
|
196
|
-
2. `<cwd>/CLAUDE.md` (your Cowork project folder when launched from a project)
|
|
197
|
-
3. Same-dir / parent / grandparent of the server's `index.js` (when running from a git clone)
|
|
269
|
+
## Version history
|
|
198
270
|
|
|
199
|
-
|
|
271
|
+
See [CHANGELOG.md](./CHANGELOG.md).
|