rootly-mcp-server 1.0.0__tar.gz → 2.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- rootly_mcp_server-2.0.0/.github/workflows/pypi-release.yml +33 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/.gitignore +15 -1
- rootly_mcp_server-2.0.0/.semaphore/deploy.yml +55 -0
- rootly_mcp_server-2.0.0/.semaphore/semaphore.yml +45 -0
- rootly_mcp_server-2.0.0/.semaphore/update-task-definition.sh +43 -0
- rootly_mcp_server-2.0.0/CLAUDE.md +68 -0
- rootly_mcp_server-2.0.0/Dockerfile +28 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/PKG-INFO +95 -29
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/README.md +91 -26
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/pyproject.toml +12 -16
- rootly_mcp_server-2.0.0/rootly_fastmcp_server.py +148 -0
- rootly_mcp_server-2.0.0/rootly_fastmcp_server_routemap.py +210 -0
- rootly_mcp_server-2.0.0/rootly_openapi_loader.py +96 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/src/rootly_mcp_server/__init__.py +1 -1
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/src/rootly_mcp_server/__main__.py +78 -10
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/src/rootly_mcp_server/client.py +40 -26
- rootly_mcp_server-2.0.0/src/rootly_mcp_server/server.py +525 -0
- rootly_mcp_server-2.0.0/src/rootly_mcp_server/test_client.py +148 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/uv.lock +164 -13
- rootly_mcp_server-1.0.0/src/rootly_mcp_server/data/swagger.json +0 -1
- rootly_mcp_server-1.0.0/src/rootly_mcp_server/server.py +0 -451
- rootly_mcp_server-1.0.0/src/rootly_mcp_server/test_client.py +0 -67
- rootly_mcp_server-1.0.0/swagger.json +0 -1
- rootly_mcp_server-1.0.0/test_mcp_client.py +0 -106
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/LICENSE +0 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/rootly-mcp-server-demo.gif +0 -0
- {rootly_mcp_server-1.0.0 → rootly_mcp_server-2.0.0}/src/rootly_mcp_server/data/__init__.py +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
name: Publish Python 🐍 distribution 📦 to PyPI on tag
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- '*'
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build-and-publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- name: Checkout code
|
|
13
|
+
uses: actions/checkout@v4
|
|
14
|
+
|
|
15
|
+
- name: Set up Python
|
|
16
|
+
uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: '3.12'
|
|
19
|
+
|
|
20
|
+
- name: Install uv and build tools
|
|
21
|
+
run: |
|
|
22
|
+
pip install build twine
|
|
23
|
+
|
|
24
|
+
- name: Build package
|
|
25
|
+
run: |
|
|
26
|
+
python -m build
|
|
27
|
+
|
|
28
|
+
- name: Publish to PyPI
|
|
29
|
+
env:
|
|
30
|
+
TWINE_USERNAME: __token__
|
|
31
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
32
|
+
run: |
|
|
33
|
+
twine upload dist/*
|
|
@@ -77,6 +77,7 @@ target/
|
|
|
77
77
|
|
|
78
78
|
# Jupyter Notebook
|
|
79
79
|
.ipynb_checkpoints
|
|
80
|
+
*.ipynb
|
|
80
81
|
|
|
81
82
|
# IPython
|
|
82
83
|
profile_default/
|
|
@@ -173,4 +174,17 @@ cython_debug/
|
|
|
173
174
|
# PyPI configuration file
|
|
174
175
|
.pypirc
|
|
175
176
|
|
|
176
|
-
|
|
177
|
+
# IDE/Editor files
|
|
178
|
+
.cursor
|
|
179
|
+
.vscode/
|
|
180
|
+
*.swp
|
|
181
|
+
*.swo
|
|
182
|
+
*~
|
|
183
|
+
|
|
184
|
+
# MCP Server specific
|
|
185
|
+
# Downloaded swagger.json files (auto-fetched from URL)
|
|
186
|
+
swagger.json
|
|
187
|
+
|
|
188
|
+
# Test outputs and temporary files
|
|
189
|
+
test_output/
|
|
190
|
+
*.tmp
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
version: v1.0
|
|
2
|
+
name: Build and Deploy
|
|
3
|
+
|
|
4
|
+
queue:
|
|
5
|
+
name: Deployment Queue
|
|
6
|
+
scope: project
|
|
7
|
+
|
|
8
|
+
agent:
|
|
9
|
+
machine:
|
|
10
|
+
type: r1-standard-4
|
|
11
|
+
os_image: ubuntu2204
|
|
12
|
+
|
|
13
|
+
blocks:
|
|
14
|
+
- name: 'Deploy'
|
|
15
|
+
dependencies: []
|
|
16
|
+
task:
|
|
17
|
+
secrets:
|
|
18
|
+
- name: 'AWS Credentials'
|
|
19
|
+
prologue:
|
|
20
|
+
commands:
|
|
21
|
+
- export AWS_PROFILE=production
|
|
22
|
+
- export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
23
|
+
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com
|
|
24
|
+
jobs:
|
|
25
|
+
- name: Deploy
|
|
26
|
+
commands:
|
|
27
|
+
- checkout
|
|
28
|
+
- |
|
|
29
|
+
export TASK_FAMILY=rootly-mcp-server
|
|
30
|
+
export CONTAINER_NAME=mcp
|
|
31
|
+
export IMAGE=657716690934.dkr.ecr.us-east-1.amazonaws.com/rootly/mcp:${SEMAPHORE_GIT_SHA}
|
|
32
|
+
NEW_TASK_DEFINITION_ARN=$(./.semaphore/update-task-definition.sh)
|
|
33
|
+
|
|
34
|
+
aws ecs update-service \
|
|
35
|
+
--cluster rootly-web \
|
|
36
|
+
--service rootly-mcp-server \
|
|
37
|
+
--task-definition "$NEW_TASK_DEFINITION_ARN" \
|
|
38
|
+
--deployment-configuration "deploymentCircuitBreaker={enable=true,rollback=true},maximumPercent=200,minimumHealthyPercent=100" \
|
|
39
|
+
--force-new-deployment >/dev/null
|
|
40
|
+
|
|
41
|
+
echo "Waiting for service to stabilize at the new revision..."
|
|
42
|
+
|
|
43
|
+
# Wait for the service to stabilize for up to 10 minutes
|
|
44
|
+
for i in {1..40}; do
|
|
45
|
+
if aws ecs describe-services --cluster rootly-web --service rootly-mcp-server --output json | jq -e \
|
|
46
|
+
'.services | map(select((.deployments | length) != 1 or .runningCount != .desiredCount)) | length == 0' >/dev/null; then
|
|
47
|
+
break
|
|
48
|
+
fi
|
|
49
|
+
sleep 15
|
|
50
|
+
done
|
|
51
|
+
|
|
52
|
+
if [ $i -eq 40 ]; then
|
|
53
|
+
echo "Service failed to stabilize after 10 minutes"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
version: v1.0
|
|
2
|
+
name: Build and Deploy
|
|
3
|
+
|
|
4
|
+
queue:
|
|
5
|
+
name: Build Queue
|
|
6
|
+
scope: project
|
|
7
|
+
|
|
8
|
+
auto_cancel:
|
|
9
|
+
queued:
|
|
10
|
+
when: 'true'
|
|
11
|
+
|
|
12
|
+
agent:
|
|
13
|
+
machine:
|
|
14
|
+
type: r1-standard-4
|
|
15
|
+
os_image: ubuntu2204
|
|
16
|
+
|
|
17
|
+
blocks:
|
|
18
|
+
- name: 'Build'
|
|
19
|
+
dependencies: []
|
|
20
|
+
task:
|
|
21
|
+
secrets:
|
|
22
|
+
- name: 'AWS Credentials'
|
|
23
|
+
prologue:
|
|
24
|
+
commands:
|
|
25
|
+
- export AWS_PROFILE=production
|
|
26
|
+
- export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
|
|
27
|
+
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com
|
|
28
|
+
jobs:
|
|
29
|
+
- name: Build
|
|
30
|
+
commands:
|
|
31
|
+
- checkout
|
|
32
|
+
- export BUILDKIT_PROGRESS=plain
|
|
33
|
+
- |
|
|
34
|
+
docker build --push \
|
|
35
|
+
-t 657716690934.dkr.ecr.us-east-1.amazonaws.com/rootly/mcp:${SEMAPHORE_GIT_SHA} \
|
|
36
|
+
-t 657716690934.dkr.ecr.us-east-1.amazonaws.com/rootly/mcp:latest \
|
|
37
|
+
-t 657716690934.dkr.ecr.us-east-1.amazonaws.com/rootly/mcp:production .
|
|
38
|
+
|
|
39
|
+
promotions:
|
|
40
|
+
- name: Deploy
|
|
41
|
+
pipeline_file: deploy.yml
|
|
42
|
+
deployment_target: production
|
|
43
|
+
|
|
44
|
+
auto_promote:
|
|
45
|
+
when: branch = 'main' AND result = 'passed'
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
set -e
|
|
4
|
+
|
|
5
|
+
# Updates a task definition with a new container image
|
|
6
|
+
# Returns the new task definition ARN
|
|
7
|
+
#
|
|
8
|
+
# Required environment variables:
|
|
9
|
+
# TASK_FAMILY - Task definition family
|
|
10
|
+
# CONTAINER_NAME - Container name to update
|
|
11
|
+
# IMAGE - New container image to deploy
|
|
12
|
+
|
|
13
|
+
if [ -z "$TASK_FAMILY" ] || [ -z "$CONTAINER_NAME" ] || [ -z "$IMAGE" ]; then
|
|
14
|
+
echo "Error: TASK_FAMILY, CONTAINER_NAME, and IMAGE environment variables are required"
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
TASK_DEFINITION="$(aws ecs describe-task-definition --task-definition=$TASK_FAMILY | jq '.taskDefinition')"
|
|
19
|
+
|
|
20
|
+
# Remove fields that can't be used in register-task-definition
|
|
21
|
+
TASK_DEFINITION="$(jq 'del(.taskDefinitionArn, .revision, .status, .requiresAttributes, .compatibilities, .registeredAt, .registeredBy)' <<< "$TASK_DEFINITION")"
|
|
22
|
+
|
|
23
|
+
# Find the index of the specified container
|
|
24
|
+
CONTAINER_INDEX="$(jq --arg NAME "$CONTAINER_NAME" '.containerDefinitions | map(.name) | index($NAME)' <<< "$TASK_DEFINITION")"
|
|
25
|
+
|
|
26
|
+
if [ "$CONTAINER_INDEX" = "null" ]; then
|
|
27
|
+
echo "Error: Container '$CONTAINER_NAME' not found in task definition"
|
|
28
|
+
exit 1
|
|
29
|
+
fi
|
|
30
|
+
|
|
31
|
+
# Update the container image
|
|
32
|
+
NEW_TASK_DEFINITION="$(jq --arg INDEX "$CONTAINER_INDEX" --arg IMAGE "$IMAGE" '.containerDefinitions[$INDEX | tonumber].image = $IMAGE' <<< "$TASK_DEFINITION")"
|
|
33
|
+
|
|
34
|
+
# Register the new task definition
|
|
35
|
+
NEW_TASK_DEFINITION_ARN="$(aws ecs register-task-definition --cli-input-json "$NEW_TASK_DEFINITION" --output text --query 'taskDefinition.taskDefinitionArn')"
|
|
36
|
+
|
|
37
|
+
echo "$TASK_DEFINITION" > task-definition.json
|
|
38
|
+
echo "$NEW_TASK_DEFINITION" > new-task-definition.json
|
|
39
|
+
|
|
40
|
+
echo "Applying update:" >&2
|
|
41
|
+
diff -u task-definition.json new-task-definition.json >&2 || :
|
|
42
|
+
|
|
43
|
+
echo "$NEW_TASK_DEFINITION_ARN"
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Development Commands
|
|
6
|
+
|
|
7
|
+
### Environment Setup
|
|
8
|
+
```bash
|
|
9
|
+
# Install dependencies using uv
|
|
10
|
+
uv pip install .
|
|
11
|
+
|
|
12
|
+
# Create and activate virtual environment
|
|
13
|
+
uv venv .venv
|
|
14
|
+
source .venv/bin/activate
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
### Testing and Quality
|
|
18
|
+
```bash
|
|
19
|
+
# Run test client to verify setup
|
|
20
|
+
python test_mcp_client.py
|
|
21
|
+
|
|
22
|
+
# Linting and type checking (if you add dev dependencies)
|
|
23
|
+
ruff check src/
|
|
24
|
+
pyright src/
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Package Building
|
|
28
|
+
```bash
|
|
29
|
+
# Build the package
|
|
30
|
+
uv build
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Architecture Overview
|
|
34
|
+
|
|
35
|
+
This is an MCP (Model Context Protocol) server that provides AI agents access to the Rootly API for incident management. The project uses Python 3.12+ with `uv` for dependency management.
|
|
36
|
+
|
|
37
|
+
### Core Components
|
|
38
|
+
|
|
39
|
+
- **`server.py`**: Main MCP server implementation (`RootlyMCPServer` class)
|
|
40
|
+
- Dynamically generates MCP tools from Rootly's OpenAPI/Swagger specification
|
|
41
|
+
- Filters available endpoints via `allowed_paths` configuration for security and context management
|
|
42
|
+
- Implements automatic pagination (default 10 items) for incident endpoints
|
|
43
|
+
- Uses FastMCP framework with ERROR log level to prevent UI noise
|
|
44
|
+
|
|
45
|
+
- **`client.py`**: Rootly API client (`RootlyClient` class)
|
|
46
|
+
- Handles authentication via `ROOTLY_API_TOKEN` environment variable
|
|
47
|
+
- Supports both JSON and JSON-API formats depending on endpoint requirements
|
|
48
|
+
- Base URL defaults to `https://api.rootly.com`
|
|
49
|
+
- Auto-prefixes paths with `/v1` if not present
|
|
50
|
+
|
|
51
|
+
- **`data/swagger.json`**: Cached OpenAPI specification
|
|
52
|
+
- Falls back to downloading from `https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json`
|
|
53
|
+
- Server searches local directories before downloading
|
|
54
|
+
|
|
55
|
+
### Key Design Patterns
|
|
56
|
+
|
|
57
|
+
- **Dynamic Tool Generation**: Tools are created at runtime based on Swagger spec rather than hardcoded
|
|
58
|
+
- **Path Whitelisting**: Only specific endpoints in `allowed_paths` are exposed to prevent context overflow and maintain security
|
|
59
|
+
- **JSON-API Support**: Automatically wraps request bodies in JSON-API format for create/update operations
|
|
60
|
+
- **Error Resilience**: Comprehensive error handling with structured JSON error responses
|
|
61
|
+
|
|
62
|
+
### Configuration
|
|
63
|
+
|
|
64
|
+
The `allowed_paths` array in `server.py:56-92` controls which Rootly API endpoints are available. Modify this list to expose additional endpoints. Paths should be specified without the `/v1` prefix.
|
|
65
|
+
|
|
66
|
+
### Environment Variables
|
|
67
|
+
|
|
68
|
+
- `ROOTLY_API_TOKEN`: Required authentication token for Rootly API access
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Use Python 3.12 slim image as base
|
|
2
|
+
FROM python:3.12-slim
|
|
3
|
+
|
|
4
|
+
# Set working directory
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Install system dependencies
|
|
8
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
9
|
+
gcc curl ca-certificates \
|
|
10
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
11
|
+
|
|
12
|
+
# Install uv
|
|
13
|
+
RUN pip install --no-cache-dir uv
|
|
14
|
+
|
|
15
|
+
# Copy the entire project first for installation
|
|
16
|
+
COPY . .
|
|
17
|
+
|
|
18
|
+
# Install the package and its dependencies
|
|
19
|
+
RUN uv pip install --system --no-cache-dir -e .
|
|
20
|
+
|
|
21
|
+
# Expose the port the app runs on
|
|
22
|
+
EXPOSE 8000
|
|
23
|
+
|
|
24
|
+
# Set environment variables
|
|
25
|
+
ENV PYTHONUNBUFFERED=1
|
|
26
|
+
|
|
27
|
+
# Run the application
|
|
28
|
+
CMD ["rootly-mcp-server", "--transport", "sse", "--log-level", "INFO", "--host", "0.0.0.0", "--port", "8000", "--hosted"]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: rootly-mcp-server
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
4
4
|
Summary: A Model Context Protocol server for Rootly APIs using OpenAPI spec
|
|
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
|
|
@@ -8,13 +8,14 @@ Author-email: Rootly AI Labs <support@rootly.com>
|
|
|
8
8
|
License-Expression: Apache-2.0
|
|
9
9
|
License-File: LICENSE
|
|
10
10
|
Keywords: automation,incidents,llm,mcp,rootly
|
|
11
|
-
Classifier: Development Status ::
|
|
11
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
15
|
Classifier: Topic :: Software Development :: Build Tools
|
|
16
16
|
Requires-Python: >=3.12
|
|
17
|
-
Requires-Dist:
|
|
17
|
+
Requires-Dist: fastmcp==2.4.0
|
|
18
|
+
Requires-Dist: httpx>=0.24.0
|
|
18
19
|
Requires-Dist: pydantic>=2.0.0
|
|
19
20
|
Requires-Dist: requests>=2.28.0
|
|
20
21
|
Provides-Extra: dev
|
|
@@ -25,11 +26,10 @@ Description-Content-Type: text/markdown
|
|
|
25
26
|
# Rootly MCP Server
|
|
26
27
|
|
|
27
28
|
An MCP server for [Rootly API](https://docs.rootly.com/api-reference/overview) that you can plug into your favorite MCP-compatible editors like Cursor, Windsurf, and Claude. Resolve production incidents in under a minute without leaving your IDE.
|
|
28
|
-
<br>
|
|
29
|
-
<br>
|
|
30
29
|
|
|
31
|
-
](https://cursor.com/install-mcp?name=rootly&config=eyJjb21tYW5kIjoibnB4IC15IG1jcC1yZW1vdGUgaHR0cHM6Ly9tY3Aucm9vdGx5LmNvbS9zc2UgLS1oZWFkZXIgQXV0aG9yaXphdGlvbjoke1JPT1RMWV9BVVRIX0hFQURFUn0iLCJlbnYiOnsiUk9PVExZX0FVVEhfSEVBREVSIjoiQmVhcmVyIDxZT1VSX1JPT1RMWV9BUElfVE9LRU4%2BIn19)
|
|
32
31
|
|
|
32
|
+

|
|
33
33
|
|
|
34
34
|
## Prerequisites
|
|
35
35
|
|
|
@@ -41,19 +41,17 @@ An MCP server for [Rootly API](https://docs.rootly.com/api-reference/overview) t
|
|
|
41
41
|
- [Rootly API token](https://docs.rootly.com/api-reference/overview#how-to-generate-an-api-key%3F)
|
|
42
42
|
|
|
43
43
|
## Run it in your IDE
|
|
44
|
+
|
|
44
45
|
Install with our [PyPi package](https://pypi.org/project/rootly-mcp-server/) or by cloning this repo.
|
|
45
46
|
|
|
46
47
|
To set it up in your favorite MCP-compatible editor (we tested it with Cursor and Windsurf), here is the config :
|
|
48
|
+
|
|
47
49
|
```json
|
|
48
50
|
{
|
|
49
51
|
"mcpServers": {
|
|
50
52
|
"rootly": {
|
|
51
53
|
"command": "uvx",
|
|
52
|
-
"args": [
|
|
53
|
-
"--from",
|
|
54
|
-
"rootly-mcp-server",
|
|
55
|
-
"rootly-mcp-server"
|
|
56
|
-
],
|
|
54
|
+
"args": ["--from", "rootly-mcp-server", "rootly-mcp-server"],
|
|
57
55
|
"env": {
|
|
58
56
|
"ROOTLY_API_TOKEN": "<YOUR_ROOTLY_API_TOKEN>"
|
|
59
57
|
}
|
|
@@ -61,68 +59,136 @@ To set it up in your favorite MCP-compatible editor (we tested it with Cursor an
|
|
|
61
59
|
}
|
|
62
60
|
}
|
|
63
61
|
```
|
|
62
|
+
|
|
64
63
|
If you want to customize `allowed_paths` to access more Rootly API paths, clone the package and use this config.
|
|
64
|
+
|
|
65
65
|
```json
|
|
66
66
|
{
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
67
|
+
"mcpServers": {
|
|
68
|
+
"rootly": {
|
|
69
|
+
"command": "uv",
|
|
70
|
+
"args": [
|
|
71
|
+
"run",
|
|
72
|
+
"--directory",
|
|
73
|
+
"/path/to/rootly-mcp-server",
|
|
74
|
+
"rootly-mcp-server"
|
|
75
|
+
],
|
|
76
|
+
"env": {
|
|
77
|
+
"ROOTLY_API_TOKEN": "<YOUR_ROOTLY_API_TOKEN>"
|
|
79
78
|
}
|
|
80
79
|
}
|
|
81
80
|
}
|
|
81
|
+
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
84
|
## Features
|
|
85
|
+
|
|
85
86
|
This server dynamically generates MCP resources based on Rootly's OpenAPI (Swagger) specification:
|
|
87
|
+
|
|
86
88
|
- Dynamically generated MCP tools based on Rootly's OpenAPI specification
|
|
87
89
|
- Default pagination (10 items) for incident endpoints to prevent context window overflow
|
|
88
90
|
- Limits the number of API paths exposed to the AI agent
|
|
89
91
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
### Whitelisted Endpoints
|
|
93
|
+
|
|
94
|
+
By default, the following Rootly API endpoints are exposed to the AI agent (see `allowed_paths` in `src/rootly_mcp_server/server.py`):
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
/v1/incidents
|
|
98
|
+
/v1/incidents/{incident_id}/alerts
|
|
99
|
+
/v1/alerts
|
|
100
|
+
/v1/alerts/{alert_id}
|
|
101
|
+
/v1/severities
|
|
102
|
+
/v1/severities/{severity_id}
|
|
103
|
+
/v1/teams
|
|
104
|
+
/v1/teams/{team_id}
|
|
105
|
+
/v1/services
|
|
106
|
+
/v1/services/{service_id}
|
|
107
|
+
/v1/functionalities
|
|
108
|
+
/v1/functionalities/{functionality_id}
|
|
109
|
+
/v1/incident_types
|
|
110
|
+
/v1/incident_types/{incident_type_id}
|
|
111
|
+
/v1/incident_action_items
|
|
112
|
+
/v1/incident_action_items/{incident_action_item_id}
|
|
113
|
+
/v1/incidents/{incident_id}/action_items
|
|
114
|
+
/v1/workflows
|
|
115
|
+
/v1/workflows/{workflow_id}
|
|
116
|
+
/v1/workflow_runs
|
|
117
|
+
/v1/workflow_runs/{workflow_run_id}
|
|
118
|
+
/v1/environments
|
|
119
|
+
/v1/environments/{environment_id}
|
|
120
|
+
/v1/users
|
|
121
|
+
/v1/users/{user_id}
|
|
122
|
+
/v1/users/me
|
|
123
|
+
/v1/status_pages
|
|
124
|
+
/v1/status_pages/{status_page_id}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
We limited the number of API paths exposed for 2 reasons:
|
|
93
128
|
|
|
94
|
-
|
|
129
|
+
- Context size: because [Rootly's API](https://docs.rootly.com/api-reference/overview) is very rich in paths, AI agents can get overwhelmed and not perform simple actions properly.
|
|
130
|
+
- Security: if you want to limit the type of information or actions that users can access through the MCP server
|
|
95
131
|
|
|
96
|
-
|
|
97
|
-
This project is a prototype and not intended for production use. If you have featured ideas or spotted some issues, feel free to submit a PR or open an issue.
|
|
132
|
+
If you want to make more paths available, edit the variable `allowed_paths` in `src/rootly_mcp_server/server.py`.
|
|
98
133
|
|
|
99
134
|
## About the Rootly AI Labs
|
|
135
|
+
|
|
100
136
|
This project was developed by the [Rootly AI Labs](https://labs.rootly.ai/). The AI Labs is building the future of system reliability and operational excellence. We operate as an open-source incubator, sharing ideas, experimenting, and rapidly prototyping. We're committed to ensuring our research benefits the entire community.
|
|
101
137
|

|
|
102
138
|
|
|
103
139
|
## Developer Setup & Troubleshooting
|
|
104
140
|
|
|
105
141
|
### 1. Install dependencies with `uv`
|
|
142
|
+
|
|
106
143
|
This project uses [`uv`](https://github.com/astral-sh/uv) for fast dependency management. To install all dependencies from your `pyproject.toml`:
|
|
144
|
+
|
|
107
145
|
```bash
|
|
108
146
|
uv pip install .
|
|
109
147
|
```
|
|
110
148
|
|
|
111
149
|
### 2. Using a virtual environment
|
|
150
|
+
|
|
112
151
|
It is recommended to use a virtual environment for development:
|
|
152
|
+
|
|
113
153
|
```bash
|
|
114
154
|
uv venv .venv
|
|
115
155
|
source .venv/bin/activate
|
|
116
156
|
```
|
|
117
157
|
|
|
118
158
|
### 3. Running the test client
|
|
159
|
+
|
|
119
160
|
To run the test client and verify your setup:
|
|
161
|
+
|
|
120
162
|
```bash
|
|
121
163
|
python test_mcp_client.py
|
|
122
164
|
```
|
|
123
165
|
|
|
124
166
|
### 5. General tips
|
|
167
|
+
|
|
125
168
|
- Always activate your virtual environment before running scripts.
|
|
126
169
|
- If you add new dependencies, use `uv pip install <package>` to keep your environment up to date.
|
|
127
170
|
- If you encounter issues, check your Python version and ensure it matches the project's requirements.
|
|
128
171
|
|
|
172
|
+
### 6. Connecting to Our MCP Server
|
|
173
|
+
|
|
174
|
+
You can configure your client to connect directly to our hosted MCP server:
|
|
175
|
+
|
|
176
|
+
```json
|
|
177
|
+
{
|
|
178
|
+
"mcpServers": {
|
|
179
|
+
"rootly": {
|
|
180
|
+
"command": "npx",
|
|
181
|
+
"args": [
|
|
182
|
+
"-y",
|
|
183
|
+
"mcp-remote",
|
|
184
|
+
"https://mcp.rootly.com/sse",
|
|
185
|
+
"--header",
|
|
186
|
+
"Authorization:${ROOTLY_AUTH_HEADER}"
|
|
187
|
+
],
|
|
188
|
+
"env": {
|
|
189
|
+
"ROOTLY_AUTH_HEADER": "Bearer <YOUR_ROOTLY_API_TOKEN>"
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
```
|