domon-mcp-server 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 (33) hide show
  1. domon_mcp_server-0.1.0/PKG-INFO +269 -0
  2. domon_mcp_server-0.1.0/README.md +244 -0
  3. domon_mcp_server-0.1.0/pyproject.toml +95 -0
  4. domon_mcp_server-0.1.0/pyproject.toml.orig +72 -0
  5. domon_mcp_server-0.1.0/src/icinga_mcp/__init__.py +10 -0
  6. domon_mcp_server-0.1.0/src/icinga_mcp/__main__.py +3 -0
  7. domon_mcp_server-0.1.0/src/icinga_mcp/cli.py +179 -0
  8. domon_mcp_server-0.1.0/src/icinga_mcp/clients/__init__.py +3 -0
  9. domon_mcp_server-0.1.0/src/icinga_mcp/clients/director.py +65 -0
  10. domon_mcp_server-0.1.0/src/icinga_mcp/clients/icinga_api.py +221 -0
  11. domon_mcp_server-0.1.0/src/icinga_mcp/clients/icingaweb.py +144 -0
  12. domon_mcp_server-0.1.0/src/icinga_mcp/config.py +191 -0
  13. domon_mcp_server-0.1.0/src/icinga_mcp/errors.py +31 -0
  14. domon_mcp_server-0.1.0/src/icinga_mcp/formatting.py +81 -0
  15. domon_mcp_server-0.1.0/src/icinga_mcp/history.py +251 -0
  16. domon_mcp_server-0.1.0/src/icinga_mcp/models.py +265 -0
  17. domon_mcp_server-0.1.0/src/icinga_mcp/permissions.py +38 -0
  18. domon_mcp_server-0.1.0/src/icinga_mcp/py.typed +0 -0
  19. domon_mcp_server-0.1.0/src/icinga_mcp/redaction.py +41 -0
  20. domon_mcp_server-0.1.0/src/icinga_mcp/server.py +93 -0
  21. domon_mcp_server-0.1.0/src/icinga_mcp/timeparse.py +42 -0
  22. domon_mcp_server-0.1.0/src/icinga_mcp/tools/__init__.py +95 -0
  23. domon_mcp_server-0.1.0/src/icinga_mcp/tools/acknowledgements.py +175 -0
  24. domon_mcp_server-0.1.0/src/icinga_mcp/tools/actions.py +227 -0
  25. domon_mcp_server-0.1.0/src/icinga_mcp/tools/base.py +71 -0
  26. domon_mcp_server-0.1.0/src/icinga_mcp/tools/comments.py +143 -0
  27. domon_mcp_server-0.1.0/src/icinga_mcp/tools/convert.py +132 -0
  28. domon_mcp_server-0.1.0/src/icinga_mcp/tools/director.py +146 -0
  29. domon_mcp_server-0.1.0/src/icinga_mcp/tools/downtimes.py +342 -0
  30. domon_mcp_server-0.1.0/src/icinga_mcp/tools/history.py +120 -0
  31. domon_mcp_server-0.1.0/src/icinga_mcp/tools/objects.py +148 -0
  32. domon_mcp_server-0.1.0/src/icinga_mcp/tools/problems.py +117 -0
  33. domon_mcp_server-0.1.0/src/icinga_mcp/tools/status.py +55 -0
