rootly-mcp-server 2.2.18__tar.gz → 2.2.20__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 (84) hide show
  1. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/dependabot.yml +23 -7
  2. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/workflows/ci.yml +12 -12
  3. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/workflows/dependency-review.yml +1 -1
  4. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/workflows/openapi-audit.yml +4 -4
  5. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/workflows/pypi-release.yml +2 -2
  6. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.gitignore +4 -0
  7. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/CHANGELOG.md +25 -0
  8. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/PKG-INFO +5 -33
  9. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/README.md +1 -31
  10. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/pyproject.toml +4 -2
  11. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/__main__.py +9 -5
  12. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/code_mode.py +4 -6
  13. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/server.py +8 -17
  14. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/spec_transform.py +1 -2
  15. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/tools/__init__.py +0 -2
  16. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/tools/incidents.py +243 -166
  17. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/tools/oncall.py +5 -2
  18. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/transport.py +7 -9
  19. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/integration/local/test_basic.py +3 -3
  20. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/integration/local/test_smart_tools.py +21 -21
  21. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/integration/remote/test_essential.py +6 -6
  22. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_code_mode_module.py +6 -2
  23. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_oncall_metrics.py +3 -3
  24. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_server.py +36 -19
  25. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_smart_utils.py +0 -1
  26. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_tools.py +65 -0
  27. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_transport_module.py +21 -7
  28. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/uv.lock +28 -11
  29. rootly_mcp_server-2.2.18/src/rootly_mcp_server/data/chatgpt_incident_workbench.html +0 -576
  30. rootly_mcp_server-2.2.18/src/rootly_mcp_server/tools/chatgpt_app.py +0 -350
  31. rootly_mcp_server-2.2.18/tests/unit/test_chatgpt_app_module.py +0 -229
  32. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.dockerignore +0 -0
  33. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.gitattributes +0 -0
  34. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.github/openapi-audit-remote-baseline.json +0 -0
  35. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.semaphore/deploy-staging.yml +0 -0
  36. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.semaphore/deploy.yml +0 -0
  37. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.semaphore/semaphore.yml +0 -0
  38. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/.semaphore/update-task-definition.sh +0 -0
  39. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/CONTRIBUTING.md +0 -0
  40. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/Dockerfile +0 -0
  41. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/LICENSE +0 -0
  42. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/examples/skills/README.md +0 -0
  43. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/gemini-extension.json +0 -0
  44. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/rootly-mcp-server-demo.gif +0 -0
  45. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/rootly_openapi.json +0 -0
  46. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/scripts/audit_openapi.py +0 -0
  47. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/scripts/setup-hooks.sh +0 -0
  48. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/server.json +0 -0
  49. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/__init__.py +0 -0
  50. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/client.py +0 -0
  51. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/data/__init__.py +0 -0
  52. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/exceptions.py +0 -0
  53. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/legacy_server.py +0 -0
  54. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/mcp_error.py +0 -0
  55. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/monitoring.py +0 -0
  56. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/och_client.py +0 -0
  57. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/pagination.py +0 -0
  58. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/payload_stripping.py +0 -0
  59. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/security.py +0 -0
  60. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/server_defaults.py +0 -0
  61. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/smart_utils.py +0 -0
  62. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/tools/alerts.py +0 -0
  63. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/tools/resources.py +0 -0
  64. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/utils.py +0 -0
  65. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/src/rootly_mcp_server/validators.py +0 -0
  66. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/README.md +0 -0
  67. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/conftest.py +0 -0
  68. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/test_client.py +0 -0
  69. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_alert_stripping.py +0 -0
  70. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_authentication.py +0 -0
  71. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_exceptions.py +0 -0
  72. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_http_headers.py +0 -0
  73. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_legacy_server_module.py +0 -0
  74. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_main_transport.py +0 -0
  75. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_mcp_error_module.py +0 -0
  76. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_och_client.py +0 -0
  77. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_oncall_handoff.py +0 -0
  78. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_oncall_new_tools.py +0 -0
  79. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_oncall_severity_normalization.py +0 -0
  80. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_payload_stripping_module.py +0 -0
  81. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_security.py +0 -0
  82. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_server_defaults_module.py +0 -0
  83. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_utils.py +0 -0
  84. {rootly_mcp_server-2.2.18 → rootly_mcp_server-2.2.20}/tests/unit/test_validators.py +0 -0
@@ -1,35 +1,51 @@
1
1
  version: 2
2
+
2
3
  updates:
