rootly-mcp-server 2.1.2__tar.gz → 2.1.3__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 (62) hide show
  1. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.gitignore +4 -2
  2. rootly_mcp_server-2.1.3/CONTRIBUTING.md +57 -0
  3. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/PKG-INFO +38 -164
  4. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/README.md +37 -163
  5. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/pyproject.toml +1 -1
  6. rootly_mcp_server-2.1.3/src/rootly_mcp_server/och_client.py +71 -0
  7. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/server.py +299 -0
  8. rootly_mcp_server-2.1.3/tests/unit/test_och_client.py +282 -0
  9. rootly_mcp_server-2.1.2/#Dockerfile# +0 -29
  10. rootly_mcp_server-2.1.2/.beads/.gitignore +0 -44
  11. rootly_mcp_server-2.1.2/.beads/README.md +0 -81
  12. rootly_mcp_server-2.1.2/.beads/config.yaml +0 -62
  13. rootly_mcp_server-2.1.2/.beads/interactions.jsonl +0 -0
  14. rootly_mcp_server-2.1.2/.beads/metadata.json +0 -4
  15. rootly_mcp_server-2.1.2/2026-01-27-MCP.txt +0 -643
  16. rootly_mcp_server-2.1.2/2026-01-27-claude-code-v2120.txt +0 -1215
  17. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.beads/issues.jsonl +0 -0
  18. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.gitattributes +0 -0
  19. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.github/dependabot.yml +0 -0
  20. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.github/workflows/ci.yml +0 -0
  21. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.github/workflows/lint.yml +0 -0
  22. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.github/workflows/pypi-release.yml +0 -0
  23. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.github/workflows/test.yml +0 -0
  24. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.semaphore/deploy.yml +0 -0
  25. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.semaphore/semaphore.yml +0 -0
  26. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/.semaphore/update-task-definition.sh +0 -0
  27. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/Dockerfile +0 -0
  28. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/LICENSE +0 -0
  29. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/examples/skills/README.md +0 -0
  30. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/rootly-mcp-server-demo.gif +0 -0
  31. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/rootly_openapi.json +0 -0
  32. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/scripts/setup-hooks.sh +0 -0
  33. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/__init__.py +0 -0
  34. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/__main__.py +0 -0
  35. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/client.py +0 -0
  36. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/data/__init__.py +0 -0
  37. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/exceptions.py +0 -0
  38. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/monitoring.py +0 -0
  39. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/pagination.py +0 -0
  40. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/security.py +0 -0
  41. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/smart_utils.py +0 -0
  42. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/texttest.json +0 -0
  43. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/utils.py +0 -0
  44. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/validators.py +0 -0
  45. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/README.md +0 -0
  46. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/conftest.py +0 -0
  47. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/integration/local/test_basic.py +0 -0
  48. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/integration/local/test_smart_tools.py +0 -0
  49. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/integration/remote/test_essential.py +0 -0
  50. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/test_client.py +0 -0
  51. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_authentication.py +0 -0
  52. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_exceptions.py +0 -0
  53. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_oncall_handoff.py +0 -0
  54. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_oncall_metrics.py +0 -0
  55. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_oncall_new_tools.py +0 -0
  56. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_security.py +0 -0
  57. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_server.py +0 -0
  58. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_smart_utils.py +0 -0
  59. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_tools.py +0 -0
  60. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_utils.py +0 -0
  61. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/tests/unit/test_validators.py +0 -0
  62. {rootly_mcp_server-2.1.2 → rootly_mcp_server-2.1.3}/uv.lock +0 -0
@@ -189,6 +189,8 @@ swagger.json
189
189
  test_output/
190
190
  *.tmp
191
191
 
192
- # Markdown files (exclude all except README)
192
+ # Markdown files (exclude all except README and CONTRIBUTING)
193
193
  *.md
