rootly-mcp-server 0.0.5__py3-none-any.whl → 1.0.0__py3-none-any.whl

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.
@@ -24,7 +24,7 @@ class RootlyClient:
24
24
  raise ValueError("ROOTLY_API_TOKEN environment variable is not set")
25
25
  return api_token
26
26
 
27
- def make_request(self, method: str, path: str, query_params: Optional[Dict[str, Any]] = None, json_data: Optional[Dict[str, Any]] = None) -> str:
27
+ def make_request(self, method: str, path: str, query_params: Optional[Dict[str, Any]] = None, json_data: Optional[Dict[str, Any]] = None, json_api_type: Optional[str] = None) -> str:
28
28
  """
29
29
  Make an authenticated request to the Rootly API.
30
30
 
@@ -33,16 +33,32 @@ class RootlyClient:
33
33
  path: The API path.
34
34
  query_params: Query parameters for the request.
35
35
  json_data: JSON data for the request body.
36
+ json_api_type: If set, use JSON-API format and this type value.
36
37
 
37
38
  Returns:
38
39
  The API response as a JSON string.
39
40
  """
41
+ # Default headers
40
42
  headers = {
41
43
  "Authorization": f"Bearer {self._api_token}",
42
44
  "Content-Type": "application/json",
43
45
  "Accept": "application/json"
44
46
  }
45
-
47
+
48
+ # If JSON-API, update headers and wrap payload
49
+ if json_api_type and method.upper() in ["POST", "PUT", "PATCH"]:
50
+ headers["Content-Type"] = "application/vnd.api+json"
51
+ headers["Accept"] = "application/vnd.api+json"
52
+ if json_data:
53
+ json_data = {
54
+ "data": {
55
+ "type": json_api_type,
56
+ "attributes": json_data
57
+ }
58
+ }
59
+ else:
60
+ json_data = None
61
+
46
62
  # Ensure path starts with a slash
47
63
  if not path.startswith("/"):
48
64
  path = f"/{path}"
@@ -55,7 +55,40 @@ class RootlyMCPServer(FastMCP):
55
55
  # Set default allowed paths if none provided
56
56
  self.allowed_paths = allowed_paths or [
57
57
  "/incidents",
58
- "/incidents/{incident_id}/alerts"
58
+ "/incidents/{incident_id}/alerts",
59
+ "/alerts",
60
+ "/alerts/{alert_id}",
61
+ "/severities",
62
+ "/severities/{severity_id}",
63
+ "/teams",
64
+ "/teams/{team_id}",
65
+ "/services",
66
+ "/services/{service_id}",
67
+ "/functionalities",
68
+ "/functionalities/{functionality_id}",
69
+ # Incident types
70
+ "/incident_types",
71
+ "/incident_types/{incident_type_id}",
72
+ # Action items (all, by id, by incident)
73
+ "/incident_action_items",
74
+ "/incident_action_items/{incident_action_item_id}",
75
+ "/incidents/{incident_id}/action_items",
76
+ # Workflows
77
+ "/workflows",
78
+ "/workflows/{workflow_id}",
79
+ # Workflow runs
80
+ "/workflow_runs",
81
+ "/workflow_runs/{workflow_run_id}",
82
+ # Environments
83
+ "/environments",
84
+ "/environments/{environment_id}",
85
+ # Users
86
+ "/users",
87
+ "/users/{user_id}",
88
+ "/users/me",
89
+ # Status pages
90
+ "/status_pages",
91
+ "/status_pages/{status_page_id}"
59
92
  ]
60
93
  # Add /v1 prefix to paths if not present
