mcp-server-malcolm 0.1.0__tar.gz

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.
Files changed (44) hide show
  1. mcp_server_malcolm-0.1.0/LICENSE +21 -0
  2. mcp_server_malcolm-0.1.0/PKG-INFO +420 -0
  3. mcp_server_malcolm-0.1.0/README.md +404 -0
  4. mcp_server_malcolm-0.1.0/pyproject.toml +38 -0
  5. mcp_server_malcolm-0.1.0/setup.cfg +4 -0
  6. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/__init__.py +26 -0
  7. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/__main__.py +5 -0
  8. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/audit.py +60 -0
  9. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/client.py +581 -0
  10. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/config.py +52 -0
  11. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/server.py +46 -0
  12. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/__init__.py +50 -0
  13. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/arkime.py +297 -0
  14. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/correlation.py +67 -0
  15. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/dsl.py +90 -0
  16. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/fields.py +151 -0
  17. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/health.py +136 -0
  18. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/netbox.py +183 -0
  19. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/query.py +140 -0
  20. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/write/__init__.py +1 -0
  21. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/write/alerting.py +99 -0
  22. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/write/arkime_tags.py +69 -0
  23. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/write/hunt_jobs.py +132 -0
  24. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm/tools/write/pcap_upload.py +75 -0
  25. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/PKG-INFO +420 -0
  26. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/SOURCES.txt +42 -0
  27. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/dependency_links.txt +1 -0
  28. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/entry_points.txt +2 -0
  29. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/requires.txt +2 -0
  30. mcp_server_malcolm-0.1.0/src/mcp_server_malcolm.egg-info/top_level.txt +1 -0
  31. mcp_server_malcolm-0.1.0/tests/test_audit.py +40 -0
  32. mcp_server_malcolm-0.1.0/tests/test_config.py +53 -0
  33. mcp_server_malcolm-0.1.0/tests/test_dsl_client.py +55 -0
  34. mcp_server_malcolm-0.1.0/tests/test_dsl_tools.py +29 -0
  35. mcp_server_malcolm-0.1.0/tests/test_gate.py +57 -0
  36. mcp_server_malcolm-0.1.0/tests/test_read_fixes.py +91 -0
  37. mcp_server_malcolm-0.1.0/tests/test_read_new_tools.py +181 -0
  38. mcp_server_malcolm-0.1.0/tests/test_seam.py +20 -0
  39. mcp_server_malcolm-0.1.0/tests/test_time_window.py +13 -0
  40. mcp_server_malcolm-0.1.0/tests/test_write_alerting.py +69 -0
  41. mcp_server_malcolm-0.1.0/tests/test_write_arkime_tags.py +70 -0
  42. mcp_server_malcolm-0.1.0/tests/test_write_hunt_jobs.py +96 -0
  43. mcp_server_malcolm-0.1.0/tests/test_write_pcap_upload.py +64 -0
  44. mcp_server_malcolm-0.1.0/tests/test_write_primitives.py +145 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 nagameTW
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,420 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-server-malcolm
3
+ Version: 0.1.0
4
+ Summary: MCP server for the Malcolm network traffic analysis platform (Zeek + Suricata + Arkime + OpenSearch + NetBox) — full read surface plus opt-in, audited write tools
5
+ Author: nagameTW
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/nagameTW/mcp-server-malcolm
8
+ Project-URL: Repository, https://github.com/nagameTW/mcp-server-malcolm
9
+ Keywords: mcp,malcolm,zeek,suricata,arkime,threat-hunting,network-security
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: mcp>=1.0
14
+ Requires-Dist: httpx>=0.27
15
+ Dynamic: license-file
16
+
17
+ # mcp-server-malcolm
18
+
19
+ **English** | [繁體中文](README.zh-TW.md)
20
+
21
+ An MCP server for [Malcolm](https://malcolm.fyi), the open-source network traffic analysis platform (Zeek + Suricata + Arkime + OpenSearch, with optional NetBox).
22
+
23
+ It gives any MCP-compatible AI agent structured access to Malcolm: search and aggregate network traffic, discover field names, query Suricata alerts, browse Arkime sessions, resolve NetBox assets, and check system health. Turn on the write classes and it can also create alerts, tag sessions, launch hunts, and upload PCAP.
24
+
25
+ ## Read-only until you opt in
26
+
27
+ With no configuration, this server exposes read tools only. It behaves like a read-only client, and nothing it does can change data in Malcolm.
28
+
29
+ The server splits write access into four classes, each behind its own environment flag and each off by default. It doesn't register a disabled class, so that class's tools never appear in `list_tools()` and can't be called. At startup it prints which classes are on:
30
+
31
+ ```
32
+ [mcp-server-malcolm] write classes: alerting=off arkime-tag=off hunt-job=off pcap-upload=off
33
+ ```
34
+
35
+ Every write is additive. Version 1 has no tool that deletes data, removes a tag, or touches user accounts. It leaves those out on purpose (see [Non-goals](#non-goals)).
36
+
37
+ ## Why an MCP layer
38
+
39
+ Malcolm keeps all network metadata in one OpenSearch index (`arkime_sessions3-*`) with non-standard field names and its own filter syntax. An LLM asked to write raw OpenSearch DSL against that index gets it wrong more often than not. This server takes that job off the model:
40
+
41
+ - It exposes Malcolm's filter syntax instead of raw DSL.
42
+ - It provides field discovery so the model checks field names before it queries.
43
+ - It provides value enumeration so the model sees what values a field actually holds.
44
+ - It wraps Suricata alert queries and handles the field mapping (`suricata.alert.*` vs `rule.*`).
45
+ - It adds NetBox asset context (IP-to-device, network segments).
46
+
47
+ The write side follows the same idea. Rather than hand an agent the raw OpenSearch and NetBox passthroughs that Malcolm already leaves open to any authenticated user, this server exposes a small, named, audited set of write actions. More on that under [Security model](#security-model).
48
+
49
+ ## Read tools
50
+
51
+ These are always registered.
52
+
53
+ ### DSL core (backend-agnostic)
54
+
55
+ Plain OpenSearch DSL against the configured endpoint (Malcolm's `/mapi/opensearch` proxy). No Malcolm-specific query shape: point the base URL at any OpenSearch-compatible backend and they still work.
56
+
57
+ | Tool | Description |
58
+ |------|-------------|
59
+ | `search_dsl` | Run a raw OpenSearch DSL query (hits + aggregations, no hidden time window) |
60
+ | `count` | Count documents matching a DSL query clause |
61
+ | `list_indices` | List indices (name/health/status/doc count) |
62
+ | `index_mapping` | Field mapping/schema for an index |
63
+ | `cluster_health` | OpenSearch cluster health |
64
+
65
+ ### Core query
66
+
67
+ | Tool | Description |
68
+ |------|-------------|
69
+ | `malcolm_search` | Search network traffic with Malcolm filter syntax |
70
+ | `malcolm_aggregate` | Aggregate traffic by one or more fields (top-N with counts) |
71
+ | `malcolm_alerts` | Search Suricata alerts by signature, severity, IP |
72
+
73
+ ### Field discovery (anti-hallucination)
74
+
75
+ | Tool | Description |
76
+ |------|-------------|
77
+ | `malcolm_field_search` | Search available field names by keyword, prefix, or type |
78
+ | `malcolm_field_values` | List distinct values for a field |
79
+ | `malcolm_field_profile` | Show which `event.dataset` types contain a field |
80
+
81
+ ### System health
82
+
83
+ | Tool | Description |
84
+ |------|-------------|
85
+ | `malcolm_service_status` | Readiness of all Malcolm services plus version info |
86
+ | `malcolm_data_coverage` | Data freshness per sensor, doc counts per dataset, index info |
87
+ | `malcolm_ping` | Quick liveness check of the Malcolm API |
88
+
89
+ ### Asset context (NetBox)
90
+
91
+ | Tool | Description |
92
+ |------|-------------|
93
+ | `malcolm_netbox_lookup` | Look up an IP, device, or network prefix in NetBox |
94
+ | `malcolm_netbox_sites` | List the NetBox site directory (id, name, metadata) |
95
+
96
+ ### Arkime
97
+
98
+ | Tool | Description |
99
+ |------|-------------|
100
+ | `arkime_sessions` | Search Arkime sessions with Arkime expression syntax |
101
+ | `arkime_session_detail` | Fetch all fields (full SPI document) for one session |
102
+ | `arkime_session_pcap` | Fetch a session's PCAP and report its size and file-magic validity (metadata only, nothing written to disk) |
103
+ | `arkime_unique` | List distinct values of one field, with optional counts |
104
+ | `arkime_spigraph` | Top values of one field with a time-series graph |
105
+ | `arkime_spiview` | Value profile across several fields in one call |
106
+ | `arkime_connections` | Source/destination connection graph (nodes and links) |
107
+
108
+ ### Correlation and export
109
+
110
+ | Tool | Description |
111
+ |------|-------------|
112
+ | `malcolm_related_sessions` | Find all sessions related to a Zeek UID |
113
+ | `malcolm_dashboard_export` | Export an OpenSearch Dashboards saved object as JSON |
114
+
115
+ ## Write tools (opt-in)
116
+
117
+ Each class is enabled by setting its flag to `true`. Nothing here runs unless you ask for it.
118
+
119
+ | Class | Flag | Tools | Endpoint |
120
+ |-------|------|-------|----------|
121
+ | alerting | `MALCOLM_MCP_ENABLE_ALERTING` | `malcolm_create_alert` | `POST /mapi/event` |
122
+ | arkime-tag | `MALCOLM_MCP_ENABLE_ARKIME_TAGS` | `arkime_add_tags` | `POST /arkime/api/sessions/addtags` |
123
+ | hunt-job | `MALCOLM_MCP_ENABLE_HUNT_JOBS` | `arkime_create_hunt`, `arkime_hunt_status` | `POST /arkime/api/hunt` |
124
+ | pcap-upload | `MALCOLM_MCP_ENABLE_PCAP_UPLOAD` | `malcolm_upload_pcap` | `POST /server/php/submit.php` |
125
+
126
+ - **alerting**: `malcolm_create_alert` indexes an analyst- or agent-generated finding as an alert document you can see in Malcolm's dashboards. It uses `/mapi/event`, Malcolm's own purpose-built write endpoint, which is the template the other classes follow.
127
+ - **arkime-tag**: `arkime_add_tags` adds tags to sessions. It only adds; tag removal needs a higher Arkime role and its own safety design, so it's deferred.
128
+ - **hunt-job**: `arkime_create_hunt` launches a cross-PCAP packet search (expensive, so scope the query first). `arkime_hunt_status` reads job progress and ships with the class.
129
+ - **pcap-upload**: `malcolm_upload_pcap` sends a local capture file to Malcolm for ingestion, with a client-side size cap.
130
+
131
+ Every write tool carries the MCP annotations `readOnlyHint: false` and `destructiveHint: false`, so an MCP client can apply its own confirmation step before the call runs.
132
+
133
+ ## Security model
134
+
135
+ Malcolm's default deployment already gives any authenticated user unrestricted write access to raw OpenSearch (`/mapi/opensearch/*`) and full NetBox CRUD (`/mapi/netbox/*`). Both are bare reverse-proxies with no HTTP-verb filtering; Malcolm's own read-only mode removes them rather than trying to filter them. In the common auth modes, "logged in" means admin-equivalent.
136
+
137
+ Turning on a write class here does not open a door that was otherwise shut. That door is already open at the platform level. This server adds a curated way through it:
138
+
139
+ - A small, named set of write actions instead of a raw passthrough.
140
+ - Off by default, enabled one class at a time.
141
+ - An audit line for every write attempt.
142
+ - MCP annotations so the client can require confirmation.
143
+
144
+ This server does **not** expose the raw OpenSearch and NetBox write passthroughs, behind a flag or otherwise. Curating that surface is what it is for.
145
+
146
+ ## Audit
147
+
148
+ Every write attempt emits one line of JSON, on success and on failure:
149
+
150
+ ```json
151
+ {"ts": "2026-07-06T09:12:44Z", "tool": "arkime_add_tags", "class": "arkime-tag", "target": "ids=240601-abc", "params": {"tags": "suspicious"}, "outcome": "ok"}
152
+ ```
153
+
154
+ `outcome` is one of `ok`, `http_4xx`, `http_5xx`, or `error:<type>`. Long parameter values are truncated, and PCAP bytes are never logged. The sink is stderr by default; set `MALCOLM_MCP_AUDIT_FILE` to append to a file instead. Read tools are not audited.
155
+
156
+ ## Quick start
157
+
158
+ ### Install
159
+
160
+ ```bash
161
+ pip install mcp-server-malcolm
162
+ ```
163
+
164
+ Or from source:
165
+
166
+ ```bash
167
+ git clone https://github.com/nagameTW/mcp-server-malcolm.git
168
+ cd mcp-server-malcolm
169
+ pip install -e .
170
+ ```
171
+
172
+ ### Configure
173
+
174
+ Set the connection variables for your Malcolm instance:
175
+
176
+ ```bash
177
+ export MALCOLM_URL="https://malcolm.example"
178
+ export MALCOLM_USERNAME="admin"
179
+ export MALCOLM_PASSWORD="admin"
180
+ export MALCOLM_SSL_VERIFY="false" # Malcolm ships self-signed certs by default
181
+ export MALCOLM_TIMEOUT="30"
182
+ ```
183
+
184
+ Leave the write flags unset to run read-only. To enable a class, set its flag:
185
+
186
+ ```bash
187
+ export MALCOLM_MCP_ENABLE_ALERTING="true"
188
+ export MALCOLM_MCP_AUDIT_FILE="/var/log/malcolm-mcp-audit.jsonl"
189
+ ```
190
+
191
+ ### Run
192
+
193
+ ```bash
194
+ # As an MCP server (stdio transport)
195
+ mcp-server-malcolm
196
+
197
+ # Or via the Python module
198
+ python -m mcp_server_malcolm
199
+ ```
200
+
201
+ ## Usage
202
+
203
+ ### MCP client (config file)
204
+
205
+ Add the server to your MCP client's configuration:
206
+
207
+ ```json
208
+ {
209
+ "mcpServers": {
210
+ "malcolm": {
211
+ "command": "mcp-server-malcolm",
212
+ "env": {
213
+ "MALCOLM_URL": "https://malcolm.example",
214
+ "MALCOLM_USERNAME": "admin",
215
+ "MALCOLM_PASSWORD": "admin",
216
+ "MALCOLM_SSL_VERIFY": "false"
217
+ }
218
+ }
219
+ }
220
+ }
221
+ ```
222
+
223
+ For the exact config-file location, check your MCP client's docs. Many use a project-level `.mcp.json` or a global config file.
224
+
225
+ ### Python (direct import)
226
+
227
+ Use `MalcolmClient` without the MCP layer:
228
+
229
+ ```python
230
+ import asyncio
231
+ from mcp_server_malcolm import MalcolmClient
232
+
233
+ async def main():
234
+ client = MalcolmClient(
235
+ base_url="https://malcolm.example",
236
+ username="admin",
237
+ password="admin",
238
+ )
239
+
240
+ # Search network traffic
241
+ results = await client.search(
242
+ filters={"event.dataset": "conn", "source.ip": "192.0.2.77"},
243
+ limit=10,
244
+ )
245
+
246
+ # Aggregate by protocol
247
+ agg = await client.aggregate(
248
+ fields="network.protocol",
249
+ filters={"network.direction": ["inbound", "outbound"]},
250
+ )
251
+
252
+ # Discover field names
253
+ fields = await client.search_fields(keyword="useragent")
254
+
255
+ # Get distinct values
256
+ datasets = await client.field_values(field="event.dataset")
257
+
258
+ # Look up a NetBox asset
259
+ asset = await client.netbox_get(
260
+ "api/ipam/ip-addresses/",
261
+ params={"address": "192.0.2.77"},
262
+ )
263
+
264
+ await client.close()
265
+
266
+ asyncio.run(main())
267
+ ```
268
+
269
+ Write primitives live behind the `_write_*` methods. Only the gated write tools reach them, not the direct-import path.
270
+
271
+ ## Malcolm filter syntax
272
+
273
+ Malcolm uses a simple JSON filter syntax, not OpenSearch DSL:
274
+
275
+ ```python
276
+ # Exact match
277
+ {"event.dataset": "conn"}
278
+
279
+ # Multiple values (OR)
280
+ {"network.direction": ["inbound", "outbound"]}
281
+
282
+ # Negation
283
+ {"!network.transport": "icmp"}
284
+
285
+ # Field must exist (not null)
286
+ {"!related.password": null}
287
+
288
+ # Wildcard
289
+ {"suricata.alert.signature": "*MALWARE*"}
290
+
291
+ # Combined (AND)
292
+ {"event.dataset": "dns", "source.ip": "192.0.2.77"}
293
+ ```
294
+
295
+ ## Examples
296
+
297
+ ### Search DNS queries to a suspicious domain
298
+
299
+ ```
300
+ malcolm_search(
301
+ filters='{"event.dataset": "dns", "zeek.dns.query": "*example.com*"}',
302
+ limit=20,
303
+ time_from="7 days ago"
304
+ )
305
+ ```
306
+
307
+ ### Aggregate top talkers by protocol
308
+
309
+ ```
310
+ malcolm_aggregate(
311
+ fields="source.ip,destination.ip,network.protocol",
312
+ filters='{"network.direction": ["inbound", "outbound"]}',
313
+ limit=20
314
+ )
315
+ ```
316
+
317
+ ### Verify field names before querying
318
+
319
+ ```
320
+ malcolm_field_search(prefix="zeek.dns")
321
+ malcolm_field_values(field="event.dataset")
322
+ malcolm_field_profile(field="zeek.ssl.server_name")
323
+ ```
324
+
325
+ ### Create an alert (alerting class enabled)
326
+
327
+ ```
328
+ malcolm_create_alert(
329
+ title="Periodic beacon to 192.0.2.77",
330
+ severity=2,
331
+ description="60s-interval C2 candidate",
332
+ source_ip="192.0.2.10",
333
+ dest_ip="192.0.2.77"
334
+ )
335
+ ```
336
+
337
+ ### Tag sessions for review (arkime-tag class enabled)
338
+
339
+ ```
340
+ arkime_add_tags(session_ids="240601-abc,240601-def", tags="review,beacon")
341
+ ```
342
+
343
+ ### Launch a hunt (hunt-job class enabled)
344
+
345
+ ```
346
+ arkime_create_hunt(
347
+ name="beacon-bytes",
348
+ search="deadbeef",
349
+ search_type="hex",
350
+ total_sessions=42,
351
+ start_time=1717200000,
352
+ stop_time=1717203600,
353
+ expression="ip==192.0.2.77"
354
+ )
355
+ ```
356
+
357
+ ## Configuration reference
358
+
359
+ | Variable | Default | Description |
360
+ |----------|---------|-------------|
361
+ | `MALCOLM_URL` | `https://localhost` | Malcolm base URL |
362
+ | `MALCOLM_USERNAME` | `admin` | Basic auth username |
363
+ | `MALCOLM_PASSWORD` | `admin` | Basic auth password |
364
+ | `MALCOLM_SSL_VERIFY` | `false` | Verify TLS certificates (accepts a CA path) |
365
+ | `MALCOLM_TIMEOUT` | `30` | HTTP request timeout (seconds) |
366
+ | `MALCOLM_MCP_ENABLE_ALERTING` | `false` | Enable the alerting write class |
367
+ | `MALCOLM_MCP_ENABLE_ARKIME_TAGS` | `false` | Enable additive session tagging |
368
+ | `MALCOLM_MCP_ENABLE_HUNT_JOBS` | `false` | Enable Arkime hunt create + status |
369
+ | `MALCOLM_MCP_ENABLE_PCAP_UPLOAD` | `false` | Enable PCAP upload |
370
+ | `MALCOLM_MCP_AUDIT_FILE` | unset | Write-audit file (stderr when unset) |
371
+
372
+ ## Malcolm API endpoints used
373
+
374
+ | Endpoint | Method | Used by |
375
+ |----------|--------|---------|
376
+ | `/mapi/document` | POST | `malcolm_search`, `malcolm_alerts`, `malcolm_related_sessions` |
377
+ | `/mapi/agg/<fields>` | POST | `malcolm_aggregate`, `malcolm_field_values`, `malcolm_field_profile`, `malcolm_data_coverage` |
378
+ | `/mapi/fields` | GET | `malcolm_field_search`, `malcolm_field_profile` |
379
+ | `/mapi/ready`, `/mapi/version` | GET | `malcolm_service_status` |
380
+ | `/mapi/ping` | GET | `malcolm_ping` |
381
+ | `/mapi/ingest-stats`, `/mapi/indices` | GET | `malcolm_data_coverage` |
382
+ | `/mapi/dashboard-export/<id>` | GET | `malcolm_dashboard_export` |
383
+ | `/mapi/opensearch/<index>/_search` | POST | `search_dsl` |
384
+ | `/mapi/opensearch/<index>/_count` | POST | `count` |
385
+ | `/mapi/opensearch/_cat/indices` | GET | `list_indices` |
386
+ | `/mapi/opensearch/<index>/_mapping` | GET | `index_mapping` |
387
+ | `/mapi/opensearch/_cluster/health` | GET | `cluster_health` |
388
+ | `/mapi/netbox/*` | GET | `malcolm_netbox_lookup` |
389
+ | `/mapi/netbox-sites` | GET | `malcolm_netbox_sites` |
390
+ | `/mapi/event` | POST | `malcolm_create_alert` (write) |
391
+ | `/arkime/api/sessions` | GET | `arkime_sessions` |
392
+ | `/arkime/api/session/<id>` | GET | `arkime_session_detail` |
393
+ | `/arkime/api/sessions.pcap` | GET | `arkime_session_pcap` |
394
+ | `/arkime/api/unique` | GET | `arkime_unique` |
395
+ | `/arkime/api/spigraph` | GET | `arkime_spigraph` |
396
+ | `/arkime/api/spiview` | GET | `arkime_spiview` |
397
+ | `/arkime/api/connections` | GET | `arkime_connections` |
398
+ | `/arkime/api/sessions/addtags` | POST | `arkime_add_tags` (write) |
399
+ | `/arkime/api/hunt`, `/arkime/api/hunts` | POST, GET | `arkime_create_hunt`, `arkime_hunt_status` (write + read) |
400
+ | `/server/php/submit.php` | POST | `malcolm_upload_pcap` (write) |
401
+
402
+ These endpoint paths and body shapes match Malcolm `26.06.1` and Arkime `v6.5.0`. Both drift between releases, so re-check against your own version if a write tool returns an unexpected error.
403
+
404
+ ## Non-goals
405
+
406
+ Version 1 leaves these out on purpose:
407
+
408
+ - Destructive writes (Arkime session delete, tag removal, user management).
409
+ - Raw OpenSearch write or raw NetBox CRUD passthrough, behind a flag or otherwise.
410
+ - The `streamable-http` transport (stdio only).
411
+
412
+ ## Requirements
413
+
414
+ - Python 3.11+
415
+ - A Malcolm instance with API access
416
+ - Network connectivity to Malcolm (HTTPS)
417
+
418
+ ## License
419
+
420
+ MIT © nagameTW