rootly-mcp-server 2.3.8__tar.gz → 2.3.16__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.3.8 → rootly_mcp_server-2.3.16}/.github/workflows/ci.yml +19 -19
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.github/workflows/openapi-audit.yml +6 -6
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.github/workflows/pypi-release.yml +3 -3
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/CHANGELOG.md +137 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/CONTRIBUTING.md +10 -6
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/Dockerfile +10 -2
- rootly_mcp_server-2.3.16/Makefile +87 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/PKG-INFO +245 -163
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/README.md +230 -155
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/examples/skills/README.md +2 -2
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/pyproject.toml +18 -11
- rootly_mcp_server-2.3.16/scripts/setup-hooks.sh +39 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/server.json +1 -1
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/__main__.py +358 -46
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/code_mode.py +1 -1
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/server.py +337 -95
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/server_defaults.py +207 -27
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/spec_transform.py +61 -15
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/tools/alerts.py +16 -2
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/tools/incidents.py +248 -125
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/tools/oncall.py +37 -17
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/tools/resources.py +1 -1
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/transport.py +319 -35
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/utils.py +2 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/integration/local/test_tool_allowlists.py +11 -2
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/integration/remote/test_essential.py +15 -12
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_alert_stripping.py +23 -5
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_alert_tools.py +29 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_code_mode_module.py +1 -1
- rootly_mcp_server-2.3.16/tests/unit/test_main_transport.py +643 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_server.py +388 -107
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_server_defaults_module.py +45 -2
- rootly_mcp_server-2.3.16/tests/unit/test_snakecase_tools.py +171 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_tools.py +427 -120
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_transport_module.py +326 -12
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/uv.lock +305 -247
- rootly_mcp_server-2.3.8/scripts/setup-hooks.sh +0 -66
- rootly_mcp_server-2.3.8/src/rootly_mcp_server/pagination.py +0 -98
- rootly_mcp_server-2.3.8/tests/unit/test_main_transport.py +0 -193
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.dockerignore +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.gitattributes +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.github/dependabot.yml +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.github/openapi-audit-remote-baseline.json +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.github/workflows/dependency-review.yml +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.gitignore +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.mcp.json +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.semaphore/deploy-staging.yml +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.semaphore/deploy.yml +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.semaphore/semaphore.yml +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/.semaphore/update-task-definition.sh +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/LICENSE +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/gemini-extension.json +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/rootly-mcp-server-demo.gif +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/rootly_openapi.json +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/scripts/audit_openapi.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/__init__.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/audit.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/client.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/data/__init__.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/exceptions.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/legacy_server.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/mcp_error.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/monitoring.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/och_client.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/payload_stripping.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/security.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/smart_utils.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/tools/__init__.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/src/rootly_mcp_server/validators.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/README.md +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/conftest.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/integration/local/test_basic.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/integration/local/test_smart_tools.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/test_client.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_authentication.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_exceptions.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_http_headers.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_legacy_server_module.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_mcp_error_module.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_och_client.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_oncall_handoff.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_oncall_metrics.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_oncall_new_tools.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_oncall_severity_normalization.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_payload_stripping_module.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_security.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_smart_utils.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_utils.py +0 -0
- {rootly_mcp_server-2.3.8 → rootly_mcp_server-2.3.16}/tests/unit/test_validators.py +0 -0
|
@@ -15,16 +15,16 @@ concurrency:
|
|
|
15
15
|
|
|
16
16
|
jobs:
|
|
17
17
|
quality:
|
|
18
|
-
name: Quality (Python 3.
|
|
18
|
+
name: Quality (Python 3.13)
|
|
19
19
|
runs-on: ubuntu-latest
|
|
20
20
|
steps:
|
|
21
21
|
- name: Checkout code
|
|
22
|
-
uses: actions/checkout@
|
|
22
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
23
23
|
|
|
24
24
|
- name: Set up Python
|
|
25
|
-
uses: actions/setup-python@
|
|
25
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
26
26
|
with:
|
|
27
|
-
python-version: "3.
|
|
27
|
+
python-version: "3.13"
|
|
28
28
|
|
|
29
29
|
- name: Install uv
|
|
30
30
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -53,10 +53,10 @@ jobs:
|
|
|
53
53
|
|
|
54
54
|
steps:
|
|
55
55
|
- name: Checkout code
|
|
56
|
-
uses: actions/checkout@
|
|
56
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
57
57
|
|
|
58
58
|
- name: Set up Python ${{ matrix.python-version }}
|
|
59
|
-
uses: actions/setup-python@
|
|
59
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
60
60
|
with:
|
|
61
61
|
python-version: ${{ matrix.python-version }}
|
|
62
62
|
|
|
@@ -70,14 +70,14 @@ jobs:
|
|
|
70
70
|
run: uv run pytest tests/unit/ --cov=src/rootly_mcp_server --cov-report=xml
|
|
71
71
|
|
|
72
72
|
- name: Run local integration tests
|
|
73
|
-
if: matrix.python-version == '3.
|
|
73
|
+
if: matrix.python-version == '3.13'
|
|
74
74
|
env:
|
|
75
75
|
ROOTLY_API_TOKEN: ${{ secrets.ROOTLY_API_TOKEN }}
|
|
76
76
|
run: uv run pytest tests/integration/local/ -x
|
|
77
77
|
|
|
78
78
|
- name: Upload coverage to Codecov
|
|
79
|
-
if: matrix.python-version == '3.
|
|
80
|
-
uses: codecov/codecov-action@
|
|
79
|
+
if: matrix.python-version == '3.13'
|
|
80
|
+
uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v5
|
|
81
81
|
with:
|
|
82
82
|
file: ./coverage.xml
|
|
83
83
|
flags: unittests
|
|
@@ -87,15 +87,15 @@ jobs:
|
|
|
87
87
|
name: Container Tests
|
|
88
88
|
runs-on: ubuntu-latest
|
|
89
89
|
needs: test
|
|
90
|
-
if: ${{ github.repository == '
|
|
90
|
+
if: ${{ github.repository == 'rootlyhq/rootly-mcp-server' }}
|
|
91
91
|
steps:
|
|
92
92
|
- name: Checkout code
|
|
93
|
-
uses: actions/checkout@
|
|
93
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
94
94
|
|
|
95
95
|
- name: Set up Python
|
|
96
|
-
uses: actions/setup-python@
|
|
96
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
97
97
|
with:
|
|
98
|
-
python-version: "3.
|
|
98
|
+
python-version: "3.13"
|
|
99
99
|
|
|
100
100
|
- name: Install uv
|
|
101
101
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -135,12 +135,12 @@ jobs:
|
|
|
135
135
|
runs-on: ubuntu-latest
|
|
136
136
|
steps:
|
|
137
137
|
- name: Checkout code
|
|
138
|
-
uses: actions/checkout@
|
|
138
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
139
139
|
|
|
140
140
|
- name: Set up Python
|
|
141
|
-
uses: actions/setup-python@
|
|
141
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
142
142
|
with:
|
|
143
|
-
python-version: "3.
|
|
143
|
+
python-version: "3.13"
|
|
144
144
|
|
|
145
145
|
- name: Install uv
|
|
146
146
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -161,12 +161,12 @@ jobs:
|
|
|
161
161
|
needs: [quality, test, security]
|
|
162
162
|
steps:
|
|
163
163
|
- name: Checkout code
|
|
164
|
-
uses: actions/checkout@
|
|
164
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
165
165
|
|
|
166
166
|
- name: Set up Python
|
|
167
|
-
uses: actions/setup-python@
|
|
167
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
168
168
|
with:
|
|
169
|
-
python-version: "3.
|
|
169
|
+
python-version: "3.13"
|
|
170
170
|
|
|
171
171
|
- name: Install uv
|
|
172
172
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -36,12 +36,12 @@ jobs:
|
|
|
36
36
|
runs-on: ubuntu-latest
|
|
37
37
|
steps:
|
|
38
38
|
- name: Checkout code
|
|
39
|
-
uses: actions/checkout@
|
|
39
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
40
40
|
|
|
41
41
|
- name: Set up Python
|
|
42
|
-
uses: actions/setup-python@
|
|
42
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
43
43
|
with:
|
|
44
|
-
python-version: "3.
|
|
44
|
+
python-version: "3.13"
|
|
45
45
|
|
|
46
46
|
- name: Install uv
|
|
47
47
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -58,12 +58,12 @@ jobs:
|
|
|
58
58
|
if: ${{ github.event_name != 'pull_request' }}
|
|
59
59
|
steps:
|
|
60
60
|
- name: Checkout code
|
|
61
|
-
uses: actions/checkout@
|
|
61
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
62
62
|
|
|
63
63
|
- name: Set up Python
|
|
64
|
-
uses: actions/setup-python@
|
|
64
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
65
65
|
with:
|
|
66
|
-
python-version: "3.
|
|
66
|
+
python-version: "3.13"
|
|
67
67
|
|
|
68
68
|
- name: Install uv
|
|
69
69
|
uses: astral-sh/setup-uv@7eb50e6e20e1e2009087999ba91242e80253875f # v7
|
|
@@ -13,12 +13,12 @@ jobs:
|
|
|
13
13
|
runs-on: ubuntu-latest
|
|
14
14
|
steps:
|
|
15
15
|
- name: Checkout code
|
|
16
|
-
uses: actions/checkout@
|
|
16
|
+
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
|
|
17
17
|
|
|
18
18
|
- name: Set up Python
|
|
19
|
-
uses: actions/setup-python@
|
|
19
|
+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6
|
|
20
20
|
with:
|
|
21
|
-
python-version: '3.
|
|
21
|
+
python-version: '3.13'
|
|
22
22
|
|
|
23
23
|
- name: Install uv and build tools
|
|
24
24
|
run: |
|
|
@@ -5,6 +5,143 @@ All notable changes to the Rootly MCP Server will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.3.16] - Released 2026-07-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Meeting Recordings & Transcripts**: Added read-only tools `get_meeting_recording`, `list_meeting_recordings`, and `list_all_meeting_recordings` so agents can read call transcripts (the `meeting_transcript` / `meeting_transcript_formatted` data). Call `get_meeting_recording` with `include=transcript` for the full transcript. Refreshed the bundled `data/swagger.json` from source to pick up these endpoints
|
|
13
|
+
|
|
14
|
+
### Fixed
|
|
15
|
+
|
|
16
|
+
- **Incident Tool Hardening (follow-ups)**: A cluster of robustness fixes for the incident tools. Consolidated the incident-reference error taxonomy into one helper so `update_incident`, `find_related_incidents`, and `suggest_solutions` now report an unknown sequential number as `not_found` and a bad reference as `validation_error` (matching `get_incident`) instead of a generic error. Incident-reference resolution now rejects path-altering `"direct"` references (e.g. `../../…`, embedded slashes/whitespace) so a reference can't redirect the request to a different endpoint. Incident summarization tolerates a present-but-null `attributes` field instead of raising. `update_incident` now normalizes `summary` like `create_incident` (a whitespace-only summary is treated as no field). `search_incidents` multi-page mode now flags truncated results with `meta.partial`/`meta.error` instead of silently returning a partial set as complete. `list_incidents` and `search_incidents` append actionable guidance (use filters / `collect_incidents`) when a deep-page request fails with a client error. Removed the unused, uncapped `pagination.py` helpers
|
|
17
|
+
- **Sequential Incident Lookups (400 Bad Request)**: Resolving an incident by its human-readable number (e.g. `57597`, `#57597`, `INC-57597`) no longer walks the entire incident list to find a match. The old approach binary-searched pages sorted by `-created_at`, and its first probe requested a high `page[number]` that the API rejects with a 400 once an account has enough incidents — so sequential lookups failed regardless of the number passed while UUIDs kept working. `get_incident` (and every other tool that accepts an incident reference) now resolves the number with a single direct `filter[sequential_id]` request. Also made the `INC-` prefix case-insensitive so lowercase `inc-57597` resolves correctly, and capped `suggest_solutions`' page size at the API maximum (100, was 150)
|
|
18
|
+
- **Alert Payload Returned on Detail Lookups**: Single-alert lookups now return the full alert payload, including custom fields. Alert responses were stripped to a whitelist of essential attributes to keep payloads small, but this also dropped the raw `data` payload — where custom fields such as runbook links live (the same data shown under the Rootly UI's alert "payload" tab). The strip now applies only to list/search responses; single-resource detail lookups (`GET /v1/alerts/{id}`) preserve their full attribute set, while relationships are still collapsed to counts and sideloaded `included` data is dropped to keep responses bounded. The curated `get_alert_by_short_id` tool also passes through `data`, `alert_field_values`, and `labels` (plus `external_url` and `updated_at`). Verified end-to-end against a live alert
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
|
|
22
|
+
- **Dependency Bumps to Resolve Dependabot Alerts**: Raised direct override constraints in `pyproject.toml` (and regenerated `uv.lock`) to pull patched versions of vulnerable transitive dependencies, resolving all 16 open Dependabot alerts:
|
|
23
|
+
- `starlette` 0.52.1 → 1.3.1 (GHSA-82w8-qh3p-5jfq, -jp82-jpqv-5vv3, -wqp7-x3pw-xc5r, -x746-7m8f-x49c — DoS, SSRF)
|
|
24
|
+
- `cryptography` 46.0.7 → 49.0.0 (GHSA-537c-gmf6-5ccf — bundled OpenSSL)
|
|
25
|
+
- `python-multipart` 0.0.28 → 0.0.32 (CVE-2026-40347, GHSA-v9pg-7xvm-68hf, -6jv3-5f52-599m, -vffw-93wf-4j4q — DoS / parameter smuggling)
|
|
26
|
+
- `pyjwt` 2.12.1 → 2.13.0 (GHSA-xgmm-8j9v-c9wx, -993g-76c3-p5m4, -w7vc-732c-9m39, -jq35-7prp-9v3f, -fhv5-28vv-h8m8 — token forgery / DoS)
|
|
27
|
+
- `msgpack` 1.1.2 → 1.2.1 (GHSA-6v7p-g79w-8964 — out-of-bounds read)
|
|
28
|
+
- `authlib` 1.7.0 → 1.7.2 (GHSA-w8p2-r796-3vmq — OAuth open redirect)
|
|
29
|
+
- **Follow-up Dependency Bumps**: Raised override constraints for newly disclosed vulnerabilities in transitive dependencies (`uv.lock` regenerated):
|
|
30
|
+
- `mcp` 1.26.0 → 1.28.1 (CVE-2026-52870, CVE-2026-52869, CVE-2026-59950)
|
|
31
|
+
- `joserfc` 1.6.4 → 1.7.4 (PYSEC-2026-2528, PYSEC-2026-2530)
|
|
32
|
+
- `idna` 3.10 → 3.18 (PYSEC-2026-215)
|
|
33
|
+
- `click` 8.1.8 → 8.4.2 (PYSEC-2026-2132)
|
|
34
|
+
|
|
35
|
+
### Testing
|
|
36
|
+
|
|
37
|
+
- Added coverage for detail-lookup payload preservation, list-response stripping (unchanged), and the `get_alert_by_short_id` payload/custom-field pass-through
|
|
38
|
+
|
|
39
|
+
## [2.3.14] - Released 2026-06-05
|
|
40
|
+
|
|
41
|
+
### Features
|
|
42
|
+
|
|
43
|
+
- **`list_incident_roles` Tool**: Added a curated `list_incident_roles(incident_id)` tool that returns role assignments for an incident (Commander, Postmortem Owner, Scribe, etc.) as a flat table with role metadata and the assigned user. Wraps `GET /v1/incidents/{id}?include=roles` and flattens the JSON:API `included` array so callers don't have to walk the relationships graph. Included in the default hosted tool surface
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- **Misnamed Tool Argument Normalization**: Added argument normalization middleware to recover from common LLM/client parameter mistakes before Pydantic validation runs. This now remaps `from`/`to` to `from_date`/`to_date` for `list_shifts`, remaps `max_tokens` to `max_results` for `search_incidents`, and coerces list-shaped schedule/shift identifiers into the CSV form expected by the current tool schemas
|
|
48
|
+
|
|
49
|
+
### Testing
|
|
50
|
+
|
|
51
|
+
- Expanded snake_case and argument-normalization coverage for alias handling, CSV coercion, and misnamed-argument recovery paths
|
|
52
|
+
- Added coverage for `list_incident_roles` happy path, unassigned roles, sequential reference resolution, and validation errors
|
|
53
|
+
|
|
54
|
+
## [2.3.13] - Released 2026-06-01
|
|
55
|
+
|
|
56
|
+
### Features
|
|
57
|
+
|
|
58
|
+
- **OAuth Authorization Server Metadata**: Hosted MCP deployments now serve RFC 8414 authorization server metadata so OAuth-capable clients can discover Rootly's authorization endpoints directly from the MCP server
|
|
59
|
+
- **Safe Write Surface Expanded**: The default write-allowed surface now exposes a broader set of non-destructive tools for alerts, alert events, alert routes, alert sources, custom forms, form fields, workflow runs, status page templates, and related resources when write tools are enabled
|
|
60
|
+
|
|
61
|
+
### Fixed
|
|
62
|
+
|
|
63
|
+
- **Snake Case Tool Names**: OpenAPI-generated MCP tools are now normalized to `snake_case`, with a compatibility bridge for legacy camelCase callers, so tool discovery and invocation are more predictable across MCP clients
|
|
64
|
+
- **ASGI Response Double-Send Guard**: Hosted auth middleware now suppresses orphaned or duplicate body frames after a response is already dropped or completed, preventing duplicate ASGI response behavior in production
|
|
65
|
+
- **OAuth Scope Compatibility**: Protected resource metadata now advertises a single coarse `all` scope instead of many granular scopes, improving compatibility with MCP clients that fail to forward fine-grained scopes through dynamic client registration
|
|
66
|
+
|
|
67
|
+
### Infrastructure
|
|
68
|
+
|
|
69
|
+
- **Docker Base Updated**: The container image now builds on `python:3.13-slim`
|
|
70
|
+
|
|
71
|
+
### Testing
|
|
72
|
+
|
|
73
|
+
- Added focused coverage for snake_case normalization and the camelCase alias bridge
|
|
74
|
+
- Added/updated hosted and server allowlist coverage for the expanded write surface
|
|
75
|
+
|
|
76
|
+
## [2.3.12] - Released 2026-05-28
|
|
77
|
+
|
|
78
|
+
### Fixed
|
|
79
|
+
|
|
80
|
+
- **Unfilled Path Templates**: When a tool was called with a missing or misnamed path argument (e.g. `schedule_id` instead of `id`), FastMCP left the literal `{id}` placeholder in the URL and the encoded `%7Bid%7D` was sent upstream, producing a misleading 404 "Not found or unauthorized". The transport layer now detects unfilled placeholders in the URL path and raises a `RootlyValidationError` naming the missing parameter before any upstream call
|
|
81
|
+
- **Deprecated Alert Routing Endpoint**: Tenants with Advanced Alert Routing enabled were repeatedly hitting 403s on `/v1/alert_routing_rules`. The replacement `listAlertRoutes` / `getAlertRoute` operations are now exposed in the default allowlist, and 403 responses with the Advanced Alert Routing message are annotated with a structured `_use_tool` field pointing models at the correct replacement
|
|
82
|
+
- **Schedule Shift Date Range Cap**: `getScheduleShifts` and `listShifts` callers regularly hit opaque 422 errors after sending `from`/`to` windows larger than the upstream cap (1 month and 2 months respectively). A pre-flight check now parses the dates and rejects oversized windows client-side with a clear chunking recommendation. `/v1/override_shifts/*` paths are excluded
|
|
83
|
+
- **Phantom `listIncidents` Tool**: `canonicalize_tool_names()` only expanded legacy → canonical aliases, so an allowlist mentioning `list_incidents` (the canonical name) stripped the curated `listIncidents` proxy. Alias expansion is now bidirectional, keeping both names exposed together during the deprecation window
|
|
84
|
+
- **Missing `createSchedule` In Hosted Slim Profile**: The `/schedules` POST endpoint was already write-allowed, but the operationId wasn't included in the slim hosted tool profile. Added so models can actually create schedules when write tools are enabled
|
|
85
|
+
- **Param-Name Discoverability**: Production logs showed models repeatedly guessing wrong on parameter names that were unobvious from tool descriptions. Tool descriptions now explicitly name the canonical argument shape for `getIncident` (`incident_id`, not `id`), the `max_results <= 10` cap on `search_incidents`, the `user_ids` (not `emails`) contract on `check_responder_availability`, and the plural `schedule_ids` argument on `get_oncall_schedule_summary`
|
|
86
|
+
|
|
87
|
+
### Testing
|
|
88
|
+
|
|
89
|
+
- Added focused transport coverage for unfilled-path-template rejection, shift date-range pre-flight (with override-shift lookalike exclusions), alert-routing 403 annotation, and false-positive guards on query-string braces and similar lookalike paths
|
|
90
|
+
- Extended `canonicalize_tool_names` coverage for both directions of the legacy/canonical pair
|
|
91
|
+
|
|
92
|
+
## [2.3.11] - Released 2026-05-27
|
|
93
|
+
|
|
94
|
+
### Features
|
|
95
|
+
|
|
96
|
+
- **Hosted Full Tool Surface by Default**: Hosted MCP deployments now expose the full tool surface by default again, so remote clients no longer miss create/update workflows that were absent from the slimmer hosted profile
|
|
97
|
+
- **Hosted Slim Profile Selector**: Added a slimmer hosted profile of about 70 high-usage tools that clients can opt into with `?tool_profile=slim`, `X-Rootly-Tool-Profile: slim`, or the `ROOTLY_MCP_HOSTED_TOOL_PROFILE` server setting
|
|
98
|
+
|
|
99
|
+
### Configuration
|
|
100
|
+
|
|
101
|
+
- **Profile Override Precedence**: `ROOTLY_MCP_ENABLED_TOOLS` remains the highest-precedence override, so operators can still replace either hosted profile with an exact custom allowlist when needed
|
|
102
|
+
|
|
103
|
+
### Documentation
|
|
104
|
+
|
|
105
|
+
- **Hosted Profile Guidance**: Updated the README to document full-vs-slim hosted usage options, server-wide profile defaults, and exact allowlist overrides
|
|
106
|
+
|
|
107
|
+
### Dependencies
|
|
108
|
+
|
|
109
|
+
- **Lockfile Sync**: Regenerated `uv.lock` so the lockfile matches the current pinned package versions in `pyproject.toml`, including `fastmcp==3.3.1` and `requests==2.34.2`
|
|
110
|
+
|
|
111
|
+
### Testing
|
|
112
|
+
|
|
113
|
+
- **Hosted Routing Coverage**: Added coverage for hosted profile resolution, profiled streamable HTTP routing, explicit allowlist bypass behavior, and unknown profile fallback handling
|
|
114
|
+
|
|
115
|
+
## [2.3.10] - Released 2026-05-26
|
|
116
|
+
|
|
117
|
+
### Fixed
|
|
118
|
+
|
|
119
|
+
- **Blank Query Param Forwarding**: The MCP transport now drops empty string, whitespace-only, and empty collection query parameters before forwarding requests upstream, preventing optional blank filters from corrupting pagination or other serialized query values
|
|
120
|
+
- **Alerts Pagination Corruption Guard**: Hardened the shared request path used by OpenAPI-generated tools so requests that include blank optional filters no longer risk serializing `page[size]` incorrectly when valid pagination values are provided
|
|
121
|
+
|
|
122
|
+
### Testing
|
|
123
|
+
|
|
124
|
+
- Added focused transport regression coverage for dropping blank query params in both direct parameter transforms and rebuilt outbound request URLs
|
|
125
|
+
|
|
126
|
+
## [2.3.9] - Released 2026-05-21
|
|
127
|
+
|
|
128
|
+
### Performance
|
|
129
|
+
|
|
130
|
+
- **Hosted Default Tool Surface Slimmed**: Default hosted deployments now expose a curated core profile of 55 high-usage tools instead of the full 200+ tool surface, improving MCP client tool-discovery performance while preserving a broad self-hosted default
|
|
131
|
+
- **Hosted and Self-Hosted Defaults Split**: Hosted/serverless instances now default to the slim allowlist, while local and self-hosted deployments continue to expose the full tool catalog unless explicitly overridden
|
|
132
|
+
|
|
133
|
+
### Configuration
|
|
134
|
+
|
|
135
|
+
- **Hosted Allowlist Override Behavior**: `ROOTLY_MCP_ENABLED_TOOLS` now cleanly overrides the hosted default profile when operators want a narrower or broader remote tool surface
|
|
136
|
+
|
|
137
|
+
### Documentation
|
|
138
|
+
|
|
139
|
+
- **README Deployment Guidance Updated**: Documented the new hosted-versus-self-hosted tool defaults, the hosted override behavior, and the current approximate tool counts for each mode
|
|
140
|
+
|
|
141
|
+
### Dependencies
|
|
142
|
+
|
|
143
|
+
- **Lockfile Sync**: Regenerated `uv.lock` so the lockfile matches the current pinned versions in `pyproject.toml`, including `requests==2.34.0` and `pydantic==2.13.4`
|
|
144
|
+
|
|
8
145
|
## [2.3.8] - Released 2026-05-19
|
|
9
146
|
|
|
10
147
|
### Security
|
|
@@ -39,19 +39,23 @@ uv pip install <package>
|
|
|
39
39
|
|
|
40
40
|
### 3. Set Up Git Hooks (Recommended)
|
|
41
41
|
|
|
42
|
-
Install pre-commit hooks to automatically run
|
|
42
|
+
Install pre-commit hooks to automatically run the quality gate before commits:
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
|
-
./scripts/setup-hooks.sh
|
|
45
|
+
make hooks # or: ./scripts/setup-hooks.sh
|
|
46
46
|
```
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
- Pyright type checking
|
|
51
|
-
- Unit tests
|
|
48
|
+
The hook runs `make check` (lint, format check, type checks, unit tests) —
|
|
49
|
+
the same gate CI enforces.
|
|
52
50
|
|
|
53
51
|
### 4. Verify Installation
|
|
54
52
|
|
|
55
53
|
The server should now be ready to use with your MCP-compatible editor.
|
|
56
54
|
|
|
57
55
|
Additional testing tools are available in the `tests/` directory.
|
|
56
|
+
|
|
57
|
+
## Common Tasks
|
|
58
|
+
|
|
59
|
+
The `Makefile` wraps the toolchain; run `make help` to list every target.
|
|
60
|
+
Common ones: `make check` (pre-push gate), `make test`, and `make fetch-spec`
|
|
61
|
+
to refresh the bundled OpenAPI spec from source.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
# Use Python 3.
|
|
2
|
-
FROM python:3.
|
|
1
|
+
# Use Python 3.13 slim image as base
|
|
2
|
+
FROM python:3.13-slim
|
|
3
3
|
|
|
4
4
|
# Set working directory
|
|
5
5
|
WORKDIR /app
|
|
@@ -18,6 +18,14 @@ COPY . .
|
|
|
18
18
|
# Install the package and its dependencies
|
|
19
19
|
RUN uv pip install --system --no-cache-dir -e .
|
|
20
20
|
|
|
21
|
+
# Install AgentCat (formerly MCPcat) for hosted telemetry without changing the
|
|
22
|
+
# repo dependency graph. The [community] extra provides FastMCP support, which
|
|
23
|
+
# this server relies on. AgentCat's package metadata pins an older Pydantic
|
|
24
|
+
# range, but the SDK imports successfully with our runtime pin, so we restore
|
|
25
|
+
# the server's pinned version after installation.
|
|
26
|
+
RUN uv pip install --system --no-cache-dir "agentcat[community]==1.0.1" \
|
|
27
|
+
&& uv pip install --system --no-cache-dir pydantic==2.13.4
|
|
28
|
+
|
|
21
29
|
# Create non-root user
|
|
22
30
|
RUN useradd -m -u 1000 appuser && chown -R appuser:appuser /app
|
|
23
31
|
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
.DEFAULT_GOAL := help
|
|
2
|
+
|
|
3
|
+
PYTHON_VERSION := 3.12
|
|
4
|
+
SPEC_URL := https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json
|
|
5
|
+
SPEC_PATH := src/rootly_mcp_server/data/swagger.json
|
|
6
|
+
PKG := src/rootly_mcp_server
|
|
7
|
+
UV := uv run --python $(PYTHON_VERSION)
|
|
8
|
+
|
|
9
|
+
IMAGE := rootly-mcp-server
|
|
10
|
+
|
|
11
|
+
.PHONY: help install build run \
|
|
12
|
+
test test-unit test-integration \
|
|
13
|
+
lint format format-check typecheck security \
|
|
14
|
+
fetch-spec audit-spec \
|
|
15
|
+
docker-build docker-test \
|
|
16
|
+
check ci hooks clean
|
|
17
|
+
|
|
18
|
+
help: ## Show available targets
|
|
19
|
+
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
|
|
20
|
+
| awk 'BEGIN{FS=":.*?## "}{printf " \033[36m%-16s\033[0m %s\n", $$1, $$2}'
|
|
21
|
+
|
|
22
|
+
install: ## Install dependencies and the pinned Python via uv
|
|
23
|
+
uv sync --dev --python $(PYTHON_VERSION)
|
|
24
|
+
|
|
25
|
+
build: ## Build the sdist and wheel
|
|
26
|
+
uv build
|
|
27
|
+
|
|
28
|
+
run: ## Run the MCP server locally (needs ROOTLY_API_TOKEN)
|
|
29
|
+
$(UV) rootly-mcp-server
|
|
30
|
+
|
|
31
|
+
# --- tests ---
|
|
32
|
+
test: ## Run the full test suite (with coverage)
|
|
33
|
+
$(UV) pytest
|
|
34
|
+
|
|
35
|
+
test-unit: ## Run unit tests only
|
|
36
|
+
$(UV) pytest tests/unit/
|
|
37
|
+
|
|
38
|
+
test-integration: ## Run local integration tests (needs ROOTLY_API_TOKEN)
|
|
39
|
+
$(UV) pytest tests/integration/local/ -x
|
|
40
|
+
|
|
41
|
+
# --- quality ---
|
|
42
|
+
lint: ## Lint with ruff
|
|
43
|
+
$(UV) ruff check .
|
|
44
|
+
|
|
45
|
+
format: ## Auto-format with ruff
|
|
46
|
+
$(UV) ruff format .
|
|
47
|
+
|
|
48
|
+
format-check: ## Check formatting without modifying files (CI gate)
|
|
49
|
+
$(UV) ruff format --check .
|
|
50
|
+
|
|
51
|
+
typecheck: ## Type-check with pyright and mypy
|
|
52
|
+
$(UV) pyright
|
|
53
|
+
$(UV) mypy $(PKG)
|
|
54
|
+
|
|
55
|
+
security: ## Security scan (bandit blocking; pip-audit advisory, mirrors CI)
|
|
56
|
+
$(UV) bandit -r src/
|
|
57
|
+
-$(UV) pip-audit
|
|
58
|
+
|
|
59
|
+
# --- OpenAPI spec ---
|
|
60
|
+
fetch-spec: ## Refresh the bundled OpenAPI spec from source (never hand-edit it)
|
|
61
|
+
curl -fsS $(SPEC_URL) -o $(SPEC_PATH)
|
|
62
|
+
|
|
63
|
+
audit-spec: ## Audit the bundled spec for MCP tool-generation issues
|
|
64
|
+
$(UV) python scripts/audit_openapi.py --filtered-defaults --instantiate-server
|
|
65
|
+
|
|
66
|
+
# --- docker (mirrors the CI container-tests job) ---
|
|
67
|
+
docker-build: ## Build the Docker image
|
|
68
|
+
docker build -t $(IMAGE) .
|
|
69
|
+
|
|
70
|
+
docker-test: docker-build ## Build the image and run the containerized server smoke test (needs ROOTLY_API_TOKEN)
|
|
71
|
+
docker run -d --name $(IMAGE) -p 8000:8000 -e ROOTLY_API_TOKEN="$(ROOTLY_API_TOKEN)" $(IMAGE)
|
|
72
|
+
timeout 30s bash -c 'until curl -fsS http://localhost:8000/health || curl -fsS http://localhost:8000/; do sleep 2; done'
|
|
73
|
+
MCP_SERVER_URL=http://localhost:8000 $(UV) pytest tests/integration/remote/test_essential.py -v --timeout=60; \
|
|
74
|
+
status=$$?; docker stop $(IMAGE) && docker rm $(IMAGE); exit $$status
|
|
75
|
+
|
|
76
|
+
# --- aggregates ---
|
|
77
|
+
check: lint format-check typecheck test-unit ## Fast pre-push gate (mirrors CI quality + unit tests)
|
|
78
|
+
|
|
79
|
+
ci: lint format-check typecheck security test-unit audit-spec ## Everything CI enforces (excl. docker/remote)
|
|
80
|
+
|
|
81
|
+
# --- misc ---
|
|
82
|
+
hooks: ## Install the git pre-commit hook
|
|
83
|
+
./scripts/setup-hooks.sh
|
|
84
|
+
|
|
85
|
+
clean: ## Remove build and test artifacts
|
|
86
|
+
rm -rf dist build .pytest_cache .mypy_cache .ruff_cache coverage.xml htmlcov
|
|
87
|
+
find . -type d -name __pycache__ -prune -exec rm -rf {} +
|