@@ -0,0 +1,269 @@
1
+ Metadata-Version: 2.3
2
+ Name: domon-mcp-server
3
+ Version: 0.1.0
4
+ Summary: MCP server for analysing Icinga 2 monitoring: problems, history, acknowledgements, comments and downtimes.
5
+ Keywords: mcp,icinga,icinga2,monitoring,model-context-protocol
6
+ Author: Sebastian Wolschke
7
+ Author-email: Sebastian Wolschke <sebastian.wolschke@telekom.de>
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: System Administrators
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Programming Language :: Python :: 3.14
15
+ Classifier: Topic :: System :: Monitoring
16
+ Requires-Dist: anyio>=4.9
17
+ Requires-Dist: httpx2>=2.10
18
+ Requires-Dist: mcp>=2.3,<3
19
+ Requires-Dist: pydantic>=2.12
20
+ Requires-Dist: pydantic-settings>=2.16
21
+ Requires-Python: >=3.11
22
+ Project-URL: Source, https://github.com/telekom-mms/domon-mcp-server
23
+ Project-URL: Issues, https://github.com/telekom-mms/domon-mcp-server/issues
24
+ Description-Content-Type: text/markdown
25
+
26
+ # icinga-mcp
27
+
28
+ MCP server for analysing an [Icinga 2](https://icinga.com/) monitoring setup with an LLM.
29
+ Implements the [Model Context Protocol](https://modelcontextprotocol.io/) revision `2026-07-28`
30
+ (via the official Python SDK, which also falls back to `2025-11-25` for older clients).
31
+
32
+ > Status: early development. Not yet published on PyPI.
33
+
34
+ ## Scope (v1)
35
+
36
+ - Read active problems, host/service details, comments and downtimes (Icinga 2 REST API)
37
+ - Acknowledge problems, add comments, schedule/remove downtimes (opt-in, every change is
38
+ confirmed by the user)
39
+ - Tools are grouped into toolsets that can be enabled/disabled individually; read-only by default
40
+ - Alert history via the IcingaDB Web module, optional (legacy `monitoring` module supported)
41
+ - Icinga Director configuration (read-only): hosts, templates, apply rules, commands, optional
42
+
43
+ Runs on Linux, macOS and Windows (Python 3.11+).
44
+
45
+ Creating, changing or deleting monitoring objects is intentionally out of scope.
46
+
47
+ ## Installation
48
+
49
+ icinga-mcp is started by your MCP client via [uv](https://docs.astral.sh/uv/). Install uv once:
50
+
51
+ ```bash
52
+ # Linux / macOS
53
+ curl -LsSf https://astral.sh/uv/install.sh | sh
54
+ ```
55
+
56
+ ```powershell
57
+ # Windows (PowerShell)
58
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
59
+ ```
60
+
61
+ ## Quick start (VS Code)
62
+
63
+ Add the server to your MCP configuration. Recommended: the user configuration
64
+ (command palette: **MCP: Open User Configuration**), so the credentials stay outside of any
65
+ repository. A workspace file `.vscode/mcp.json` works too, but must not be committed.
66
+
67
+ ```json
68
+ {
69
+ "servers": {
70
+ "icinga": {
71
+ "type": "stdio",
72
+ "command": "uvx",
73
+ "args": ["--from", "domon-mcp-server", "icinga-mcp"],
74
+ "env": {
75
+ "ICINGA_URL": "https://icinga-master.example.com:5665",
76
+ "ICINGA_USER": "icinga-mcp",
77
+ "ICINGA_PASSWORD": "change-me",
78
+ "ICINGAWEB_URL": "https://icinga.example.com",
79
+ "ICINGAWEB_USER": "jdoe",
80
+ "ICINGAWEB_PASSWORD": "change-me",
81
+ "ICINGA_MCP_READ_ONLY": "false",
82
+ "ICINGA_MCP_AUTHOR": "jdoe"
83
+ }
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ The `ICINGAWEB_*` lines enable the alert history and the Director tools (optional). Omit the last two lines to keep
90
+ icinga-mcp read-only. The password is stored in plain text in this file. Use a dedicated, minimally privileged
91
+ `ApiUser` (see [permissions](#icinga-2-api-permissions)) and protect the file accordingly.
92
+
93
+ Until `domon-mcp-server` is published on PyPI, run it from a local checkout instead of `uvx`:
94
+
95
+ ```json
96
+ "command": "uv",
97
+ "args": ["run", "--directory", "/path/to/icinga-mcp", "icinga-mcp"],
98
+ ```
99
+
100
+ On Windows use forward slashes or escaped backslashes in JSON paths, e.g.
101
+ `"C:/Users/me/icinga-mcp"`.
102
+
103
+ ## Configuration
104
+
105
+ All settings are read from environment variables (the `env` block of the MCP configuration).
106
+
107
+ | Variable | Required | Description |
108
+ |---|---|---|
109
+ | `ICINGA_URL` | yes | Icinga 2 API base URL, e.g. `https://icinga-master:5665` |
110
+ | `ICINGA_USER` | yes | Icinga 2 `ApiUser` name |
111
+ | `ICINGA_PASSWORD` | yes | API password |
112
+ | `ICINGA_CA_CERT` | no | Path to the CA that signed the API certificate (e.g. the Icinga CA). Setting it enables TLS certificate verification |
113
+ | `ICINGA_TLS_SERVER_NAME` | no | Expected certificate host name if it differs from the URL host (used for SNI and verification), e.g. when the API sits behind a Kubernetes ingress |
114
+ | `ICINGA_VERIFY_TLS` | no | Force verification on (`true`, e.g. for publicly trusted certificates without `ICINGA_CA_CERT`) or off (`false`). Default: on if `ICINGA_CA_CERT` is set, otherwise off |
115
+ | `ICINGA_TIMEOUT` | no | Request timeout in seconds (default `30`) |
116
+
117
+ ### Icinga Web: history and Director (optional)
118
+
119
+ The Icinga 2 API has no history and does not know the Director data model. `get_history`
120
+ reads alert history from Icinga Web 2's IcingaDB module by default, the
121
+ `director_*` tools read the configuration from the Icinga Director REST API. Both are only
122
+ available when these variables are set:
123
+
124
+ | Variable | Required | Description |
125
+ |---|---|---|
126
+ | `ICINGAWEB_URL` | yes | Icinga Web 2 root URL, e.g. `https://icinga.example.com` (or `.../icingaweb2`) |
127
+ | `ICINGAWEB_USER` | yes | Icinga Web user (needs IcingaDB module access for history by default; `monitoring` module for legacy history; Director API access for Director tools) |
128
+ | `ICINGAWEB_PASSWORD` | yes | Password (HTTP basic auth) |
129
+ | `ICINGAWEB_HISTORY_BACKEND` | no | History source: `icingadb` (default) or `monitoring` for legacy IDO installations |
130
+ | `ICINGAWEB_CA_CERT` | no | CA bundle if the web server certificate is not publicly trusted |
131
+ | `ICINGAWEB_VERIFY_TLS` | no | Default `true`; set `false` only for debugging |
132
+ | `ICINGAWEB_TIMEOUT` | no | Request timeout in seconds (default `60`) |
133
+ | `ICINGA_MCP_MAX_HISTORY` | no | Longest time window per query (default `31d`) |
134
+
135
+ ### TLS certificate verification (optional)
136
+
137
+ Icinga 2 API certificates are usually signed by the internal Icinga CA, which no operating
138
+ system trusts. By default icinga-mcp therefore connects **without certificate verification**
139
+ and logs a warning. The API password is still sent encrypted, but the server identity is not
140
+ checked, so a man-in-the-middle could capture the credentials.
141
+
142
+ To enable verification, store the CA once per instance and add to the `env` block:
143
+
144
+ ```json
145
+ "ICINGA_CA_CERT": "/home/me/.config/icinga-mcp/<instance>-ca.pem",
146
+ "ICINGA_TLS_SERVER_NAME": "<CN of the server certificate>"
147
+ ```
148
+
149
+ `ICINGA_TLS_SERVER_NAME` is only needed if the certificate name differs from the URL host.
150
+ The CA is the last certificate printed by the following command (OpenSSL is included in
151
+ Linux, macOS and Git for Windows):
152
+
153
+ ```bash
154
+ openssl s_client -connect <host>:5665 -showcerts </dev/null
155
+ ```
156
+
157
+ Compare the CA fingerprint (`openssl x509 -in <file> -noout -fingerprint -sha256`) with the
158
+ one provided by your Icinga administrators.
159
+
160
+ ### Icinga 2 API permissions
161
+
162
+ Minimal `ApiUser` permissions:
163
+
164
+ ```
165
+ object ApiUser "icinga-mcp" {
166
+ password = "..."
167
+ permissions = [
168
+ "status/query",
169
+ "objects/query/Host", "objects/query/Service",
170
+ "objects/query/HostGroup", "objects/query/ServiceGroup",
171
+ "objects/query/Comment", "objects/query/Downtime",
172
+ // only needed for write tools
173
+ "actions/acknowledge-problem", "actions/remove-acknowledgement",
174
+ "actions/add-comment", "actions/schedule-downtime", "actions/remove-downtime",
175
+ ]
176
+ }
177
+ ```
178
+
179
+ ## Tools
180
+
181
+ | Tool | Toolset | Mode | Description |
182
+ |---|---|---|---|
183
+ | `icinga_status` | `status` | read | Version, feature flags, host/service counts per state, unhandled problems |
184
+ | `list_problems` | `problems` | read | Current alerts (DOWN hosts, WARNING/CRITICAL/UNKNOWN services); filters for host/service patterns, host group, states, handled, hard states |
185
+ | `get_host` | `objects` | read | Host details incl. check output, perfdata, custom vars (redacted) and its services |
186
+ | `get_service` | `objects` | read | Service details incl. check output, perfdata, command and custom vars (redacted) |
187
+ | `list_hosts` | `objects` | read | Search hosts by name/address pattern or host group |
188
+ | `acknowledge_problem` | `acknowledgements` | write | Acknowledge problems (sticky, notify, expiry); OK or already acknowledged objects are skipped |
189
+ | `remove_acknowledgement` | `acknowledgements` | write | Remove acknowledgements |
190
+ | `list_comments` | `comments` | read | Comments and acknowledgement texts, newest first |
191
+ | `add_comment` | `comments` | write | Add a comment (note) to hosts/services |
192
+ | `list_downtimes` | `downtimes` | read | Scheduled downtimes and whether they are in effect |
193
+ | `director_list` | `director` | read | Search the Director configuration: hosts, host/service templates, service apply rules, commands, host groups, notification templates, time periods. Needs Icinga Web |
194
+ | `director_get` | `director` | read | One Director object with inherited properties (hosts/templates) and the objects that use a template or command. Needs Icinga Web |
195
+ | `get_history` | `history` | read | Alert history in a time window (`since` = `24h`, `7d` or ISO 8601): hard/soft state changes, notifications, acknowledgements, comments, downtimes, flapping; summary with the most active objects. Needs Icinga Web |
196
+ | `schedule_downtime` | `downtimes` | write | Fixed or flexible downtime (`start` = `now` or ISO 8601, `end` or `duration` like `2h`), optionally for all services of a host |
197
+ | `remove_downtime` | `downtimes` | write | Remove downtimes by name (from `list_downtimes`) |
198
+
199
+ Values below keys whose names look sensitive (`*pass*`, `*secret*`, `*token*`, `*basicauth*`,
200
+ ...) are replaced by `***REDACTED***` in all tool results. Pure macro references such as
201
+ `$snmp_password$` (e.g. in command arguments) stay visible because they contain no secret.
202
+
203
+ ### Enabling and disabling tools
204
+
205
+ | Variable | Default | Description |
206
+ |---|---|---|
207
+ | `ICINGA_MCP_TOOLSETS` | all | Comma-separated toolsets to enable, e.g. `status,problems,objects` |
208
+ | `ICINGA_MCP_DISABLED_TOOLS` | none | Comma-separated tool names to hide, e.g. `remove_downtime` |
209
+ | `ICINGA_MCP_READ_ONLY` | `true` | Hide all write tools. Set to `false` to enable them |
210
+
211
+ Disabled tools are not registered at all, so the model never sees them.
212
+ `icinga-mcp list-tools` shows the effective selection.
213
+
214
+ ### Write tools and safety
215
+
216
+ Write tools are only available with `ICINGA_MCP_READ_ONLY=false` and need these settings:
217
+
218
+ | Variable | Default | Description |
219
+ |---|---|---|
220
+ | `ICINGA_MCP_AUTHOR` | (required) | Name recorded as author in Icinga, e.g. your user name |
221
+ | `ICINGA_MCP_MAX_TARGETS` | `20` | Maximum number of objects per call |
222
+ | `ICINGA_MCP_MAX_DOWNTIME` | `14d` | Maximum length of a downtime |
223
+ | `ICINGA_MCP_REQUIRE_ELICITATION` | `false` | Refuse changes from clients that cannot ask the user (see below) |
224
+
225
+ Safety measures:
226
+
227
+ - Targets are exact object names (`host` or `host!service`), never patterns or free filters.
228
+ All targets are looked up first; unknown names abort the call before anything is changed.
229
+ - **Every change is confirmed by the user.** If the MCP client supports
230
+ [elicitation](https://modelcontextprotocol.io/specification/2026-07-28/client/elicitation)
231
+ (e.g. VS Code), the user gets a dialog listing the objects and options. Clients without
232
+ elicitation get a preview on the first call; only a second call with `confirm=true` applies
233
+ the change. In that mode the model is instructed to ask the user first, but technically it
234
+ could set `confirm=true` on its own; set `ICINGA_MCP_REQUIRE_ELICITATION=true` to rule that out.
235
+ - Results report per object whether Icinga applied the change.
236
+
237
+ ## Command line
238
+
239
+ | Command | Description |
240
+ |---|---|
241
+ | `icinga-mcp` / `icinga-mcp serve` | Run the MCP server on stdio (started by the MCP client) |
242
+ | `icinga-mcp check` | Test connection, TLS, credentials, API permissions and (if configured) Icinga Web history access |
243
+ | `icinga-mcp list-tools` | Show all tools and which ones are enabled (no credentials needed) |
244
+
245
+ `check` reads the same environment variables as the server:
246
+
247
+ ```bash
248
+ # Linux / macOS
249
+ ICINGA_URL=https://icinga-master:5665 ICINGA_USER=icinga-mcp ICINGA_PASSWORD='...' uvx --from domon-mcp-server icinga-mcp check
250
+ ```
251
+
252
+ ```powershell
253
+ # Windows (PowerShell)
254
+ $env:ICINGA_URL = "https://icinga-master:5665"; $env:ICINGA_USER = "icinga-mcp"; $env:ICINGA_PASSWORD = "..."
255
+ uvx --from domon-mcp-server icinga-mcp check
256
+ ```
257
+
258
+ ## Development
259
+
260
+ ```bash
261
+ uv sync
262
+ uv run pytest # unit tests
263
+ uv run pytest -m integration # read-only tests against a real instance (needs ICINGA_* env)
264
+ uv run ruff check .
265
+ uv run ruff format --check .
266
+ uv run mypy
267
+ ```
268
+
269
+ See [AGENTS.md](AGENTS.md) for architecture and conventions.
@@ -0,0 +1,244 @@
1
+ # icinga-mcp
2
+
3
+ MCP server for analysing an [Icinga 2](https://icinga.com/) monitoring setup with an LLM.
4
+ Implements the [Model Context Protocol](https://modelcontextprotocol.io/) revision `2026-07-28`
5
+ (via the official Python SDK, which also falls back to `2025-11-25` for older clients).
6
+
7
+ > Status: early development. Not yet published on PyPI.
8
+
9
+ ## Scope (v1)
10
+
11
+ - Read active problems, host/service details, comments and downtimes (Icinga 2 REST API)
12
+ - Acknowledge problems, add comments, schedule/remove downtimes (opt-in, every change is
13
+ confirmed by the user)
14
+ - Tools are grouped into toolsets that can be enabled/disabled individually; read-only by default
15
+ - Alert history via the IcingaDB Web module, optional (legacy `monitoring` module supported)
16
+ - Icinga Director configuration (read-only): hosts, templates, apply rules, commands, optional
17
+
18
+ Runs on Linux, macOS and Windows (Python 3.11+).
19
+
20
+ Creating, changing or deleting monitoring objects is intentionally out of scope.
21
+
22
+ ## Installation
23
+
24
+ icinga-mcp is started by your MCP client via [uv](https://docs.astral.sh/uv/). Install uv once:
25
+
26
+ ```bash
27
+ # Linux / macOS
28
+ curl -LsSf https://astral.sh/uv/install.sh | sh
29
+ ```
30
+
31
+ ```powershell
32
+ # Windows (PowerShell)
33
+ powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
34
+ ```
35
+
36
+ ## Quick start (VS Code)
37
+
38
+ Add the server to your MCP configuration. Recommended: the user configuration
39
+ (command palette: **MCP: Open User Configuration**), so the credentials stay outside of any
40
+ repository. A workspace file `.vscode/mcp.json` works too, but must not be committed.
41
+
42
+ ```json
43
+ {
44
+ "servers": {
45
+ "icinga": {
46
+ "type": "stdio",
47
+ "command": "uvx",
48
+ "args": ["--from", "domon-mcp-server", "icinga-mcp"],
49
+ "env": {
50
+ "ICINGA_URL": "https://icinga-master.example.com:5665",
51
+ "ICINGA_USER": "icinga-mcp",
52
+ "ICINGA_PASSWORD": "change-me",
53
+ "ICINGAWEB_URL": "https://icinga.example.com",
54
+ "ICINGAWEB_USER": "jdoe",
55
+ "ICINGAWEB_PASSWORD": "change-me",
56
+ "ICINGA_MCP_READ_ONLY": "false",
57
+ "ICINGA_MCP_AUTHOR": "jdoe"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ ```
63
+
64
+ The `ICINGAWEB_*` lines enable the alert history and the Director tools (optional). Omit the last two lines to keep
65
+ icinga-mcp read-only. The password is stored in plain text in this file. Use a dedicated, minimally privileged
66
+ `ApiUser` (see [permissions](#icinga-2-api-permissions)) and protect the file accordingly.
67
+
68
+ Until `domon-mcp-server` is published on PyPI, run it from a local checkout instead of `uvx`:
69
+
70
+ ```json
71
+ "command": "uv",
72
+ "args": ["run", "--directory", "/path/to/icinga-mcp", "icinga-mcp"],
73
+ ```
74
+
75
+ On Windows use forward slashes or escaped backslashes in JSON paths, e.g.
76
+ `"C:/Users/me/icinga-mcp"`.
77
+
78
+ ## Configuration
79
+
80
+ All settings are read from environment variables (the `env` block of the MCP configuration).
81
+
82
+ | Variable | Required | Description |
83
+ |---|---|---|
84
+ | `ICINGA_URL` | yes | Icinga 2 API base URL, e.g. `https://icinga-master:5665` |
85
+ | `ICINGA_USER` | yes | Icinga 2 `ApiUser` name |
86
+ | `ICINGA_PASSWORD` | yes | API password |
87
+ | `ICINGA_CA_CERT` | no | Path to the CA that signed the API certificate (e.g. the Icinga CA). Setting it enables TLS certificate verification |
88
+ | `ICINGA_TLS_SERVER_NAME` | no | Expected certificate host name if it differs from the URL host (used for SNI and verification), e.g. when the API sits behind a Kubernetes ingress |
89
+ | `ICINGA_VERIFY_TLS` | no | Force verification on (`true`, e.g. for publicly trusted certificates without `ICINGA_CA_CERT`) or off (`false`). Default: on if `ICINGA_CA_CERT` is set, otherwise off |
90
+ | `ICINGA_TIMEOUT` | no | Request timeout in seconds (default `30`) |
91
+
92
+ ### Icinga Web: history and Director (optional)
93
+
94
+ The Icinga 2 API has no history and does not know the Director data model. `get_history`
95
+ reads alert history from Icinga Web 2's IcingaDB module by default, the
96
+ `director_*` tools read the configuration from the Icinga Director REST API. Both are only
97
+ available when these variables are set:
98
+
99
+ | Variable | Required | Description |
100
+ |---|---|---|
101
+ | `ICINGAWEB_URL` | yes | Icinga Web 2 root URL, e.g. `https://icinga.example.com` (or `.../icingaweb2`) |
102
+ | `ICINGAWEB_USER` | yes | Icinga Web user (needs IcingaDB module access for history by default; `monitoring` module for legacy history; Director API access for Director tools) |
103
+ | `ICINGAWEB_PASSWORD` | yes | Password (HTTP basic auth) |
104
+ | `ICINGAWEB_HISTORY_BACKEND` | no | History source: `icingadb` (default) or `monitoring` for legacy IDO installations |
105
+ | `ICINGAWEB_CA_CERT` | no | CA bundle if the web server certificate is not publicly trusted |
106
+ | `ICINGAWEB_VERIFY_TLS` | no | Default `true`; set `false` only for debugging |
107
+ | `ICINGAWEB_TIMEOUT` | no | Request timeout in seconds (default `60`) |
108
+ | `ICINGA_MCP_MAX_HISTORY` | no | Longest time window per query (default `31d`) |
109
+
110
+ ### TLS certificate verification (optional)
111
+
112
+ Icinga 2 API certificates are usually signed by the internal Icinga CA, which no operating
113
+ system trusts. By default icinga-mcp therefore connects **without certificate verification**
114
+ and logs a warning. The API password is still sent encrypted, but the server identity is not
115
+ checked, so a man-in-the-middle could capture the credentials.
116
+
117
+ To enable verification, store the CA once per instance and add to the `env` block:
118
+
119
+ ```json
120
+ "ICINGA_CA_CERT": "/home/me/.config/icinga-mcp/<instance>-ca.pem",
121
+ "ICINGA_TLS_SERVER_NAME": "<CN of the server certificate>"
122
+ ```
123
+
124
+ `ICINGA_TLS_SERVER_NAME` is only needed if the certificate name differs from the URL host.
125
+ The CA is the last certificate printed by the following command (OpenSSL is included in
126
+ Linux, macOS and Git for Windows):
127
+
128
+ ```bash
129
+ openssl s_client -connect <host>:5665 -showcerts </dev/null
130
+ ```
131
+
132
+ Compare the CA fingerprint (`openssl x509 -in <file> -noout -fingerprint -sha256`) with the
133
+ one provided by your Icinga administrators.
134
+
135
+ ### Icinga 2 API permissions
136
+
137
+ Minimal `ApiUser` permissions:
138
+
139
+ ```
140
+ object ApiUser "icinga-mcp" {
141
+ password = "..."
142
+ permissions = [
143
+ "status/query",
144
+ "objects/query/Host", "objects/query/Service",
145
+ "objects/query/HostGroup", "objects/query/ServiceGroup",
146
+ "objects/query/Comment", "objects/query/Downtime",
147
+ // only needed for write tools
148
+ "actions/acknowledge-problem", "actions/remove-acknowledgement",
149
+ "actions/add-comment", "actions/schedule-downtime", "actions/remove-downtime",
150
+ ]
151
+ }
152
+ ```
153
+
154
+ ## Tools
155
+
156
+ | Tool | Toolset | Mode | Description |
157
+ |---|---|---|---|
158
+ | `icinga_status` | `status` | read | Version, feature flags, host/service counts per state, unhandled problems |
159
+ | `list_problems` | `problems` | read | Current alerts (DOWN hosts, WARNING/CRITICAL/UNKNOWN services); filters for host/service patterns, host group, states, handled, hard states |
160
+ | `get_host` | `objects` | read | Host details incl. check output, perfdata, custom vars (redacted) and its services |
161
+ | `get_service` | `objects` | read | Service details incl. check output, perfdata, command and custom vars (redacted) |
162
+ | `list_hosts` | `objects` | read | Search hosts by name/address pattern or host group |
163
+ | `acknowledge_problem` | `acknowledgements` | write | Acknowledge problems (sticky, notify, expiry); OK or already acknowledged objects are skipped |
164
+ | `remove_acknowledgement` | `acknowledgements` | write | Remove acknowledgements |
165
+ | `list_comments` | `comments` | read | Comments and acknowledgement texts, newest first |
166
+ | `add_comment` | `comments` | write | Add a comment (note) to hosts/services |
167
+ | `list_downtimes` | `downtimes` | read | Scheduled downtimes and whether they are in effect |
168
+ | `director_list` | `director` | read | Search the Director configuration: hosts, host/service templates, service apply rules, commands, host groups, notification templates, time periods. Needs Icinga Web |
169
+ | `director_get` | `director` | read | One Director object with inherited properties (hosts/templates) and the objects that use a template or command. Needs Icinga Web |
170
+ | `get_history` | `history` | read | Alert history in a time window (`since` = `24h`, `7d` or ISO 8601): hard/soft state changes, notifications, acknowledgements, comments, downtimes, flapping; summary with the most active objects. Needs Icinga Web |
171
+ | `schedule_downtime` | `downtimes` | write | Fixed or flexible downtime (`start` = `now` or ISO 8601, `end` or `duration` like `2h`), optionally for all services of a host |
172
+ | `remove_downtime` | `downtimes` | write | Remove downtimes by name (from `list_downtimes`) |
173
+
174
+ Values below keys whose names look sensitive (`*pass*`, `*secret*`, `*token*`, `*basicauth*`,
175
+ ...) are replaced by `***REDACTED***` in all tool results. Pure macro references such as
176
+ `$snmp_password$` (e.g. in command arguments) stay visible because they contain no secret.
177
+
178
+ ### Enabling and disabling tools
179
+
180
+ | Variable | Default | Description |
181
+ |---|---|---|
182
+ | `ICINGA_MCP_TOOLSETS` | all | Comma-separated toolsets to enable, e.g. `status,problems,objects` |
183
+ | `ICINGA_MCP_DISABLED_TOOLS` | none | Comma-separated tool names to hide, e.g. `remove_downtime` |
184
+ | `ICINGA_MCP_READ_ONLY` | `true` | Hide all write tools. Set to `false` to enable them |
185
+
186
+ Disabled tools are not registered at all, so the model never sees them.
187
+ `icinga-mcp list-tools` shows the effective selection.
188
+
189
+ ### Write tools and safety
190
+
191
+ Write tools are only available with `ICINGA_MCP_READ_ONLY=false` and need these settings:
192
+
193
+ | Variable | Default | Description |
194
+ |---|---|---|
195
+ | `ICINGA_MCP_AUTHOR` | (required) | Name recorded as author in Icinga, e.g. your user name |
196
+ | `ICINGA_MCP_MAX_TARGETS` | `20` | Maximum number of objects per call |
197
+ | `ICINGA_MCP_MAX_DOWNTIME` | `14d` | Maximum length of a downtime |
198
+ | `ICINGA_MCP_REQUIRE_ELICITATION` | `false` | Refuse changes from clients that cannot ask the user (see below) |
199
+
200
+ Safety measures:
201
+
202
+ - Targets are exact object names (`host` or `host!service`), never patterns or free filters.
203
+ All targets are looked up first; unknown names abort the call before anything is changed.
204
+ - **Every change is confirmed by the user.** If the MCP client supports
205
+ [elicitation](https://modelcontextprotocol.io/specification/2026-07-28/client/elicitation)
206
+ (e.g. VS Code), the user gets a dialog listing the objects and options. Clients without
207
+ elicitation get a preview on the first call; only a second call with `confirm=true` applies
208
+ the change. In that mode the model is instructed to ask the user first, but technically it
209
+ could set `confirm=true` on its own; set `ICINGA_MCP_REQUIRE_ELICITATION=true` to rule that out.
210
+ - Results report per object whether Icinga applied the change.
211
+
212
+ ## Command line
213
+
214
+ | Command | Description |
215
+ |---|---|
216
+ | `icinga-mcp` / `icinga-mcp serve` | Run the MCP server on stdio (started by the MCP client) |
217
+ | `icinga-mcp check` | Test connection, TLS, credentials, API permissions and (if configured) Icinga Web history access |
218
+ | `icinga-mcp list-tools` | Show all tools and which ones are enabled (no credentials needed) |
219
+
220
+ `check` reads the same environment variables as the server:
221
+
222
+ ```bash
223
+ # Linux / macOS
224
+ ICINGA_URL=https://icinga-master:5665 ICINGA_USER=icinga-mcp ICINGA_PASSWORD='...' uvx --from domon-mcp-server icinga-mcp check
225
+ ```
226
+
227
+ ```powershell
228
+ # Windows (PowerShell)
229
+ $env:ICINGA_URL = "https://icinga-master:5665"; $env:ICINGA_USER = "icinga-mcp"; $env:ICINGA_PASSWORD = "..."
230
+ uvx --from domon-mcp-server icinga-mcp check
231
+ ```
232
+
233
+ ## Development
234
+
235
+ ```bash
236
+ uv sync
237
+ uv run pytest # unit tests
238
+ uv run pytest -m integration # read-only tests against a real instance (needs ICINGA_* env)
239
+ uv run ruff check .
240
+ uv run ruff format --check .
241
+ uv run mypy
242
+ ```
243
+
244
+ See [AGENTS.md](AGENTS.md) for architecture and conventions.
@@ -0,0 +1,95 @@
1
+ [project]
2
+ name = "domon-mcp-server"
3
+ version = "0.1.0"
4
+ description = "MCP server for analysing Icinga 2 monitoring: problems, history, acknowledgements, comments and downtimes."
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ keywords = [
8
+ "mcp",
9
+ "icinga",
10
+ "icinga2",
11
+ "monitoring",
12
+ "model-context-protocol",
13
+ ]
14
+ classifiers = [
15
+ "Development Status :: 3 - Alpha",
16
+ "Intended Audience :: System Administrators",
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Topic :: System :: Monitoring",
23
+ ]
24
+ dependencies = [
25
+ "anyio>=4.9",
26
+ "httpx2>=2.10",
27
+ "mcp>=2.3,<3",
28
+ "pydantic>=2.12",
29
+ "pydantic-settings>=2.16",
30
+ ]
31
+
32
+ [[project.authors]]
33
+ name = "Sebastian Wolschke"
34
+ email = "sebastian.wolschke@telekom.de"
35
+
36
+ [project.scripts]
37
+ icinga-mcp = "icinga_mcp.cli:main"
38
+
39
+ [project.urls]
40
+ Source = "https://github.com/telekom-mms/domon-mcp-server"
41
+ Issues = "https://github.com/telekom-mms/domon-mcp-server/issues"
42
+
43
+ [build-system]
44
+ requires = ["uv_build>=0.11.7,<0.12.0"]
45
+ build-backend = "uv_build"
46
+
47
+ [tool.uv.build-backend]
48
+ module-name = "icinga_mcp"
49
+
50
+ [tool.ruff]
51
+ line-length = 100
52
+ target-version = "py311"
53
+
54
+ [tool.ruff.lint]
55
+ select = [
56
+ "E",
57
+ "F",
58
+ "W",
59
+ "I",
60
+ "B",
61
+ "UP",
62
+ "S",
63
+ "SIM",
64
+ "RUF",
65
+ "ASYNC",
66
+ ]
67
+
68
+ [tool.ruff.lint.per-file-ignores]
69
+ "tests/**" = [
70
+ "S101",
71
+ "S105",
72
+ "S106",
73
+ ]
74
+
75
+ [tool.mypy]
76
+ strict = true
77
+ plugins = ["pydantic.mypy"]
78
+ python_version = "3.11"
79
+ files = [
80
+ "src",
81
+ "tests",
82
+ ]
83
+
84
+ [tool.pytest.ini_options]
85
+ testpaths = ["tests"]
86
+ addopts = "-ra -m 'not integration'"
87
+ markers = ["integration: tests against a real Icinga 2 instance (requires ICINGA_* environment)"]
88
+
89
+ [dependency-groups]
90
+ dev = [
91
+ "anyio>=4.15.1",
92
+ "mypy>=2.4.0",
93
+ "pytest>=9.1.1",
94
+ "ruff>=0.17.0",
95
+ ]
@@ -0,0 +1,72 @@
1
+ [project]
2
+ name = "domon-mcp-server"
3
+ version = "0.1.0"
4
+ description = "MCP server for analysing Icinga 2 monitoring: problems, history, acknowledgements, comments and downtimes."
5
+ authors = [
6
+ { name = "Sebastian Wolschke", email = "sebastian.wolschke@telekom.de" }
7
+ ]
8
+ readme = "README.md"
9
+ requires-python = ">=3.11"
10
+ keywords = ["mcp", "icinga", "icinga2", "monitoring", "model-context-protocol"]
11
+ classifiers = [
12
+ "Development Status :: 3 - Alpha",
13
+ "Intended Audience :: System Administrators",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Topic :: System :: Monitoring",
20
+ ]
21
+ dependencies = [
22
+ "anyio>=4.9",
23
+ "httpx2>=2.10",
24
+ "mcp>=2.3,<3",
25
+ "pydantic>=2.12",
26
+ "pydantic-settings>=2.16",
27
+ ]
28
+
29
+ [project.scripts]
30
+ icinga-mcp = "icinga_mcp.cli:main"
31
+
32
+ [project.urls]
33
+ Source = "https://github.com/telekom-mms/domon-mcp-server"
34
+ Issues = "https://github.com/telekom-mms/domon-mcp-server/issues"
35
+
36
+ [build-system]
37
+ requires = ["uv_build>=0.11.7,<0.12.0"]
38
+ build-backend = "uv_build"
39
+
40
+ [tool.uv.build-backend]
41
+ module-name = "icinga_mcp"
42
+
43
+ [tool.ruff]
44
+ line-length = 100
45
+ target-version = "py311"
46
+
47
+ [tool.ruff.lint]
48
+ select = ["E", "F", "W", "I", "B", "UP", "S", "SIM", "RUF", "ASYNC"]
49
+
50
+ [tool.ruff.lint.per-file-ignores]
51
+ "tests/**" = ["S101", "S105", "S106"]
52
+
53
+ [tool.mypy]
54
+ strict = true
55
+ plugins = ["pydantic.mypy"]
56
+ python_version = "3.11"
57
+ files = ["src", "tests"]
58
+
59
+ [tool.pytest.ini_options]
60
+ testpaths = ["tests"]
61
+ addopts = "-ra -m 'not integration'"
62
+ markers = [
63
+ "integration: tests against a real Icinga 2 instance (requires ICINGA_* environment)",
64
+ ]
65
+
66
+ [dependency-groups]
67
+ dev = [
68
+ "anyio>=4.15.1",
69
+ "mypy>=2.4.0",
70
+ "pytest>=9.1.1",
71
+ "ruff>=0.17.0",
72
+ ]