194
- !README.md
194
+ !README.md
195
+ !CONTRIBUTING.md
196
+ !CHANGELOG.md.beads/
@@ -0,0 +1,57 @@
1
+ # Contributing to Rootly MCP Server
2
+
3
+ ## Submitting Changes
4
+
5
+ 1. Fork the repository and create a feature branch
6
+ 2. Make your changes with clear, atomic commits
7
+ 3. Open a Pull Request with a description that clearly explains:
8
+ - What the change does
9
+ - Why it's needed
10
+ - Any breaking changes or migration steps
11
+
12
+ ## Developer Setup
13
+
14
+ ### Prerequisites
15
+ - Python 3.12 or higher
16
+ - [`uv`](https://github.com/astral-sh/uv) for dependency management
17
+
18
+ ### 1. Set Up Virtual Environment
19
+
20
+ Create and activate a virtual environment:
21
+
22
+ ```bash
23
+ uv venv .venv
24
+ source .venv/bin/activate # Always activate before running scripts
25
+ ```
26
+
27
+ ### 2. Install Dependencies
28
+
29
+ Install all project dependencies:
30
+
31
+ ```bash
32
+ uv pip install .
33
+ ```
34
+
35
+ To add new dependencies during development:
36
+ ```bash
37
+ uv pip install <package>
38
+ ```
39
+
40
+ ### 3. Set Up Git Hooks (Recommended)
41
+
42
+ Install pre-commit hooks to automatically run linting and tests before commits:
43
+
44
+ ```bash
45
+ ./scripts/setup-hooks.sh
46
+ ```
47
+
48
+ This ensures code quality by running:
49
+ - Ruff linting
50
+ - Pyright type checking
51
+ - Unit tests
52
+
53
+ ### 4. Verify Installation
54
+
55
+ The server should now be ready to use with your MCP-compatible editor.
56
+
57
+ Additional testing tools are available in the `tests/` directory.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rootly-mcp-server
3
- Version: 2.1.2
3
+ Version: 2.1.3
4
4
  Summary: Secure Model Context Protocol server for Rootly APIs with AI SRE capabilities, comprehensive error handling, and input validation
5
5
  Project-URL: Homepage, https://github.com/Rootly-AI-Labs/Rootly-MCP-server
6
6
  Project-URL: Issues, https://github.com/Rootly-AI-Labs/Rootly-MCP-server/issues
@@ -113,27 +113,6 @@ Configure your MCP-compatible editor (tested with Cursor) with one of the config
113
113
  }
