rootly-mcp-server 2.1.1__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.
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.gitignore +4 -2
- rootly_mcp_server-2.1.3/CONTRIBUTING.md +57 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/PKG-INFO +38 -164
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/README.md +37 -163
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/pyproject.toml +1 -1
- rootly_mcp_server-2.1.3/src/rootly_mcp_server/och_client.py +71 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/server.py +1323 -0
- rootly_mcp_server-2.1.3/tests/unit/test_och_client.py +282 -0
- rootly_mcp_server-2.1.3/tests/unit/test_oncall_new_tools.py +662 -0
- rootly_mcp_server-2.1.1/#Dockerfile# +0 -29
- rootly_mcp_server-2.1.1/.beads/.gitignore +0 -44
- rootly_mcp_server-2.1.1/.beads/.local_version +0 -1
- rootly_mcp_server-2.1.1/.beads/.sync.lock +0 -0
- rootly_mcp_server-2.1.1/.beads/README.md +0 -81
- rootly_mcp_server-2.1.1/.beads/beads.db +0 -0
- rootly_mcp_server-2.1.1/.beads/beads.db-shm +0 -0
- rootly_mcp_server-2.1.1/.beads/beads.db-wal +0 -0
- rootly_mcp_server-2.1.1/.beads/config.yaml +0 -62
- rootly_mcp_server-2.1.1/.beads/daemon.lock +0 -7
- rootly_mcp_server-2.1.1/.beads/daemon.pid +0 -1
- rootly_mcp_server-2.1.1/.beads/interactions.jsonl +0 -0
- rootly_mcp_server-2.1.1/.beads/last-touched +0 -1
- rootly_mcp_server-2.1.1/.beads/metadata.json +0 -4
- rootly_mcp_server-2.1.1/.beads/sync_base.jsonl +0 -5
- rootly_mcp_server-2.1.1/.claude/settings.local.json +0 -77
- rootly_mcp_server-2.1.1/.mcp.json +0 -15
- rootly_mcp_server-2.1.1/2026-01-27-MCP.txt +0 -643
- rootly_mcp_server-2.1.1/2026-01-27-claude-code-v2120.txt +0 -1215
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.beads/issues.jsonl +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.gitattributes +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.github/dependabot.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.github/workflows/ci.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.github/workflows/lint.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.github/workflows/pypi-release.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.github/workflows/test.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.semaphore/deploy.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.semaphore/semaphore.yml +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/.semaphore/update-task-definition.sh +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/Dockerfile +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/LICENSE +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/examples/skills/README.md +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/rootly-mcp-server-demo.gif +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/rootly_openapi.json +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/scripts/setup-hooks.sh +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/__init__.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/__main__.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/client.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/data/__init__.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/exceptions.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/monitoring.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/pagination.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/security.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/smart_utils.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/texttest.json +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/utils.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/src/rootly_mcp_server/validators.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/README.md +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/conftest.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/integration/local/test_basic.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/integration/local/test_smart_tools.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/integration/remote/test_essential.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/test_client.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_authentication.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_exceptions.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_oncall_handoff.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_oncall_metrics.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_security.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_server.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_smart_utils.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_tools.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_utils.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/tests/unit/test_validators.py +0 -0
- {rootly_mcp_server-2.1.1 → rootly_mcp_server-2.1.3}/uv.lock +0 -0
|
@@ -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.
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
##
|
|
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
|
-
|
|
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.
|
|
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
|