3
- - package-ecosystem: "github-actions"
4
+ - package-ecosystem: "pip"
4
5
  directory: "/"
5
6
  schedule:
6
7
  interval: "weekly"
8
+ open-pull-requests-limit: 20
7
9
  cooldown:
8
10
  default-days: 3
11
+ semver-major-days: 7
9
12
  groups:
10
- actions:
13
+ minor-and-patch:
14
+ applies-to: version-updates
15
+ update-types:
16
+ - "minor"
17
+ - "patch"
11
18
  patterns:
12
19
  - "*"
13
20
 
14
- - package-ecosystem: "pip"
21
+ - package-ecosystem: "docker"
15
22
  directory: "/"
16
23
  schedule:
17
24
  interval: "weekly"
18
- open-pull-requests-limit: 10
25
+ open-pull-requests-limit: 20
19
26
  cooldown:
20
27
  default-days: 3
21
- semver-major-days: 7
22
28
  groups:
23
29
  minor-and-patch:
24
30
  applies-to: version-updates
25
31
  update-types:
26
32
  - "minor"
27
33
  - "patch"
34
+ patterns:
35
+ - "*"
28
36
 
29
- - package-ecosystem: "docker"
37
+ - package-ecosystem: "github-actions"
30
38
  directory: "/"
31
39
  schedule:
32
40
  interval: "weekly"
41
+ open-pull-requests-limit: 20
33
42
  cooldown:
34
43
  default-days: 3
35
- semver-major-days: 7
44
+ groups:
45
+ minor-and-patch:
46
+ applies-to: version-updates
47
+ update-types:
48
+ - "minor"
49
+ - "patch"
50
+ patterns:
51
+ - "*"
@@ -19,10 +19,10 @@ jobs:
19
19
  runs-on: ubuntu-latest
20
20
  steps:
21
21
  - name: Checkout code
22
- uses: actions/checkout@v6
22
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
23
23
 
24
24
  - name: Set up Python
25
- uses: actions/setup-python@v6
25
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
26
26
  with:
27
27
  python-version: "3.12"
28
28
 
@@ -53,10 +53,10 @@ jobs:
53
53
 
54
54
  steps:
55
55
  - name: Checkout code
56
- uses: actions/checkout@v6
56
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
57
57
 
58
58
  - name: Set up Python ${{ matrix.python-version }}
59
- uses: actions/setup-python@v6
59
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
60
60
  with:
61
61
  python-version: ${{ matrix.python-version }}
62
62
 
@@ -87,13 +87,13 @@ jobs:
87
87
  name: Container Tests
88
88
  runs-on: ubuntu-latest
89
89
  needs: test
90
- if: ${{ secrets.ROOTLY_API_TOKEN != '' }}
90
+ if: ${{ github.repository == 'Rootly-AI-Labs/rootly-mcp-server' }}
91
91
  steps:
92
92
  - name: Checkout code
93
- uses: actions/checkout@v6
93
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
94
94
 
95
95
  - name: Set up Python
96
- uses: actions/setup-python@v6
96
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
97
97
  with:
98
98
  python-version: "3.12"
99
99
 
@@ -135,10 +135,10 @@ jobs:
135
135
  runs-on: ubuntu-latest
136
136
  steps:
137
137
  - name: Checkout code
138
- uses: actions/checkout@v6
138
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
139
139
 
140
140
  - name: Set up Python
141
- uses: actions/setup-python@v6
141
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
142
142
  with:
143
143
  python-version: "3.12"
144
144
 
@@ -161,10 +161,10 @@ jobs:
161
161
  needs: [quality, test, security]
162
162
  steps:
163
163
  - name: Checkout code
164
- uses: actions/checkout@v6
164
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
165
165
 
166
166
  - name: Set up Python
167
- uses: actions/setup-python@v6
167
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
168
168
  with:
169
169
  python-version: "3.12"
170
170
 
@@ -175,7 +175,7 @@ jobs:
175
175
  run: uv build
176
176
 
177
177
  - name: Upload build artifacts
178
- uses: actions/upload-artifact@v7
178
+ uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
179
179
  with:
180
180
  name: dist
181
181
  path: dist/
@@ -12,4 +12,4 @@ jobs:
12
12
  runs-on: ubuntu-latest
13
13
  steps:
14
14
  - name: Dependency Review
15
- uses: actions/dependency-review-action@v4
15
+ uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4
@@ -36,10 +36,10 @@ jobs:
36
36
  runs-on: ubuntu-latest
