splunk-soar-mcp 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.
- splunk_soar_mcp-0.1.0/.env.example +36 -0
- splunk_soar_mcp-0.1.0/.github/workflows/ci.yml +31 -0
- splunk_soar_mcp-0.1.0/.gitignore +26 -0
- splunk_soar_mcp-0.1.0/CHANGELOG.md +84 -0
- splunk_soar_mcp-0.1.0/CONTRIBUTING.md +40 -0
- splunk_soar_mcp-0.1.0/LICENSE +21 -0
- splunk_soar_mcp-0.1.0/PKG-INFO +510 -0
- splunk_soar_mcp-0.1.0/README.md +478 -0
- splunk_soar_mcp-0.1.0/SECURITY.md +43 -0
- splunk_soar_mcp-0.1.0/pyproject.toml +57 -0
- splunk_soar_mcp-0.1.0/scripts/smoke_test.py +113 -0
- splunk_soar_mcp-0.1.0/scripts/test_all_tools.py +607 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/__init__.py +6 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/__main__.py +73 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/app.py +75 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/client.py +172 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/config.py +93 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/errors.py +30 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/formatting.py +111 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/prompts.py +92 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/redaction.py +120 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/datapaths.md +54 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/phantom_api.md +170 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/vpe_blocks.md +48 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/resources.py +80 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/server.py +90 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/__init__.py +0 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/admin.py +200 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/containers.py +444 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/lists.py +205 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/metadata.py +207 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/platform.py +225 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/playbooks.py +358 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/raw.py +73 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/run.py +108 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/users.py +272 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/vpe.py +279 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/vpe/__init__.py +0 -0
- splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/vpe/blocks.py +409 -0
- splunk_soar_mcp-0.1.0/tests/conftest.py +33 -0
- splunk_soar_mcp-0.1.0/tests/test_admin_tools.py +177 -0
- splunk_soar_mcp-0.1.0/tests/test_blocks.py +106 -0
- splunk_soar_mcp-0.1.0/tests/test_client.py +108 -0
- splunk_soar_mcp-0.1.0/tests/test_config.py +48 -0
- splunk_soar_mcp-0.1.0/tests/test_execution.py +115 -0
- splunk_soar_mcp-0.1.0/tests/test_formatting.py +43 -0
- splunk_soar_mcp-0.1.0/tests/test_playbook_source.py +43 -0
- splunk_soar_mcp-0.1.0/tests/test_redaction.py +92 -0
- splunk_soar_mcp-0.1.0/tests/test_server.py +301 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------
|
|
2
|
+
# Splunk SOAR MCP server — configuration
|
|
3
|
+
# Copy to .env and fill in. .env is gitignored.
|
|
4
|
+
# ---------------------------------------------------------------------------
|
|
5
|
+
|
|
6
|
+
# Base URL of your SOAR instance (no trailing slash, no /rest suffix)
|
|
7
|
+
SPLUNK_SOAR_URL=https://soar.example.com
|
|
8
|
+
|
|
9
|
+
# Automation user API token — SOAR UI: Administration > User Management >
|
|
10
|
+
# Automation Users > (user) > ph-auth-token
|
|
11
|
+
SPLUNK_SOAR_API=your-ph-auth-token-here
|
|
12
|
+
|
|
13
|
+
# --- Safety -----------------------------------------------------------------
|
|
14
|
+
# readonly : GET-only. Cannot change anything on the instance.
|
|
15
|
+
# standard : readonly + low-risk writes (notes, comments, artifacts,
|
|
16
|
+
# container status/severity/owner, custom-list rows). [default]
|
|
17
|
+
# full : standard + run actions & playbooks, deletes, raw POST/DELETE.
|
|
18
|
+
SOAR_MCP_MODE=standard
|
|
19
|
+
|
|
20
|
+
# Optional. Comma-separated container labels the server may touch.
|
|
21
|
+
# Empty = all labels. Strongly recommended on multi-tenant/MSSP instances.
|
|
22
|
+
# SOAR_MCP_ALLOWED_LABELS=test_label,lab
|
|
23
|
+
|
|
24
|
+
# Path to this file, if it is not ./.env — a stdio server inherits its working
|
|
25
|
+
# directory from whatever launched it, so an absolute path is usually safer.
|
|
26
|
+
# SOAR_MCP_ENV_FILE=/etc/splunk-soar-mcp/.env
|
|
27
|
+
|
|
28
|
+
# --- Connection -------------------------------------------------------------
|
|
29
|
+
# Verify TLS. Set false only for self-signed on-prem certs on a trusted network.
|
|
30
|
+
SOAR_MCP_VERIFY_SSL=true
|
|
31
|
+
# Path to a CA bundle, if you have one (preferred over disabling verification).
|
|
32
|
+
# SOAR_MCP_CA_BUNDLE=/etc/ssl/certs/soar-ca.pem
|
|
33
|
+
|
|
34
|
+
SOAR_MCP_TIMEOUT=60
|
|
35
|
+
SOAR_MCP_DEFAULT_PAGE_SIZE=25
|
|
36
|
+
SOAR_MCP_MAX_PAGE_SIZE=500
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
test:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
strategy:
|
|
12
|
+
fail-fast: false
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.10", "3.11", "3.12", "3.13"]
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
- uses: actions/setup-python@v5
|
|
18
|
+
with:
|
|
19
|
+
python-version: ${{ matrix.python-version }}
|
|
20
|
+
- run: pip install -e ".[dev]"
|
|
21
|
+
- run: ruff check .
|
|
22
|
+
- run: pytest -q
|
|
23
|
+
- name: Server starts and registers tools
|
|
24
|
+
env:
|
|
25
|
+
SPLUNK_SOAR_URL: https://soar.invalid
|
|
26
|
+
SPLUNK_SOAR_API: ci-placeholder
|
|
27
|
+
run: |
|
|
28
|
+
splunk-soar-mcp --list-tools --mode readonly
|
|
29
|
+
splunk-soar-mcp --list-tools --mode full
|
|
30
|
+
- name: End-to-end stdio smoke test
|
|
31
|
+
run: python scripts/smoke_test.py
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# secrets — never commit
|
|
2
|
+
.env
|
|
3
|
+
.env.*
|
|
4
|
+
!.env.example
|
|
5
|
+
secrets.txt
|
|
6
|
+
*.pem
|
|
7
|
+
*.key
|
|
8
|
+
|
|
9
|
+
# python
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.py[cod]
|
|
12
|
+
*.egg-info/
|
|
13
|
+
build/
|
|
14
|
+
dist/
|
|
15
|
+
.venv/
|
|
16
|
+
venv/
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.ruff_cache/
|
|
19
|
+
.mypy_cache/
|
|
20
|
+
.coverage
|
|
21
|
+
htmlcov/
|
|
22
|
+
|
|
23
|
+
# editors / os
|
|
24
|
+
.vscode/
|
|
25
|
+
.idea/
|
|
26
|
+
.DS_Store
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here.
|
|
4
|
+
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this
|
|
5
|
+
project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [Unreleased]
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Administration reads: `soar_get_system_settings` (34 sections, with a guide to
|
|
12
|
+
which admin page each backs), `soar_get_license`, `soar_get_system_health`,
|
|
13
|
+
`soar_list_cluster_nodes`, `soar_list_feature_flags`, `soar_list_ingestion_status`.
|
|
14
|
+
- Event metadata: `soar_list_container_statuses`, `soar_list_severities`,
|
|
15
|
+
`soar_list_custom_fields`, `soar_list_cef_fields`, `soar_list_workbooks`,
|
|
16
|
+
`soar_get_workbook`.
|
|
17
|
+
- Users and roles: `soar_list_users`, `soar_get_user`, `soar_list_roles`,
|
|
18
|
+
`soar_get_role` with its permission matrix, plus `soar_create_role`,
|
|
19
|
+
`soar_update_role` and `soar_delete_role` in `full` mode. Platform built-in
|
|
20
|
+
roles are refused, and deletion requires the role's exact name.
|
|
21
|
+
- Custom list lifecycle: `soar_create_custom_list`, `soar_update_custom_list_row`
|
|
22
|
+
(a targeted row replacement rather than rewriting the list), and
|
|
23
|
+
`soar_delete_custom_list` in `full` mode.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
|
|
27
|
+
- `soar_run_action` omitted the asset's `app_id` from the action target. SOAR
|
|
28
|
+
queued the run and then failed it with `app_id has invalid format`, so the
|
|
29
|
+
call looked like a success while the action never ran.
|
|
30
|
+
- `soar_list_action_runs` and `soar_get_action_run` read `app_run`, the
|
|
31
|
+
per-asset execution layer, which does not record an action that failed before
|
|
32
|
+
reaching an app. They now read `action_run`, and `soar_get_action_run` returns
|
|
33
|
+
the app runs beneath it for their `result_data`.
|
|
34
|
+
|
|
35
|
+
- `soar_add_comment` posted to `container/<id>`, which SOAR answers with
|
|
36
|
+
`{"success": true}` while silently creating nothing. It now posts to
|
|
37
|
+
`container_comment`, verified against 7.1.
|
|
38
|
+
- `soar_get_playbook_run_log` no longer falls back to `playbook_run_log`, an
|
|
39
|
+
endpoint that returns `403 Not allowed`; an empty log now reports the run's
|
|
40
|
+
status, since a run still executing has not written one yet.
|
|
41
|
+
- httpx no longer logs one INFO line per REST call into the client's log pane.
|
|
42
|
+
|
|
43
|
+
### Security
|
|
44
|
+
|
|
45
|
+
- Credentials are stripped from every response. SOAR returns asset configuration
|
|
46
|
+
verbatim, including populated `password`, `client_secret`, `api_key` and
|
|
47
|
+
`ph auth token` fields; these are now replaced before anything leaves the
|
|
48
|
+
process, including via `soar_rest_get` and error bodies.
|
|
49
|
+
- `SOAR_MCP_ALLOWED_LABELS` now gates reads as well as writes, and container
|
|
50
|
+
listings are filtered to permitted labels server-side.
|
|
51
|
+
- Refusals no longer name the target's container label or the permitted set, and
|
|
52
|
+
`soar_system_info` reports only a count. On a multi-tenant instance the
|
|
53
|
+
allowlist is the customer list, so echoing it let a caller enumerate tenants.
|
|
54
|
+
|
|
55
|
+
### Changed
|
|
56
|
+
|
|
57
|
+
- Credentials come from the environment or an env file only. The bespoke
|
|
58
|
+
`secrets.txt` search was removed; `SOAR_MCP_ENV_FILE` overrides the env file
|
|
59
|
+
path, which a stdio server usually needs since it inherits its client's
|
|
60
|
+
working directory.
|
|
61
|
+
- Every tool that reaches the instance is now annotated `open_world_hint=True`;
|
|
62
|
+
only the local block builders are closed-world.
|
|
63
|
+
|
|
64
|
+
## [0.1.0]
|
|
65
|
+
|
|
66
|
+
Initial release.
|
|
67
|
+
|
|
68
|
+
### Added
|
|
69
|
+
|
|
70
|
+
- Read tools for apps, assets, app actions, custom functions and repositories.
|
|
71
|
+
- Playbook tools: listing, metadata, block inventory, per-block source, run history,
|
|
72
|
+
run logs with a substring filter, and app action runs with full `result_data`.
|
|
73
|
+
- Container tools: listing with label/status/severity/owner filters, artifacts, notes
|
|
74
|
+
and comments.
|
|
75
|
+
- Custom list tools: listing, contents, append and replace.
|
|
76
|
+
- Execution tools for running playbooks and app actions, in `full` mode.
|
|
77
|
+
- Visual editor block tools: decode and encode clipboard payloads, and builders for
|
|
78
|
+
code, action, decision, format, custom function and child playbook blocks.
|
|
79
|
+
- Raw REST escape hatches, with POST and DELETE gated to `full` mode.
|
|
80
|
+
- Three-tier safety model (`readonly` / `standard` / `full`) that decides which tools are
|
|
81
|
+
registered, plus a container-label allowlist enforced on every write.
|
|
82
|
+
- Resources for the `phantom.*` callable reference, datapath forms and the editor block
|
|
83
|
+
format; prompts for debugging a run, triaging a container and designing a block.
|
|
84
|
+
- stdio and streamable-HTTP transports.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Bug reports, endpoint corrections and new tools are all welcome.
|
|
4
|
+
|
|
5
|
+
## Getting set up
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/huseynAgazade/splunk-soar-mcp
|
|
9
|
+
cd splunk-soar-mcp
|
|
10
|
+
pip install -e ".[dev]"
|
|
11
|
+
pytest # the REST layer is mocked; no SOAR instance required
|
|
12
|
+
ruff check .
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Adding a tool
|
|
16
|
+
|
|
17
|
+
1. Put it in the `tools/` module that matches its subject.
|
|
18
|
+
2. Give it a `@mcp.tool` decorator with a `description` that says what the tool is *for*,
|
|
19
|
+
and a docstring whose `Args:` section documents every parameter — both end up in the
|
|
20
|
+
schema the model reads.
|
|
21
|
+
3. Set `ToolAnnotations` honestly: `read_only_hint` for queries, `destructive_hint` for
|
|
22
|
+
anything irreversible.
|
|
23
|
+
4. Register it in `server.py` under the **lowest** mode that should have it. A tool that
|
|
24
|
+
writes belongs in `register_writes`; one that deletes or executes belongs in
|
|
25
|
+
`register_destructive` or `run.py`.
|
|
26
|
+
5. Raise `SoarError` (or a subclass) for failures the caller could act on. It subclasses
|
|
27
|
+
the SDK's `ToolError`, so the message reaches the model — a plain exception is masked
|
|
28
|
+
as "Error executing tool".
|
|
29
|
+
6. Add a test. `tests/conftest.py` has the fixtures; `respx` mocks the REST layer.
|
|
30
|
+
|
|
31
|
+
## Endpoint corrections
|
|
32
|
+
|
|
33
|
+
SOAR's REST surface varies between versions, and some of it is undocumented. If a tool
|
|
34
|
+
targets the wrong endpoint on your version, please open an issue with your SOAR version
|
|
35
|
+
and the response you get — that is more useful than a guess at the right path.
|
|
36
|
+
|
|
37
|
+
## Style
|
|
38
|
+
|
|
39
|
+
`ruff` enforces the rest. Keep tool descriptions concrete: what it returns and when to
|
|
40
|
+
reach for it beats a restatement of the name.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Vahab Huseynzada
|
|
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.
|