114
114
  ```
115
115
 
116
- To customize `allowed_paths` and access additional Rootly API paths, clone the repository and use this configuration:
117
-
118
- ```json
119
- {
120
- "mcpServers": {
121
- "rootly": {
122
- "command": "uv",
123
- "args": [
124
- "run",
125
- "--directory",
126
- "/path/to/rootly-mcp-server",
127
- "rootly-mcp-server"
128
- ],
129
- "env": {
130
- "ROOTLY_API_TOKEN": "<YOUR_ROOTLY_API_TOKEN>"
131
- }
132
- }
133
- }
134
- }
135
- ```
136
-
137
116
  ### Connect to Hosted MCP Server
138
117
 
139
118
  Alternatively, connect directly to our hosted MCP server:
@@ -168,6 +147,41 @@ Alternatively, connect directly to our hosted MCP server:
168
147
  - **`suggest_solutions`**: Mines past incident resolutions to recommend actionable solutions
169
148
  - **MCP Resources**: Exposes incident and team data as structured resources for easy AI reference
170
149
  - **Intelligent Pattern Recognition**: Automatically identifies services, error types, and resolution patterns
150
+ - **On-Call Health Integration**: Detects burnout risk in scheduled responders
151
+
152
+ ## On-Call Health Integration
153
+
154
+ Rootly MCP integrates with [On-Call Health](https://oncallhealth.ai) to detect burnout risk in scheduled responders.
155
+
156
+ ### Setup
157
+
158
+ Set the `ONCALLHEALTH_API_KEY` environment variable:
159
+
160
+ ```json
161
+ {
162
+ "mcpServers": {
163
+ "rootly": {
164
+ "command": "uvx",
165
+ "args": ["rootly-mcp-server"],
166
+ "env": {
167
+ "ROOTLY_API_TOKEN": "your_rootly_token",
168
+ "ONCALLHEALTH_API_KEY": "och_live_your_key"
169
+ }
170
+ }
171
+ }
172
+ }
173
+ ```
174
+
175
+ ### Usage
176
+
177
+ ```
178
+ check_oncall_burnout_risk(
179
+ start_date="2026-02-09",
180
+ end_date="2026-02-15"
181
+ )
182
+ ```
183
+
184
+ Returns at-risk users who are scheduled, recommended safe replacements, and action summaries.
171
185
 
172
186
  ## Example Skills
173
187
 
@@ -196,103 +210,6 @@ cp examples/skills/rootly-incident-responder.md .claude/skills/
196
210
 
197
211
  This skill demonstrates a complete incident response workflow using Rootly's intelligent tools combined with GitHub integration for code correlation.
198
212
 
199
- ### Available Tools
200
-
201
- **Alerts**
202
- - `listIncidentAlerts`
203
- - `listAlerts`
204
- - `attachAlert`
205
- - `createAlert`
206
-
207
- **Environments**
208
- - `listEnvironments`
209
- - `createEnvironment`
210
-
211
- **Functionalities**
212
- - `listFunctionalities`
213
- - `createFunctionality`
214
-
215
- **Workflows**
216
- - `listWorkflows`
217
- - `createWorkflow`
218
-
219
- **Incidents**
220
- - `listIncidentActionItems`
221
- - `createIncidentActionItem`
222
- - `listIncident_Types`
223
- - `createIncidentType`
224
- - `search_incidents`
225
- - `find_related_incidents`
226
- - `suggest_solutions`
227
-
228
- **On-Call**
229
- - `get_oncall_shift_metrics`
230
- - `get_oncall_handoff_summary`
231
- - `get_shift_incidents`
232
-
233
- **Services & Severities**
234
- - `listServices`
235
- - `createService`
236
- - `listSeverities`
237
- - `createSeverity`
238
-
239
- **Teams & Users**
240
- - `listTeams`
241
- - `createTeam`
242
- - `listUsers`
243
- - `getCurrentUser`
244
-
245
- **Meta**
246
- - `list_endpoints`
247
-
248
- ### Why Path Limiting?
249
-
250
- We limit exposed API paths for two key reasons:
251
-
252
- 1. **Context Management**: Rootly's comprehensive API can overwhelm AI agents, affecting their ability to perform simple tasks effectively
253
- 2. **Security**: Controls which information and actions are accessible through the MCP server
254
-
255
- To expose additional paths, modify the `allowed_paths` variable in `src/rootly_mcp_server/server.py`.
256
-
257
- ### Smart Analysis Tools
258
-
259
- The MCP server includes intelligent tools that analyze historical incident data to provide actionable insights:
260
-
261
- #### `find_related_incidents`
262
- Finds historically similar incidents using text similarity analysis:
263
- ```
264
- find_related_incidents(incident_id="12345", similarity_threshold=0.15, max_results=5)
265
- ```
266
- - **Input**: Incident ID, similarity threshold (0.0-1.0), max results
267
- - **Output**: Similar incidents with confidence scores, matched services, and resolution times
268
- - **Use Case**: Get context from past incidents to understand patterns and solutions
269
-
270
- #### `suggest_solutions`
271
- Recommends solutions by analyzing how similar incidents were resolved:
272
- ```
273
- suggest_solutions(incident_id="12345", max_solutions=3)
274
- # OR for new incidents:
275
- suggest_solutions(incident_title="Payment API errors", incident_description="Users getting 500 errors during checkout")
276
- ```
277
- - **Input**: Either incident ID OR title/description text
278
- - **Output**: Actionable solution recommendations with confidence scores and time estimates
279
- - **Use Case**: Get intelligent suggestions based on successful past resolutions
280
-
281
- #### How It Works
282
- - **Text Similarity**: Uses TF-IDF vectorization and cosine similarity (scikit-learn)
283
- - **Service Detection**: Automatically identifies affected services from incident text
284
- - **Pattern Recognition**: Finds common error types, resolution patterns, and time estimates
285
- - **Fallback Mode**: Works without ML libraries using keyword-based similarity
286
- - **Solution Mining**: Extracts actionable steps from resolution summaries
287
-
288
- #### Data Requirements
289
- For optimal results, ensure your Rootly incidents have descriptive:
290
- - **Titles**: Clear, specific incident descriptions
291
- - **Summaries**: Detailed resolution steps when closing incidents
292
- - **Service Tags**: Proper service identification
293
-
294
- Example good resolution summary: `"Restarted auth-service, cleared Redis cache, and increased connection pool from 10 to 50"`
295
-
296
213
  ### On-Call Shift Metrics
297
214
 
298
215
  Get on-call shift metrics for any time period, grouped by user, team, or schedule. Includes primary/secondary role tracking, shift counts, hours, and days on-call.
@@ -344,52 +261,9 @@ get_shift_incidents(
344
261
  Returns: `incidents` list + `summary` (counts, avg resolution time, grouping)
345
262
 
346
263
 
347
- ## Developer Setup & Troubleshooting
348
-
349
- ### Prerequisites
350
- - Python 3.12 or higher
351
- - [`uv`](https://github.com/astral-sh/uv) for dependency management
352
-
353
- ### 1. Set Up Virtual Environment
354
-
355
- Create and activate a virtual environment:
356
-
357
- ```bash
358
- uv venv .venv
359
- source .venv/bin/activate # Always activate before running scripts
360
- ```
361
-
362
- ### 2. Install Dependencies
363
-
364
- Install all project dependencies:
365
-
366
- ```bash
367
- uv pip install .
368
- ```
369
-
370
- To add new dependencies during development:
371
- ```bash
372
- uv pip install <package>
373
- ```
374
-
375
- ### 3. Set Up Git Hooks (Recommended for Contributors)
376
-
377
- Install pre-commit hooks to automatically run linting and tests before commits:
378
-
379
- ```bash
380
- ./scripts/setup-hooks.sh
381
- ```
382
-
383
- This ensures code quality by running:
384
- - Ruff linting
385
- - Pyright type checking
386
- - Unit tests
387
-
388
- ### 4. Verify Installation
389
-
390
- The server should now be ready to use with your MCP-compatible editor.
264
+ ## Contributing
391
265
 
392
- **For developers:** Additional testing tools are available in the `tests/` directory.
266
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for developer setup and guidelines.
393
267
 
394
268
  ## Play with it on Postman
395
269
  [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/45004446-1074ba3c-44fe-40e3-a932-af7c071b96eb?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D45004446-1074ba3c-44fe-40e3-a932-af7c071b96eb%26entityType%3Dcollection%26workspaceId%3D4bec6e3c-50a0-4746-85f1-00a703c32f24)
@@ -74,27 +74,6 @@ Configure your MCP-compatible editor (tested with Cursor) with one of the config
74
74
  }
75
75
  ```