37
37
  steps:
38
38
  - name: Checkout code
39
- uses: actions/checkout@v6
39
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
40
40
 
41
41
  - name: Set up Python
42
- uses: actions/setup-python@v6
42
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
43
43
  with:
44
44
  python-version: "3.12"
45
45
 
@@ -58,10 +58,10 @@ jobs:
58
58
  if: ${{ github.event_name != 'pull_request' }}
59
59
  steps:
60
60
  - name: Checkout code
61
- uses: actions/checkout@v6
61
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
62
62
 
63
63
  - name: Set up Python
64
- uses: actions/setup-python@v6
64
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
65
65
  with:
66
66
  python-version: "3.12"
67
67
 
@@ -13,10 +13,10 @@ jobs:
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
15
  - name: Checkout code
16
- uses: actions/checkout@v6
16
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
17
17
 
18
18
  - name: Set up Python
19
- uses: actions/setup-python@v6
19
+ uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6
20
20
  with:
21
21
  python-version: '3.12'
22
22
 
@@ -1,3 +1,7 @@
1
+ # Benchmark and performance tracking files
2
+ *benchmark*.json
3
+ *_benchmark_*.json
4
+
1
5
  # Byte-compiled / optimized / DLL files
2
6
  __pycache__/
3
7
  *.py[cod]
@@ -5,6 +5,31 @@ 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.2.20] - Released 2026-04-21
9
+
10
+ ### Security
11
+
12
+ - **Critical Security Updates**: Upgraded vulnerable dependencies to address 3 security advisories
13
+ - **authlib**: Updated from `1.6.9` to `1.7.0` to fix CSRF protection vulnerability (GHSA-jj8c-mmj3-mmgv)
14
+ - **python-dotenv**: Updated from `1.1.0` to `1.2.2` to fix symlink attack vulnerability (GHSA-m8f7-34r5-grfg)
15
+ - **python-multipart**: Updated from `0.0.22` to `0.0.26` to fix denial of service vulnerability (CVE-2026-40347)
16
+ - **Dependabot Configuration**: Fixed unsupported `semver-major-days` property for docker and github-actions ecosystems
17
+
18
+ ### Dependencies
19
+
20
+ - **joserfc**: Added `1.6.4` as new dependency (required by updated authlib)
21
+ - **Security Scanning**: All known vulnerabilities resolved as confirmed by pip-audit
22
+
23
+ ## [2.2.19] - Released 2026-04-17
24
+
25
+ ### Features
26
+
27
+ - **Scoped Incident Creation Tool**: Added a custom `createIncident` tool so agents can create incidents directly from MCP without exposing the full raw `/incidents` OpenAPI surface
28
+
29
+ ### Documentation
30
+
31
+ - **Custom Tool List Updated**: Added `createIncident` to the README custom tool section with its scoped workflow-oriented behavior
32
+
8
33
  ## [2.2.18] - Released 2026-04-15
9
34
 
10
35
  ### Features
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rootly-mcp-server
3
- Version: 2.2.18
3
+ Version: 2.2.20
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
@@ -21,7 +21,7 @@ Classifier: Topic :: Software Development :: Build Tools
21
21
  Classifier: Topic :: System :: Monitoring
22
22
  Classifier: Topic :: System :: Systems Administration
23
23
  Requires-Python: >=3.12
24
- Requires-Dist: authlib>=1.6.9
24
+ Requires-Dist: authlib>=1.6.11
25
25
  Requires-Dist: brotli>=1.2.0
26
26
  Requires-Dist: cryptography>=46.0.7
27
27
  Requires-Dist: fastmcp[code-mode]==3.2.0
@@ -29,6 +29,8 @@ Requires-Dist: httpx==0.28.1
29
29
  Requires-Dist: numpy>=1.24.0
30
30
  Requires-Dist: pydantic==2.12.5
31
31
  Requires-Dist: pygments>=2.20.0
32
+ Requires-Dist: python-dotenv>=1.2.2
33
+ Requires-Dist: python-multipart>=0.0.26
32
34
  Requires-Dist: requests==2.33.1
33
35
  Requires-Dist: scikit-learn>=1.3.0
34
36
  Provides-Extra: dev
@@ -276,36 +278,6 @@ Add to `claude_desktop_config.json`:
276
278
 
277
279
  </details>
278
280
 
