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.
Files changed (49) hide show
  1. splunk_soar_mcp-0.1.0/.env.example +36 -0
  2. splunk_soar_mcp-0.1.0/.github/workflows/ci.yml +31 -0
  3. splunk_soar_mcp-0.1.0/.gitignore +26 -0
  4. splunk_soar_mcp-0.1.0/CHANGELOG.md +84 -0
  5. splunk_soar_mcp-0.1.0/CONTRIBUTING.md +40 -0
  6. splunk_soar_mcp-0.1.0/LICENSE +21 -0
  7. splunk_soar_mcp-0.1.0/PKG-INFO +510 -0
  8. splunk_soar_mcp-0.1.0/README.md +478 -0
  9. splunk_soar_mcp-0.1.0/SECURITY.md +43 -0
  10. splunk_soar_mcp-0.1.0/pyproject.toml +57 -0
  11. splunk_soar_mcp-0.1.0/scripts/smoke_test.py +113 -0
  12. splunk_soar_mcp-0.1.0/scripts/test_all_tools.py +607 -0
  13. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/__init__.py +6 -0
  14. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/__main__.py +73 -0
  15. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/app.py +75 -0
  16. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/client.py +172 -0
  17. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/config.py +93 -0
  18. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/errors.py +30 -0
  19. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/formatting.py +111 -0
  20. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/prompts.py +92 -0
  21. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/redaction.py +120 -0
  22. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/datapaths.md +54 -0
  23. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/phantom_api.md +170 -0
  24. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/reference/vpe_blocks.md +48 -0
  25. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/resources.py +80 -0
  26. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/server.py +90 -0
  27. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/__init__.py +0 -0
  28. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/admin.py +200 -0
  29. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/containers.py +444 -0
  30. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/lists.py +205 -0
  31. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/metadata.py +207 -0
  32. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/platform.py +225 -0
  33. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/playbooks.py +358 -0
  34. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/raw.py +73 -0
  35. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/run.py +108 -0
  36. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/users.py +272 -0
  37. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/tools/vpe.py +279 -0
  38. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/vpe/__init__.py +0 -0
  39. splunk_soar_mcp-0.1.0/src/splunk_soar_mcp/vpe/blocks.py +409 -0
  40. splunk_soar_mcp-0.1.0/tests/conftest.py +33 -0
  41. splunk_soar_mcp-0.1.0/tests/test_admin_tools.py +177 -0
  42. splunk_soar_mcp-0.1.0/tests/test_blocks.py +106 -0
  43. splunk_soar_mcp-0.1.0/tests/test_client.py +108 -0
  44. splunk_soar_mcp-0.1.0/tests/test_config.py +48 -0
  45. splunk_soar_mcp-0.1.0/tests/test_execution.py +115 -0
  46. splunk_soar_mcp-0.1.0/tests/test_formatting.py +43 -0
  47. splunk_soar_mcp-0.1.0/tests/test_playbook_source.py +43 -0
  48. splunk_soar_mcp-0.1.0/tests/test_redaction.py +92 -0
  49. 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.