76
76
 
77
- To customize `allowed_paths` and access additional Rootly API paths, clone the repository and use this configuration:
78
-
79
- ```json
80
- {
81
- "mcpServers": {
82
- "rootly": {
83
- "command": "uv",
84
- "args": [
85
- "run",
86
- "--directory",
87
- "/path/to/rootly-mcp-server",
88
- "rootly-mcp-server"
89
- ],
90
- "env": {
91
- "ROOTLY_API_TOKEN": "<YOUR_ROOTLY_API_TOKEN>"
92
- }
93
- }
94
- }
95
- }
96
- ```
97
-
98
77
  ### Connect to Hosted MCP Server
99
78
 
100
79
  Alternatively, connect directly to our hosted MCP server:
@@ -129,6 +108,41 @@ Alternatively, connect directly to our hosted MCP server:
129
108
  - **`suggest_solutions`**: Mines past incident resolutions to recommend actionable solutions
130
109
  - **MCP Resources**: Exposes incident and team data as structured resources for easy AI reference
131
110
  - **Intelligent Pattern Recognition**: Automatically identifies services, error types, and resolution patterns
111
+ - **On-Call Health Integration**: Detects burnout risk in scheduled responders
112
+
113
+ ## On-Call Health Integration
114
+
115
+ Rootly MCP integrates with [On-Call Health](https://oncallhealth.ai) to detect burnout risk in scheduled responders.
116
+
117
+ ### Setup
118
+
119
+ Set the `ONCALLHEALTH_API_KEY` environment variable:
120
+
121
+ ```json
122
+ {
123
+ "mcpServers": {
124
+ "rootly": {
125
+ "command": "uvx",
126
+ "args": ["rootly-mcp-server"],
127
+ "env": {
128
+ "ROOTLY_API_TOKEN": "your_rootly_token",
129
+ "ONCALLHEALTH_API_KEY": "och_live_your_key"
130
+ }
131
+ }
132
+ }
133
+ }
134
+ ```
135
+
136
+ ### Usage
137
+
138
+ ```
139
+ check_oncall_burnout_risk(
140
+ start_date="2026-02-09",
141
+ end_date="2026-02-15"
142
+ )
143
+ ```
144
+
145
+ Returns at-risk users who are scheduled, recommended safe replacements, and action summaries.
132
146
 
133
147
  ## Example Skills
134
148
 
@@ -157,103 +171,6 @@ cp examples/skills/rootly-incident-responder.md .claude/skills/
157
171
 
158
172
  This skill demonstrates a complete incident response workflow using Rootly's intelligent tools combined with GitHub integration for code correlation.
159
173
 
160
- ### Available Tools
161
-
162
- **Alerts**
163
- - `listIncidentAlerts`
164
- - `listAlerts`
165
- - `attachAlert`
166
- - `createAlert`
167
-
168
- **Environments**
169
- - `listEnvironments`
170
- - `createEnvironment`
171
-
172
- **Functionalities**
173
- - `listFunctionalities`
174
- - `createFunctionality`
175
-
176
- **Workflows**
177
- - `listWorkflows`
178
- - `createWorkflow`
179
-
180
- **Incidents**
181
- - `listIncidentActionItems`
182
- - `createIncidentActionItem`
183
- - `listIncident_Types`
184
- - `createIncidentType`
185
- - `search_incidents`
186
- - `find_related_incidents`
187
- - `suggest_solutions`
188
-
189
- **On-Call**
190
- - `get_oncall_shift_metrics`
191
- - `get_oncall_handoff_summary`
192
- - `get_shift_incidents`
193
-
194
- **Services & Severities**
195
- - `listServices`
196
- - `createService`
197
- - `listSeverities`
198
- - `createSeverity`
199
-
200
- **Teams & Users**
201
- - `listTeams`
202
- - `createTeam`
203
- - `listUsers`
204
- - `getCurrentUser`
205
-
206
- **Meta**
207
- - `list_endpoints`
208
-
209
- ### Why Path Limiting?
210
-
211
- We limit exposed API paths for two key reasons:
212
-
213
- 1. **Context Management**: Rootly's comprehensive API can overwhelm AI agents, affecting their ability to perform simple tasks effectively
214
- 2. **Security**: Controls which information and actions are accessible through the MCP server
215
-
216
- To expose additional paths, modify the `allowed_paths` variable in `src/rootly_mcp_server/server.py`.
217
-
218
- ### Smart Analysis Tools
219
-
220
- The MCP server includes intelligent tools that analyze historical incident data to provide actionable insights:
221
-
222
- #### `find_related_incidents`
223
- Finds historically similar incidents using text similarity analysis:
224
- ```
225
- find_related_incidents(incident_id="12345", similarity_threshold=0.15, max_results=5)
226
- ```
227
- - **Input**: Incident ID, similarity threshold (0.0-1.0), max results
228
- - **Output**: Similar incidents with confidence scores, matched services, and resolution times
229
- - **Use Case**: Get context from past incidents to understand patterns and solutions
230
-
231
- #### `suggest_solutions`
232
- Recommends solutions by analyzing how similar incidents were resolved:
233
- ```
234
- suggest_solutions(incident_id="12345", max_solutions=3)
235
- # OR for new incidents:
236
- suggest_solutions(incident_title="Payment API errors", incident_description="Users getting 500 errors during checkout")
237
- ```
238
- - **Input**: Either incident ID OR title/description text
239
- - **Output**: Actionable solution recommendations with confidence scores and time estimates
240
- - **Use Case**: Get intelligent suggestions based on successful past resolutions
241
-
242
- #### How It Works
243
- - **Text Similarity**: Uses TF-IDF vectorization and cosine similarity (scikit-learn)
244
- - **Service Detection**: Automatically identifies affected services from incident text
245
- - **Pattern Recognition**: Finds common error types, resolution patterns, and time estimates
246
- - **Fallback Mode**: Works without ML libraries using keyword-based similarity
247
- - **Solution Mining**: Extracts actionable steps from resolution summaries
248
-
249
- #### Data Requirements
250
- For optimal results, ensure your Rootly incidents have descriptive:
251
- - **Titles**: Clear, specific incident descriptions
252
- - **Summaries**: Detailed resolution steps when closing incidents
253
- - **Service Tags**: Proper service identification
254
-
255
- Example good resolution summary: `"Restarted auth-service, cleared Redis cache, and increased connection pool from 10 to 50"`
256
-
257
174
  ### On-Call Shift Metrics
258
175
 
259
176
  Get on-call shift metrics for any time period, grouped by user, team, or schedule. Includes primary/secondary role tracking, shift counts, hours, and days on-call.
@@ -305,52 +222,9 @@ get_shift_incidents(
305
222
  Returns: `incidents` list + `summary` (counts, avg resolution time, grouping)
306
223
 
307
224
 
308
- ## Developer Setup & Troubleshooting
309
-
310
- ### Prerequisites
311
- - Python 3.12 or higher
312
- - [`uv`](https://github.com/astral-sh/uv) for dependency management
313
-
314
- ### 1. Set Up Virtual Environment
315
-
316
- Create and activate a virtual environment:
317
-
318
- ```bash
319
- uv venv .venv
320
- source .venv/bin/activate # Always activate before running scripts
321
- ```
322
-
323
- ### 2. Install Dependencies
324
-
325
- Install all project dependencies:
326
-
327
- ```bash
328
- uv pip install .
329
- ```
330
-
331
- To add new dependencies during development:
332
- ```bash
333
- uv pip install <package>
334
- ```
335
-
336
- ### 3. Set Up Git Hooks (Recommended for Contributors)
337
-
338
- Install pre-commit hooks to automatically run linting and tests before commits:
339
-
340
- ```bash
341
- ./scripts/setup-hooks.sh
342
- ```
343
-
344
- This ensures code quality by running:
345
- - Ruff linting
346
- - Pyright type checking
347
- - Unit tests
348
-
349
- ### 4. Verify Installation
350
-
351
- The server should now be ready to use with your MCP-compatible editor.
225
+ ## Contributing
352
226
 
353
- **For developers:** Additional testing tools are available in the `tests/` directory.
227
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for developer setup and guidelines.
354
228
 
355
229
  ## Play with it on Postman
356
230
  [<img src="https://run.pstmn.io/button.svg" alt="Run In Postman" style="width: 128px; height: 32px;">](https://god.gw.postman.com/run-collection/45004446-1074ba3c-44fe-40e3-a932-af7c071b96eb?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D45004446-1074ba3c-44fe-40e3-a932-af7c071b96eb%26entityType%3Dcollection%26workspaceId%3D4bec6e3c-50a0-4746-85f1-00a703c32f24)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rootly-mcp-server"
3
- version = "2.1.2"
3
+ version = "2.1.3"
4
4
  description = "Secure Model Context Protocol server for Rootly APIs with AI SRE capabilities, comprehensive error handling, and input validation"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -0,0 +1,71 @@
1
+ """On-Call Health API client for burnout risk analysis."""
2
+
3
+ import os
4
+ from typing import Any
5
+
6
+ import httpx
7
+
8
+
9
+ class OnCallHealthClient:
10
+ def __init__(self, api_key: str | None = None, base_url: str | None = None):
11
+ self.api_key: str = api_key or os.environ.get("ONCALLHEALTH_API_KEY", "")
12
+ self.base_url: str = base_url or os.environ.get(
13
+ "ONCALLHEALTH_API_URL", "https://api.oncallhealth.ai"
14
+ )
15
+
16
+ async def get_analysis(self, analysis_id: int) -> dict[str, Any]:
17
+ """Fetch analysis by ID."""
18
+ async with httpx.AsyncClient() as client:
19
+ response = await client.get(
20
+ f"{self.base_url}/analyses/{analysis_id}",
21
+ headers={"X-API-Key": self.api_key},
22
+ timeout=30.0,
23
+ )
24
+ response.raise_for_status()
25
+ return response.json()
26
+
27
+ async def get_latest_analysis(self) -> dict[str, Any]:
28
+ """Fetch most recent analysis."""
29
+ async with httpx.AsyncClient() as client:
30
+ response = await client.get(
31
+ f"{self.base_url}/analyses",
32
+ headers={"X-API-Key": self.api_key},
33
+ params={"limit": 1},
34
+ timeout=30.0,
35
+ )
36
+ response.raise_for_status()
37
+ data = response.json()
38
+ analyses = data.get("analyses", [])
39
+ if not analyses:
40
+ raise ValueError("No analyses found")
41
+ return analyses[0]
42
+
43
+ def extract_at_risk_users(
44
+ self, analysis: dict[str, Any], threshold: float = 50.0
45
+ ) -> tuple[list[dict[str, Any]], list[dict[str, Any]]]:
46
+ """Extract at-risk and safe users from analysis."""
47
+ members = analysis.get("analysis_data", {}).get("team_analysis", {}).get("members", [])
48
+
49
+ at_risk: list[dict[str, Any]] = []
50
+ safe: list[dict[str, Any]] = []
51
+
52
+ for member in members:
53
+ user_data: dict[str, Any] = {
54
+ "user_name": member.get("user_name"),
55
+ "rootly_user_id": member.get("rootly_user_id"),
56
+ "och_score": member.get("och_score", 0),
57
+ "risk_level": member.get("risk_level", "unknown"),
58
+ "burnout_score": member.get("burnout_score", 0),
59
+ "incident_count": member.get("incident_count", 0),
60
+ }
61
+
62
+ if user_data["och_score"] >= threshold:
63
+ at_risk.append(user_data)
64
+ elif user_data["och_score"] < 20: # Safe threshold
65
+ safe.append(user_data)
66
+
67
+ # Sort at-risk by score descending, safe by score ascending
68
+ at_risk.sort(key=lambda x: x["och_score"], reverse=True)
69
+ safe.sort(key=lambda x: x["och_score"])
70
+
71
+ return at_risk, safe