279
- ## ChatGPT App Starter
280
-
281
- The server now includes a built-in ChatGPT app surface for incident exploration.
282
-
283
- - **Model-visible app tool:** `open_rootly_incident_workbench`
284
- - **App-only detail tool:** `get_rootly_incident_detail`
285
- - **UI resource:** `ui://rootly/incident-workbench.html`
286
-
287
- This gives ChatGPT a visual Rootly incident workbench without needing a separate backend.
288
-
289
- ### What it does
290
-
291
- - Applies structured incident filters such as team, time range, severity, and status
292
- - Collects a bounded set of incident summaries for the widget
293
- - Lets the widget open a detailed incident pane without exposing the detail tool to the model
294
-
295
- ### Try it in ChatGPT Developer Mode
296
-
297
- Once the MCP server is connected in ChatGPT Developer Mode, try prompts like:
298
-
299
- - `Open the Rootly incident workbench for Infrastructure incidents from the last 7 days`
300
- - `Show me resolved critical incidents for Infrastructure from April 1 through April 13`
301
- - `Open the Rootly incident workbench for database timeout incidents`
302
-
303
- ### Production auth note
304
-
305
- For internal testing and developer-mode setups, the existing bearer-token flow is enough.
306
-
307
- For a public ChatGPT app that exposes customer-specific data or write actions, plan to add OAuth 2.1 support on the MCP side before submission. The current Rootly MCP server forwards bearer tokens, but public Apps SDK submissions expect OAuth 2.1-compatible MCP authorization metadata and token verification.
308
-
309
281
  ## Rootly CLI
310
282
 
311
283
  Standalone CLI for incidents, alerts, services, and on-call operations.
@@ -445,6 +417,7 @@ The default server configuration exposes **110 tools**.
445
417
  - `check_oncall_health_risk`
446
418
  - `check_responder_availability`
447
419
  - `collect_incidents`
420
+ - `createIncident` - create a new incident with a scoped set of fields for agent workflows
448
421
  - `create_override_recommendation`
449
422
  - `find_related_incidents`
450
423
  - `getIncident` - retrieve a single incident for direct verification, including PIR-related fields
@@ -457,7 +430,6 @@ The default server configuration exposes **110 tools**.
457
430
  - `list_endpoints`
458
431
  - `list_incidents`
459
432
  - `list_shifts`
460
- - `open_rootly_incident_workbench`
461
433
  - `search_incidents`
462
434
  - `suggest_solutions`
463
435
  - `updateIncident` - scoped incident update tool for `summary` and `retrospective_progress_status`
@@ -234,36 +234,6 @@ Add to `claude_desktop_config.json`:
234
234
 
235
235
  </details>
236
236
 
237
- ## ChatGPT App Starter
238
-
239
- The server now includes a built-in ChatGPT app surface for incident exploration.
240
-
241
- - **Model-visible app tool:** `open_rootly_incident_workbench`
242
- - **App-only detail tool:** `get_rootly_incident_detail`
243
- - **UI resource:** `ui://rootly/incident-workbench.html`
244
-
245
- This gives ChatGPT a visual Rootly incident workbench without needing a separate backend.
246
-
247
- ### What it does
248
-
249
- - Applies structured incident filters such as team, time range, severity, and status
250
- - Collects a bounded set of incident summaries for the widget
251
- - Lets the widget open a detailed incident pane without exposing the detail tool to the model
252
-
253
- ### Try it in ChatGPT Developer Mode
254
-
255
- Once the MCP server is connected in ChatGPT Developer Mode, try prompts like:
256
-
257
- - `Open the Rootly incident workbench for Infrastructure incidents from the last 7 days`
258
- - `Show me resolved critical incidents for Infrastructure from April 1 through April 13`
259
- - `Open the Rootly incident workbench for database timeout incidents`
260
-
261
- ### Production auth note
262
-
263
- For internal testing and developer-mode setups, the existing bearer-token flow is enough.
264
-
265
- For a public ChatGPT app that exposes customer-specific data or write actions, plan to add OAuth 2.1 support on the MCP side before submission. The current Rootly MCP server forwards bearer tokens, but public Apps SDK submissions expect OAuth 2.1-compatible MCP authorization metadata and token verification.
266
-
267
237
  ## Rootly CLI
268
238
 
269
239
  Standalone CLI for incidents, alerts, services, and on-call operations.
@@ -403,6 +373,7 @@ The default server configuration exposes **110 tools**.
403
373
  - `check_oncall_health_risk`
404
374
  - `check_responder_availability`
405
375
  - `collect_incidents`