61
94
  self.allowed_paths = [
@@ -357,7 +390,7 @@ class RootlyMCPServer(FastMCP):
357
390
  path: The API path.
358
391
  method: The HTTP method.
359
392
  operation: The Swagger operation object.
360
- **kwargs: The parameters for the request.
393
+ **v: The parameters for the request.
361
394
 
362
395
  Returns:
363
396
  The API response as a JSON string.
@@ -379,38 +412,39 @@ class RootlyMCPServer(FastMCP):
379
412
  body_params = {}
380
413
 
381
414
  if method.lower() == "get":
382
- # For GET requests, all remaining parameters are query parameters
383
415
  query_params = kwargs
384
-
385
- # Add default pagination for incident-related endpoints
386
416
  if "incidents" in path and method.lower() == "get":
387
- # Check if pagination parameters are already specified
388
417
  has_pagination = any(param.startswith("page[") for param in query_params.keys())
389
-
390
- # If no pagination parameters are specified, add default page size
391
418
  if not has_pagination:
392
419
  query_params["page[size]"] = self.default_page_size
393
420
  logger.debug(f"Added default pagination (page[size]={self.default_page_size}) for incidents endpoint: {path}")
394
421
  else:
395
- # For other methods, check which parameters are query parameters
396
422
  for param in operation.get("parameters", []):
397
423
  param_name = param.get("name")
398
424
  param_in = param.get("in")
399
-
400
425
  if param_in == "query" and param_name in kwargs:
401
426
  query_params[param_name] = kwargs.pop(param_name)
402
-
403
- # All remaining parameters go in the request body
404
427
  body_params = kwargs
405
428
 
406
- # Make the API request
407
429
  try:
430
+ json_api_type = None
431
+ if method.lower() in ["post", "put", "patch"]:
432
+ segments = [seg for seg in actual_path.split("/") if seg and not seg.startswith(":") and not seg.startswith("{")]
433
+ if segments:
434
+ if segments[-1].startswith("by_") or segments[-1].endswith("_id") or segments[-1].startswith("id") or segments[-1].startswith("{id"):
435
+ if len(segments) > 1:
436
+ json_api_type = segments[-2]
437
+ else:
438
+ json_api_type = segments[-1]
439
+
408
440
  response = self.client.make_request(
409
441
  method=method.upper(),
410
442
  path=actual_path,
411
443
  query_params=query_params if query_params else None,
412
- json_data=body_params if body_params else None
444
+ json_data=body_params if body_params else None,
445
+ json_api_type=json_api_type
413
446
  )
447
+ # Do not include kwargs or payload in the output, just return the response
414
448
  return response
415
449
  except Exception as e:
416
450
  logger.error(f"Error calling Rootly API: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rootly-mcp-server
3
- Version: 0.0.5
3
+ Version: 1.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
@@ -22,7 +22,6 @@ Requires-Dist: black>=23.0.0; extra == 'dev'
22
22
  Requires-Dist: isort>=5.0.0; extra == 'dev'
23
23
  Description-Content-Type: text/markdown
24
24
 
25
-
26
25
  # Rootly MCP Server
27
26
 
28
27
  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.
@@ -101,3 +100,29 @@ This project is a prototype and not intended for production use. If you have fea
101
100
  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.
102
101
  ![Rootly AI logo](https://github.com/Rootly-AI-Labs/EventOrOutage/raw/main/rootly-ai.png)
103
102
 
103
+ ## Developer Setup & Troubleshooting
104
+
105
+ ### 1. Install dependencies with `uv`
106
+ This project uses [`uv`](https://github.com/astral-sh/uv) for fast dependency management. To install all dependencies from your `pyproject.toml`:
107
+ ```bash
108
+ uv pip install .
109
+ ```
110
+
111
+ ### 2. Using a virtual environment
112
+ It is recommended to use a virtual environment for development:
113
+ ```bash
114
+ uv venv .venv
115
+ source .venv/bin/activate
116
+ ```
117
+
118
+ ### 3. Running the test client
119
+ To run the test client and verify your setup:
120
+ ```bash
121
+ python test_mcp_client.py
122
+ ```
123
+
124
+ ### 5. General tips
125
+ - Always activate your virtual environment before running scripts.
126
+ - If you add new dependencies, use `uv pip install <package>` to keep your environment up to date.
127
+ - If you encounter issues, check your Python version and ensure it matches the project's requirements.
128
+
@@ -1,12 +1,12 @@
1
1
  rootly_mcp_server/__init__.py,sha256=n-YajkwxYg0eoVvtYfYTY6slaktHTYvQbasg15HwGKo,628
2
2
  rootly_mcp_server/__main__.py,sha256=yVbn4s2WGDy7ASbcLULMi2ro4Qt6WgVZbHVD0p0ibrs,4311
3
- rootly_mcp_server/client.py,sha256=vvaY_UaYLobeHbJwgsmFNX-2ABpYoKxMTie8DRBo_xk,3865
4
- rootly_mcp_server/server.py,sha256=iYOSmS7UfxF28w09X3PjDI6he9VLE1h3U9U3qsJ8K5M,16273
3
+ rootly_mcp_server/client.py,sha256=bUi_2WJl_w4kAAyuD18Mu0O_EPJ1VrvqxQAkPWQQKc0,4521
4
+ rootly_mcp_server/server.py,sha256=sq8kksmDY_4DpSGVVQoTi6yNBZFA5TWmtqLMUhbeM7Y,17656
5
5
  rootly_mcp_server/test_client.py,sha256=xFQ4cfUpD6qs-aLidy56B3nnV38EFvUe_eBHOqZOC9o,2191
6
6
  rootly_mcp_server/data/__init__.py,sha256=fO8a0bQnRVEoRMHKvhFzj10bhoaw7VsI51czc2MsUm4,143
7
7
  rootly_mcp_server/data/swagger.json,sha256=8Ag4COTnS3WSC6vBaa2Q7hq3RxIQ8fGrmwsnNSnPheA,2046619
8
- rootly_mcp_server-0.0.5.dist-info/METADATA,sha256=r9dctRmxTaFySuSdiyoELmxJT019AHoLbaO9dXbF_2g,4074
9
- rootly_mcp_server-0.0.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- rootly_mcp_server-0.0.5.dist-info/entry_points.txt,sha256=NE33b8VgigVPGBkboyo6pvN1Vz35HZtLybxMO4Q03PI,70
11
- rootly_mcp_server-0.0.5.dist-info/licenses/LICENSE,sha256=c9w9ZZGl14r54tsP40oaq5adTVX_HMNHozPIH2ymzmw,11341
12
- rootly_mcp_server-0.0.5.dist-info/RECORD,,
8
+ rootly_mcp_server-1.0.0.dist-info/METADATA,sha256=6M05t9v0v2WT_eTHqCI4cqCBEOC9_WjIV8SweLPbZYE,4883
9
+ rootly_mcp_server-1.0.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ rootly_mcp_server-1.0.0.dist-info/entry_points.txt,sha256=NE33b8VgigVPGBkboyo6pvN1Vz35HZtLybxMO4Q03PI,70
11
+ rootly_mcp_server-1.0.0.dist-info/licenses/LICENSE,sha256=c9w9ZZGl14r54tsP40oaq5adTVX_HMNHozPIH2ymzmw,11341
12
+ rootly_mcp_server-1.0.0.dist-info/RECORD,,