376
+ - `createIncident` - create a new incident with a scoped set of fields for agent workflows
406
377
  - `create_override_recommendation`
407
378
  - `find_related_incidents`
408
379
  - `getIncident` - retrieve a single incident for direct verification, including PIR-related fields
@@ -415,7 +386,6 @@ The default server configuration exposes **110 tools**.
415
386
  - `list_endpoints`
416
387
  - `list_incidents`
417
388
  - `list_shifts`
418
- - `open_rootly_incident_workbench`
419
389
  - `search_incidents`
420
390
  - `suggest_solutions`
421
391
  - `updateIncident` - scoped incident update tool for `summary` and `retrospective_progress_status`
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "rootly-mcp-server"
3
- version = "2.2.18"
3
+ version = "2.2.20"
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.12"
@@ -37,7 +37,9 @@ classifiers = [
37
37
  ]
38
38
  dependencies = [
39
39
  "fastmcp[code-mode]==3.2.0", # Pin to patched version with Code Mode support
40
- "authlib>=1.6.9", # Override vulnerable transitive authlib from fastmcp
40
+ "authlib>=1.6.11", # Override vulnerable transitive authlib (GHSA-jj8c-mmj3-mmgv)
41
+ "python-dotenv>=1.2.2", # Override vulnerable transitive python-dotenv (GHSA-m8f7-34r5-grfg)
42
+ "python-multipart>=0.0.26", # Override vulnerable transitive python-multipart (CVE-2026-40347)
41
43
  "cryptography>=46.0.7", # Override vulnerable transitive cryptography
42
44
  "Pygments>=2.20.0", # Override vulnerable transitive Pygments
43
45
  "requests==2.33.1", # Pin to patched version
@@ -50,9 +50,7 @@ def normalize_transport(value: str) -> TransportName:
50
50
  return mapped
51
51
 
52
52
 
53
- def normalize_transport_or_default(
54
- value: str, default: TransportName = "stdio"
55
- ) -> TransportName:
53
+ def normalize_transport_or_default(value: str, default: TransportName = "stdio") -> TransportName:
56
54
  """Normalize transport value, falling back to default when invalid."""
57
55
  try:
58
56
  return normalize_transport(value)
@@ -275,7 +273,9 @@ def run_dual_http_server(
275
273
  stateless=stateless_http,
276
274
  )
277
275
  code_mode_http_app = StreamableHTTPASGIApp(code_mode_session_manager)
278
- routes.append(Route(code_mode_path, endpoint=code_mode_http_app, methods=streamable_methods))
276
+ routes.append(
277
+ Route(code_mode_path, endpoint=code_mode_http_app, methods=streamable_methods)
278
+ )
279
279
 
280
280
  routes.extend(server._get_additional_http_routes()) # noqa: SLF001
281
281
 
@@ -373,7 +373,11 @@ def main():
373
373
  # argparse already normalizes/validates --transport via type=normalize_transport
374
374
  normalized_transport = args.transport
375
375
  code_mode_enabled = args.enable_code_mode or code_mode_enabled_from_env(default=True)
376
- code_mode_path = normalize_code_mode_path(args.code_mode_path) if args.code_mode_path else code_mode_path_from_env()
376
+ code_mode_path = (
377
+ normalize_code_mode_path(args.code_mode_path)
378
+ if args.code_mode_path
379
+ else code_mode_path_from_env()
380
+ )
377
381
  server = create_rootly_mcp_server(
378
382
  swagger_path=args.swagger_path,
379
383
  name=args.name,
@@ -172,8 +172,7 @@ class CompatibleMontySandboxProvider(MontySandboxProvider):
172
172
 
173
173
  inputs = inputs or {}
174
174
  async_functions = {
175
- key: _ensure_async(value)
176
- for key, value in (external_functions or {}).items()
175
+ key: _ensure_async(value) for key, value in (external_functions or {}).items()
177
176
  }
178
177
 
179
178
  monty = self._build_monty_runner(
@@ -219,10 +218,9 @@ class RootlyCodeMode(CodeMode):
219
218
  async def call_tool(tool_name: str, params: dict[str, Any]) -> Any:
220
219
  resolved_name = _normalize_execute_tool_name(tool_name)
221
220
  backend_tools = await _get_cached_tools()
222
- tool = (
223
- transform._find_tool(resolved_name, transform._build_discovery_tools())
224
- or transform._find_tool(resolved_name, backend_tools)
225
- )
221
+ tool = transform._find_tool(
222
+ resolved_name, transform._build_discovery_tools()
223
+ ) or transform._find_tool(resolved_name, backend_tools)
226
224
  if tool is None:
227
225
  raise NotFoundError(f"Unknown tool: {tool_name}")
228
226
 
@@ -22,7 +22,6 @@ from .exceptions import RootlyAuthenticationError
22
22
  from .mcp_error import MCPError
23
23
  from .security import mask_sensitive_data, sanitize_error_message
24
24
  from .tools.alerts import register_alert_tools
25
- from .tools.chatgpt_app import register_chatgpt_app_tools
26
25
  from .tools.incidents import register_incident_tools
27
26
  from .tools.oncall import register_oncall_tools
28
27
  from .tools.resources import register_resource_handlers
@@ -202,16 +201,14 @@ def _log_tool_usage_event(
202
201
  event["error_type"] = error_type
203
202
  if error_context:
204
203
  event.update(
205
- {
206
- key: value
207
- for key, value in error_context.items()
208
- if value not in ("", [], None, {})
209
- }
204
+ {key: value for key, value in error_context.items() if value not in ("", [], None, {})}
210
205
  )
211
206
 
212
207
  _configure_tool_usage_json_logger()
213
208
  _tool_usage_json_logger.info(
214
- json.dumps({k: v for k, v in event.items() if v not in ("", [], None)}, separators=(",", ":"))
209
+ json.dumps(
210
+ {k: v for k, v in event.items() if v not in ("", [], None)}, separators=(",", ":")
211
+ )
215
212
  )
216
213
 
217
214
 
@@ -406,8 +403,7 @@ def create_rootly_mcp_server(
406
403
  f"/v1{path}" if not path.startswith("/v1") else path for path in allowed_paths
407
404
  ]
408
405
  delete_allowed_paths_v1 = [
409
- f"/v1{path}" if not path.startswith("/v1") else path
410
- for path in delete_allowed_paths
406
+ f"/v1{path}" if not path.startswith("/v1") else path for path in delete_allowed_paths
411
407
  ]
412
408
 
413
409
  logger.info(f"Creating Rootly MCP Server with allowed paths: {allowed_paths_v1}")
@@ -519,7 +515,9 @@ def create_rootly_mcp_server(
519
515
  logger.debug(
520
516
  f"make_authenticated_request: client_ip={client_ip}, headers_keys={list(request_headers.keys()) if request_headers else []}"
521
517
  )
522
- direct_auth_header = request_headers.get("authorization", "") if request_headers else ""
518
+ direct_auth_header = (
519
+ request_headers.get("authorization", "") if request_headers else ""
520
+ )
523
521
  effective_auth_header = direct_auth_header or _session_auth_token.get("")
524
522
  if direct_auth_header:
525
523
  logger.debug("make_authenticated_request: Found auth header, adding to request")
@@ -576,13 +574,6 @@ def create_rootly_mcp_server(
576
574
  mcp_error=MCPError,
577
575
  )
578
576
 
579
- register_chatgpt_app_tools(
580
- mcp=mcp,
581
- make_authenticated_request=make_authenticated_request,
582
- strip_heavy_nested_data=strip_heavy_nested_data,
583
- mcp_error=MCPError,
584
- )
585
-
586
577
  register_alert_tools(
587
578
  mcp=mcp,
588
579
  make_authenticated_request=make_authenticated_request,
@@ -164,8 +164,7 @@ def _filter_openapi_spec(
164
164
  if not allow_delete:
165
165
  path_item.pop("delete", None)
166
166
  if not any(
167
- method.lower() in ["get", "post", "put", "patch", "delete"]
168
- for method in path_item
167
+ method.lower() in ["get", "post", "put", "patch", "delete"] for method in path_item
169
168
  ):
170
169
  paths_to_remove.append(path)
171
170
  for path in paths_to_remove:
@@ -1,14 +1,12 @@
1
1
  """Tool registration modules for Rootly MCP server."""
2
2
 
3
3
  from .alerts import register_alert_tools
4
- from .chatgpt_app import register_chatgpt_app_tools
5
4
  from .incidents import register_incident_tools
6
5
  from .oncall import register_oncall_tools
7
6
  from .resources import register_resource_handlers
8
7
 
9
8
  __all__ = [
10
9
  "register_alert_tools",
11
- "register_chatgpt_app_tools",
12
10
  "register_incident_tools",
13
11
  "register_oncall_tools",
14
12
  "register_resource_handlers",