universal-mcp 0.1.8rc3__py3-none-any.whl → 0.1.9__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.
- universal_mcp/applications/__init__.py +7 -2
- universal_mcp/applications/ahrefs/README.md +76 -0
- universal_mcp/applications/ahrefs/__init__.py +0 -0
- universal_mcp/applications/ahrefs/app.py +2291 -0
- universal_mcp/applications/application.py +191 -87
- universal_mcp/applications/cal_com_v2/README.md +175 -0
- universal_mcp/applications/cal_com_v2/__init__.py +0 -0
- universal_mcp/applications/cal_com_v2/app.py +5390 -0
- universal_mcp/applications/calendly/app.py +0 -12
- universal_mcp/applications/clickup/README.md +160 -0
- universal_mcp/applications/clickup/__init__.py +0 -0
- universal_mcp/applications/clickup/app.py +5009 -0
- universal_mcp/applications/coda/app.py +0 -33
- universal_mcp/applications/e2b/app.py +2 -28
- universal_mcp/applications/falai/README.md +42 -0
- universal_mcp/applications/falai/__init__.py +0 -0
- universal_mcp/applications/falai/app.py +332 -0
- universal_mcp/applications/figma/README.md +74 -0
- universal_mcp/applications/figma/__init__.py +0 -0
- universal_mcp/applications/figma/app.py +1261 -0
- universal_mcp/applications/firecrawl/app.py +2 -32
- universal_mcp/applications/gong/README.md +88 -0
- universal_mcp/applications/gong/__init__.py +0 -0
- universal_mcp/applications/gong/app.py +2297 -0
- universal_mcp/applications/google_calendar/app.py +0 -11
- universal_mcp/applications/google_docs/app.py +0 -18
- universal_mcp/applications/google_drive/app.py +0 -17
- universal_mcp/applications/google_mail/app.py +0 -16
- universal_mcp/applications/google_sheet/app.py +0 -18
- universal_mcp/applications/hashnode/app.py +81 -0
- universal_mcp/applications/hashnode/prompt.md +23 -0
- universal_mcp/applications/heygen/README.md +69 -0
- universal_mcp/applications/heygen/__init__.py +0 -0
- universal_mcp/applications/heygen/app.py +956 -0
- universal_mcp/applications/mailchimp/README.md +306 -0
- universal_mcp/applications/mailchimp/__init__.py +0 -0
- universal_mcp/applications/mailchimp/app.py +10937 -0
- universal_mcp/applications/markitdown/app.py +2 -2
- universal_mcp/applications/perplexity/app.py +0 -35
- universal_mcp/applications/replicate/README.md +65 -0
- universal_mcp/applications/replicate/__init__.py +0 -0
- universal_mcp/applications/replicate/app.py +980 -0
- universal_mcp/applications/resend/app.py +0 -18
- universal_mcp/applications/retell_ai/README.md +46 -0
- universal_mcp/applications/retell_ai/__init__.py +0 -0
- universal_mcp/applications/retell_ai/app.py +333 -0
- universal_mcp/applications/rocketlane/README.md +42 -0
- universal_mcp/applications/rocketlane/__init__.py +0 -0
- universal_mcp/applications/rocketlane/app.py +194 -0
- universal_mcp/applications/serpapi/app.py +2 -28
- universal_mcp/applications/spotify/README.md +116 -0
- universal_mcp/applications/spotify/__init__.py +0 -0
- universal_mcp/applications/spotify/app.py +2526 -0
- universal_mcp/applications/supabase/README.md +112 -0
- universal_mcp/applications/supabase/__init__.py +0 -0
- universal_mcp/applications/supabase/app.py +2970 -0
- universal_mcp/applications/tavily/app.py +0 -20
- universal_mcp/applications/wrike/app.py +0 -12
- universal_mcp/applications/youtube/app.py +0 -18
- universal_mcp/integrations/agentr.py +27 -4
- universal_mcp/integrations/integration.py +14 -6
- universal_mcp/servers/server.py +53 -6
- universal_mcp/stores/store.py +6 -0
- universal_mcp/tools/tools.py +2 -2
- universal_mcp/utils/docstring_parser.py +192 -94
- universal_mcp/utils/installation.py +199 -8
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.9.dist-info}/METADATA +6 -1
- universal_mcp-0.1.9.dist-info/RECORD +116 -0
- universal_mcp-0.1.8rc3.dist-info/RECORD +0 -75
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.9.dist-info}/WHEEL +0 -0
- {universal_mcp-0.1.8rc3.dist-info → universal_mcp-0.1.9.dist-info}/entry_points.txt +0 -0
@@ -5,24 +5,6 @@ from universal_mcp.integrations import Integration
|
|
5
5
|
class ResendApp(APIApplication):
|
6
6
|
def __init__(self, integration: Integration) -> None:
|
7
7
|
super().__init__(name="resend", integration=integration)
|
8
|
-
self.api_key = None
|
9
|
-
|
10
|
-
def _get_headers(self):
|
11
|
-
if not self.api_key:
|
12
|
-
credentials = self.integration.get_credentials()
|
13
|
-
if not credentials:
|
14
|
-
raise ValueError("No credentials found")
|
15
|
-
api_key = (
|
16
|
-
credentials.get("api_key")
|
17
|
-
or credentials.get("API_KEY")
|
18
|
-
or credentials.get("apiKey")
|
19
|
-
)
|
20
|
-
if not api_key:
|
21
|
-
raise ValueError("No API key found")
|
22
|
-
self.api_key = api_key
|
23
|
-
return {
|
24
|
-
"Authorization": f"Bearer {self.api_key}",
|
25
|
-
}
|
26
8
|
|
27
9
|
def send_email(self, to: str, subject: str, content: str) -> str:
|
28
10
|
"""
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
# Retell Ai MCP Server
|
3
|
+
|
4
|
+
An MCP Server for the Retell Ai API.
|
5
|
+
|
6
|
+
## Supported Integrations
|
7
|
+
|
8
|
+
- AgentR
|
9
|
+
- API Key (Coming Soon)
|
10
|
+
- OAuth (Coming Soon)
|
11
|
+
|
12
|
+
## Tools
|
13
|
+
|
14
|
+
This is automatically generated from OpenAPI schema for the Retell Ai API.
|
15
|
+
|
16
|
+
## Supported Integrations
|
17
|
+
|
18
|
+
This tool can be integrated with any service that supports HTTP requests.
|
19
|
+
|
20
|
+
## Tool List
|
21
|
+
|
22
|
+
| Tool | Description |
|
23
|
+
|------|-------------|
|
24
|
+
| get_v2_get_call_by_call_id | Retrieve detailed information about a specific call using its call ID. |
|
25
|
+
| post_v2_create_phone_call | Initiates a phone call using a JSON payload with specified parameters. |
|
26
|
+
| post_v2_create_web_call | Creates a web call via a POST request to the v2 endpoint with specified agent ID and optional metadata or dynamic variables. |
|
27
|
+
| get_get_voice_by_voice_id | Fetches voice details based on the provided voice ID. |
|
28
|
+
| post_v2_list_calls | Sends a POST request to list call records with optional filtering, sorting, pagination, and limits. |
|
29
|
+
| post_create_phone_number | Creates a phone number with the specified area code and optional parameters. |
|
30
|
+
| get_get_phone_number_by_phone_number | Retrieves phone number details by making a GET request to the API endpoint using the provided phone number. |
|
31
|
+
| get_list_phone_numbers | Retrieves a list of phone numbers from the remote API. |
|
32
|
+
| patch_update_phone_number_by_phone_number | Updates the information of a phone number by its number, allowing optional modification of inbound and outbound agent IDs and nickname. |
|
33
|
+
| delete_delete_phone_number_by_phone_number | Deletes a phone number resource by its phone number identifier via an HTTP DELETE request. |
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
## Usage
|
38
|
+
|
39
|
+
- Login to AgentR
|
40
|
+
- Follow the quickstart guide to setup MCP Server for your client
|
41
|
+
- Visit Apps Store and enable the Retell Ai app
|
42
|
+
- Restart the MCP Server
|
43
|
+
|
44
|
+
### Local Development
|
45
|
+
|
46
|
+
- Follow the README to test with the local MCP Server
|
File without changes
|
@@ -0,0 +1,333 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from universal_mcp.applications import APIApplication
|
4
|
+
from universal_mcp.integrations import Integration
|
5
|
+
|
6
|
+
|
7
|
+
class RetellAiApp(APIApplication):
|
8
|
+
def __init__(self, integration: Integration = None, **kwargs) -> None:
|
9
|
+
super().__init__(name="retell-ai", integration=integration, **kwargs)
|
10
|
+
self.base_url = "https://api.retellai.com"
|
11
|
+
|
12
|
+
def get_v2_get_call_by_call_id(self, call_id) -> dict[str, Any]:
|
13
|
+
"""
|
14
|
+
Retrieve detailed information about a specific call using its call ID.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
call_id: The unique identifier of the call to retrieve. Must not be None.
|
18
|
+
|
19
|
+
Returns:
|
20
|
+
A dictionary containing the details of the requested call as returned by the API.
|
21
|
+
|
22
|
+
Raises:
|
23
|
+
ValueError: If the 'call_id' parameter is None.
|
24
|
+
HTTPError: If the HTTP request to the API fails or returns an unsuccessful status code.
|
25
|
+
|
26
|
+
Tags:
|
27
|
+
get, call, api, important
|
28
|
+
"""
|
29
|
+
if call_id is None:
|
30
|
+
raise ValueError("Missing required parameter 'call_id'")
|
31
|
+
url = f"{self.base_url}/v2/get-call/{call_id}"
|
32
|
+
query_params = {}
|
33
|
+
response = self._get(url, params=query_params)
|
34
|
+
response.raise_for_status()
|
35
|
+
return response.json()
|
36
|
+
|
37
|
+
def post_v2_create_phone_call(
|
38
|
+
self,
|
39
|
+
from_number,
|
40
|
+
to_number,
|
41
|
+
override_agent_id=None,
|
42
|
+
metadata=None,
|
43
|
+
retell_llm_dynamic_variables=None,
|
44
|
+
) -> dict[str, Any]:
|
45
|
+
"""
|
46
|
+
Initiates a phone call using a JSON payload with specified parameters.
|
47
|
+
|
48
|
+
Args:
|
49
|
+
from_number: The source number for the call.
|
50
|
+
to_number: The destination number for the call.
|
51
|
+
override_agent_id: Optional ID for overriding the default agent.
|
52
|
+
metadata: Optional metadata to be included with the call request.
|
53
|
+
retell_llm_dynamic_variables: Optional dynamic variables for LLM (Large Language Model) processing.
|
54
|
+
|
55
|
+
Returns:
|
56
|
+
A dictionary containing the response data for the created phone call.
|
57
|
+
|
58
|
+
Raises:
|
59
|
+
ValueError: Raised if either 'from_number' or 'to_number' is missing.
|
60
|
+
|
61
|
+
Tags:
|
62
|
+
initiate, create-call, async_job, management, important
|
63
|
+
"""
|
64
|
+
if from_number is None:
|
65
|
+
raise ValueError("Missing required parameter 'from_number'")
|
66
|
+
if to_number is None:
|
67
|
+
raise ValueError("Missing required parameter 'to_number'")
|
68
|
+
request_body = {
|
69
|
+
"from_number": from_number,
|
70
|
+
"to_number": to_number,
|
71
|
+
"override_agent_id": override_agent_id,
|
72
|
+
"metadata": metadata,
|
73
|
+
"retell_llm_dynamic_variables": retell_llm_dynamic_variables,
|
74
|
+
}
|
75
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
76
|
+
url = f"{self.base_url}/v2/create-phone-call"
|
77
|
+
query_params = {}
|
78
|
+
response = self._post(url, data=request_body, params=query_params)
|
79
|
+
response.raise_for_status()
|
80
|
+
return response.json()
|
81
|
+
|
82
|
+
def post_v2_create_web_call(
|
83
|
+
self, agent_id, metadata=None, retell_llm_dynamic_variables=None
|
84
|
+
) -> dict[str, Any]:
|
85
|
+
"""
|
86
|
+
Creates a web call via a POST request to the v2 endpoint with specified agent ID and optional metadata or dynamic variables.
|
87
|
+
|
88
|
+
Args:
|
89
|
+
agent_id: Required identifier of the agent initiating the web call.
|
90
|
+
metadata: Optional metadata to include in the web call request.
|
91
|
+
retell_llm_dynamic_variables: Optional dynamic variables for LLN model customization.
|
92
|
+
|
93
|
+
Returns:
|
94
|
+
A dictionary containing the response details from the web call creation request.
|
95
|
+
|
96
|
+
Raises:
|
97
|
+
ValueError: Raised when the required 'agent_id' parameter is missing.
|
98
|
+
|
99
|
+
Tags:
|
100
|
+
create, web-calls, api-call, important
|
101
|
+
"""
|
102
|
+
if agent_id is None:
|
103
|
+
raise ValueError("Missing required parameter 'agent_id'")
|
104
|
+
request_body = {
|
105
|
+
"agent_id": agent_id,
|
106
|
+
"metadata": metadata,
|
107
|
+
"retell_llm_dynamic_variables": retell_llm_dynamic_variables,
|
108
|
+
}
|
109
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
110
|
+
url = f"{self.base_url}/v2/create-web-call"
|
111
|
+
query_params = {}
|
112
|
+
response = self._post(url, data=request_body, params=query_params)
|
113
|
+
response.raise_for_status()
|
114
|
+
return response.json()
|
115
|
+
|
116
|
+
def get_get_voice_by_voice_id(self, voice_id) -> dict[str, Any]:
|
117
|
+
"""
|
118
|
+
Fetches voice details based on the provided voice ID.
|
119
|
+
|
120
|
+
Args:
|
121
|
+
voice_id: The unique identifier of the voice to retrieve.
|
122
|
+
|
123
|
+
Returns:
|
124
|
+
A dictionary containing voice details.
|
125
|
+
|
126
|
+
Raises:
|
127
|
+
ValueError: Raised when the 'voice_id' parameter is missing or None.
|
128
|
+
|
129
|
+
Tags:
|
130
|
+
retrieve, voice, important, data-fetched
|
131
|
+
"""
|
132
|
+
if voice_id is None:
|
133
|
+
raise ValueError("Missing required parameter 'voice_id'")
|
134
|
+
url = f"{self.base_url}/get-voice/{voice_id}"
|
135
|
+
query_params = {}
|
136
|
+
response = self._get(url, params=query_params)
|
137
|
+
response.raise_for_status()
|
138
|
+
return response.json()
|
139
|
+
|
140
|
+
def post_v2_list_calls(
|
141
|
+
self, filter_criteria=None, sort_order=None, limit=None, pagination_key=None
|
142
|
+
) -> list[Any]:
|
143
|
+
"""
|
144
|
+
Sends a POST request to list call records with optional filtering, sorting, pagination, and limits.
|
145
|
+
|
146
|
+
Args:
|
147
|
+
filter_criteria: Optional dictionary specifying filter conditions for returned call records.
|
148
|
+
sort_order: Optional sorting instructions (e.g., by date or status) for the call records.
|
149
|
+
limit: Optional integer specifying the maximum number of call records to return.
|
150
|
+
pagination_key: Optional key indicating where to continue fetching records for paginated results.
|
151
|
+
|
152
|
+
Returns:
|
153
|
+
A list of call record objects returned from the API.
|
154
|
+
|
155
|
+
Raises:
|
156
|
+
HTTPError: If the HTTP request to the remote service fails or returns an error status code.
|
157
|
+
|
158
|
+
Tags:
|
159
|
+
list, calls, api, batch, management, important
|
160
|
+
"""
|
161
|
+
request_body = {
|
162
|
+
"filter_criteria": filter_criteria,
|
163
|
+
"sort_order": sort_order,
|
164
|
+
"limit": limit,
|
165
|
+
"pagination_key": pagination_key,
|
166
|
+
}
|
167
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
168
|
+
url = f"{self.base_url}/v2/list-calls"
|
169
|
+
query_params = {}
|
170
|
+
response = self._post(url, data=request_body, params=query_params)
|
171
|
+
response.raise_for_status()
|
172
|
+
return response.json()
|
173
|
+
|
174
|
+
def post_create_phone_number(
|
175
|
+
self, area_code, inbound_agent_id=None, outbound_agent_id=None, nickname=None
|
176
|
+
) -> dict[str, Any]:
|
177
|
+
"""
|
178
|
+
Creates a phone number with the specified area code and optional parameters.
|
179
|
+
|
180
|
+
Args:
|
181
|
+
area_code: The area code for the phone number (required).
|
182
|
+
inbound_agent_id: The ID of the agent to handle inbound calls (optional).
|
183
|
+
outbound_agent_id: The ID of the agent to handle outbound calls (optional).
|
184
|
+
nickname: A user-friendly name for the phone number (optional).
|
185
|
+
|
186
|
+
Returns:
|
187
|
+
A dictionary containing the created phone number details and any associated metadata.
|
188
|
+
|
189
|
+
Raises:
|
190
|
+
ValueError: When the required parameter 'area_code' is None or not provided.
|
191
|
+
HTTPError: When the API request fails with an error status code.
|
192
|
+
|
193
|
+
Tags:
|
194
|
+
create, phone, post, communication, important
|
195
|
+
"""
|
196
|
+
if area_code is None:
|
197
|
+
raise ValueError("Missing required parameter 'area_code'")
|
198
|
+
request_body = {
|
199
|
+
"inbound_agent_id": inbound_agent_id,
|
200
|
+
"outbound_agent_id": outbound_agent_id,
|
201
|
+
"area_code": area_code,
|
202
|
+
"nickname": nickname,
|
203
|
+
}
|
204
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
205
|
+
url = f"{self.base_url}/create-phone-number"
|
206
|
+
query_params = {}
|
207
|
+
response = self._post(url, data=request_body, params=query_params)
|
208
|
+
response.raise_for_status()
|
209
|
+
return response.json()
|
210
|
+
|
211
|
+
def get_get_phone_number_by_phone_number(self, phone_number) -> dict[str, Any]:
|
212
|
+
"""
|
213
|
+
Retrieves phone number details by making a GET request to the API endpoint using the provided phone number.
|
214
|
+
|
215
|
+
Args:
|
216
|
+
phone_number: str. The phone number to look up. Must not be None.
|
217
|
+
|
218
|
+
Returns:
|
219
|
+
dict[str, Any]: A dictionary containing the details associated with the given phone number as returned by the API.
|
220
|
+
|
221
|
+
Raises:
|
222
|
+
ValueError: If the 'phone_number' parameter is None.
|
223
|
+
requests.HTTPError: If the HTTP request fails or an error response is returned from the API.
|
224
|
+
|
225
|
+
Tags:
|
226
|
+
get, phone-number, api, lookup, important
|
227
|
+
"""
|
228
|
+
if phone_number is None:
|
229
|
+
raise ValueError("Missing required parameter 'phone_number'")
|
230
|
+
url = f"{self.base_url}/get-phone-number/{phone_number}"
|
231
|
+
query_params = {}
|
232
|
+
response = self._get(url, params=query_params)
|
233
|
+
response.raise_for_status()
|
234
|
+
return response.json()
|
235
|
+
|
236
|
+
def get_list_phone_numbers(
|
237
|
+
self,
|
238
|
+
) -> list[Any]:
|
239
|
+
"""
|
240
|
+
Retrieves a list of phone numbers from the remote API.
|
241
|
+
|
242
|
+
Args:
|
243
|
+
None: This function takes no arguments
|
244
|
+
|
245
|
+
Returns:
|
246
|
+
A list containing the phone numbers returned by the API.
|
247
|
+
|
248
|
+
Raises:
|
249
|
+
requests.HTTPError: If the HTTP request to the API fails or returns an unsuccessful status code.
|
250
|
+
|
251
|
+
Tags:
|
252
|
+
get, list, phone-numbers, api, synchronous, important
|
253
|
+
"""
|
254
|
+
url = f"{self.base_url}/list-phone-numbers"
|
255
|
+
query_params = {}
|
256
|
+
response = self._get(url, params=query_params)
|
257
|
+
response.raise_for_status()
|
258
|
+
return response.json()
|
259
|
+
|
260
|
+
def patch_update_phone_number_by_phone_number(
|
261
|
+
self, phone_number, inbound_agent_id=None, outbound_agent_id=None, nickname=None
|
262
|
+
) -> dict[str, Any]:
|
263
|
+
"""
|
264
|
+
Updates the information of a phone number by its number, allowing optional modification of inbound and outbound agent IDs and nickname.
|
265
|
+
|
266
|
+
Args:
|
267
|
+
phone_number: str. The phone number to update. This parameter is required.
|
268
|
+
inbound_agent_id: Optional[str]. The ID of the inbound agent to associate with the phone number. If None, this field will not be updated.
|
269
|
+
outbound_agent_id: Optional[str]. The ID of the outbound agent to associate with the phone number. If None, this field will not be updated.
|
270
|
+
nickname: Optional[str]. The nickname to assign to the phone number. If None, this field will not be updated.
|
271
|
+
|
272
|
+
Returns:
|
273
|
+
dict[str, Any]: A dictionary containing the updated phone number information as returned by the API.
|
274
|
+
|
275
|
+
Raises:
|
276
|
+
ValueError: If the required parameter 'phone_number' is not provided.
|
277
|
+
requests.HTTPError: If the HTTP PATCH request fails or the response has an error status.
|
278
|
+
|
279
|
+
Tags:
|
280
|
+
update, phone-number, api, patch, management
|
281
|
+
"""
|
282
|
+
if phone_number is None:
|
283
|
+
raise ValueError("Missing required parameter 'phone_number'")
|
284
|
+
request_body = {
|
285
|
+
"inbound_agent_id": inbound_agent_id,
|
286
|
+
"outbound_agent_id": outbound_agent_id,
|
287
|
+
"nickname": nickname,
|
288
|
+
}
|
289
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
290
|
+
url = f"{self.base_url}/update-phone-number/{phone_number}"
|
291
|
+
query_params = {}
|
292
|
+
response = self._patch(url, data=request_body, params=query_params)
|
293
|
+
response.raise_for_status()
|
294
|
+
return response.json()
|
295
|
+
|
296
|
+
def delete_delete_phone_number_by_phone_number(self, phone_number) -> Any:
|
297
|
+
"""
|
298
|
+
Deletes a phone number resource by its phone number identifier via an HTTP DELETE request.
|
299
|
+
|
300
|
+
Args:
|
301
|
+
phone_number: The phone number (str or compatible type) identifying the resource to be deleted.
|
302
|
+
|
303
|
+
Returns:
|
304
|
+
The server's JSON response as a Python object upon successful deletion.
|
305
|
+
|
306
|
+
Raises:
|
307
|
+
ValueError: If 'phone_number' is None.
|
308
|
+
requests.HTTPError: If the HTTP DELETE request results in an error status code.
|
309
|
+
|
310
|
+
Tags:
|
311
|
+
delete, phone-number, api, management, important
|
312
|
+
"""
|
313
|
+
if phone_number is None:
|
314
|
+
raise ValueError("Missing required parameter 'phone_number'")
|
315
|
+
url = f"{self.base_url}/delete-phone-number/{phone_number}"
|
316
|
+
query_params = {}
|
317
|
+
response = self._delete(url, params=query_params)
|
318
|
+
response.raise_for_status()
|
319
|
+
return response.json()
|
320
|
+
|
321
|
+
def list_tools(self):
|
322
|
+
return [
|
323
|
+
self.get_v2_get_call_by_call_id,
|
324
|
+
self.post_v2_create_phone_call,
|
325
|
+
self.post_v2_create_web_call,
|
326
|
+
self.get_get_voice_by_voice_id,
|
327
|
+
self.post_v2_list_calls,
|
328
|
+
self.post_create_phone_number,
|
329
|
+
self.get_get_phone_number_by_phone_number,
|
330
|
+
self.get_list_phone_numbers,
|
331
|
+
self.patch_update_phone_number_by_phone_number,
|
332
|
+
self.delete_delete_phone_number_by_phone_number,
|
333
|
+
]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
|
2
|
+
# Rocketlane MCP Server
|
3
|
+
|
4
|
+
An MCP Server for the Rocketlane API.
|
5
|
+
|
6
|
+
## Supported Integrations
|
7
|
+
|
8
|
+
- AgentR
|
9
|
+
- API Key (Coming Soon)
|
10
|
+
- OAuth (Coming Soon)
|
11
|
+
|
12
|
+
## Tools
|
13
|
+
|
14
|
+
This is automatically generated from OpenAPI schema for the Rocketlane API.
|
15
|
+
|
16
|
+
## Supported Integrations
|
17
|
+
|
18
|
+
This tool can be integrated with any service that supports HTTP requests.
|
19
|
+
|
20
|
+
## Tool List
|
21
|
+
|
22
|
+
| Tool | Description |
|
23
|
+
|------|-------------|
|
24
|
+
| get_subscription | Retrieves subscription details from the server. |
|
25
|
+
| get_home | Retrieves the JSON response from the '/home' endpoint of the configured API. |
|
26
|
+
| get_all_projects | Retrieves a list of all projects from the remote service. |
|
27
|
+
| get_projects_by_projectid | Retrieves project details for a given project ID from the server. |
|
28
|
+
| get_projects_by_projectid_tasks | Retrieves a list of tasks associated with a given project ID. |
|
29
|
+
| create_task | Creates a new task within the specified project, assigning optional details such as description, name, assignee, start date, and due date. |
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
- Login to AgentR
|
36
|
+
- Follow the quickstart guide to setup MCP Server for your client
|
37
|
+
- Visit Apps Store and enable the Rocketlane app
|
38
|
+
- Restart the MCP Server
|
39
|
+
|
40
|
+
### Local Development
|
41
|
+
|
42
|
+
- Follow the README to test with the local MCP Server
|
File without changes
|
@@ -0,0 +1,194 @@
|
|
1
|
+
from typing import Any
|
2
|
+
|
3
|
+
from universal_mcp.applications import APIApplication
|
4
|
+
from universal_mcp.integrations import Integration
|
5
|
+
|
6
|
+
|
7
|
+
class RocketlaneApp(APIApplication):
|
8
|
+
def __init__(self, integration: Integration = None, **kwargs) -> None:
|
9
|
+
super().__init__(name="rocketlane", integration=integration, **kwargs)
|
10
|
+
subdomain = self.integration.get_credentials().get("subdomain")
|
11
|
+
self.base_url = f"https://{subdomain}.api.rocketlane.com/api/v1"
|
12
|
+
|
13
|
+
def _get_headers(self) -> dict[str, Any]:
|
14
|
+
api_key = self.integration.get_credentials().get("api_key")
|
15
|
+
return {
|
16
|
+
"api-key": f"{api_key}",
|
17
|
+
"Content-Type": "application/json",
|
18
|
+
"Accept": "application/json",
|
19
|
+
}
|
20
|
+
|
21
|
+
def get_subscription(
|
22
|
+
self,
|
23
|
+
) -> Any:
|
24
|
+
"""
|
25
|
+
Retrieves subscription details from the server.
|
26
|
+
|
27
|
+
Args:
|
28
|
+
None: This function does not take any parameters.
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
A JSON response containing subscription details.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
requests.HTTPError: Raised if an HTTP error occurs during the request
|
35
|
+
|
36
|
+
Tags:
|
37
|
+
fetch, subscription, management, important
|
38
|
+
"""
|
39
|
+
url = f"{self.base_url}/subscription"
|
40
|
+
query_params = {}
|
41
|
+
response = self._get(url, params=query_params)
|
42
|
+
response.raise_for_status()
|
43
|
+
return response.json()
|
44
|
+
|
45
|
+
def get_home(
|
46
|
+
self,
|
47
|
+
) -> Any:
|
48
|
+
"""
|
49
|
+
Retrieves the JSON response from the '/home' endpoint of the configured API.
|
50
|
+
|
51
|
+
Returns:
|
52
|
+
Any: Parsed JSON data returned by the '/home' endpoint.
|
53
|
+
|
54
|
+
Raises:
|
55
|
+
requests.HTTPError: If the HTTP request to the '/home' endpoint returns an unsuccessful status code.
|
56
|
+
|
57
|
+
Tags:
|
58
|
+
get, home, api, request, important
|
59
|
+
"""
|
60
|
+
url = f"{self.base_url}/home"
|
61
|
+
query_params = {}
|
62
|
+
response = self._get(url, params=query_params)
|
63
|
+
response.raise_for_status()
|
64
|
+
return response.json()
|
65
|
+
|
66
|
+
def get_all_projects(
|
67
|
+
self,
|
68
|
+
) -> dict[str, Any]:
|
69
|
+
"""
|
70
|
+
Retrieves a list of all projects from the remote service.
|
71
|
+
|
72
|
+
Args:
|
73
|
+
None: This function takes no arguments
|
74
|
+
|
75
|
+
Returns:
|
76
|
+
A dictionary containing the JSON response data representing all available projects.
|
77
|
+
|
78
|
+
Raises:
|
79
|
+
HTTPError: If the HTTP request to retrieve the projects fails or returns an unsuccessful status code.
|
80
|
+
|
81
|
+
Tags:
|
82
|
+
list, projects, api, important
|
83
|
+
"""
|
84
|
+
url = f"{self.base_url}/projects"
|
85
|
+
query_params = {}
|
86
|
+
response = self._get(url, params=query_params)
|
87
|
+
response.raise_for_status()
|
88
|
+
return response.json()
|
89
|
+
|
90
|
+
def get_projects_by_projectid(self, projectId) -> Any:
|
91
|
+
"""
|
92
|
+
Retrieves project details for a given project ID from the server.
|
93
|
+
|
94
|
+
Args:
|
95
|
+
projectId: The unique identifier of the project to retrieve.
|
96
|
+
|
97
|
+
Returns:
|
98
|
+
A JSON-deserialized object containing the project's details as returned by the server.
|
99
|
+
|
100
|
+
Raises:
|
101
|
+
ValueError: Raised if 'projectId' is None.
|
102
|
+
requests.HTTPError: Raised if the HTTP request to retrieve the project fails (e.g., 4xx or 5xx response).
|
103
|
+
|
104
|
+
Tags:
|
105
|
+
get, project, fetch, management, important
|
106
|
+
"""
|
107
|
+
if projectId is None:
|
108
|
+
raise ValueError("Missing required parameter 'projectId'")
|
109
|
+
url = f"{self.base_url}/projects/{projectId}"
|
110
|
+
query_params = {}
|
111
|
+
response = self._get(url, params=query_params)
|
112
|
+
response.raise_for_status()
|
113
|
+
return response.json()
|
114
|
+
|
115
|
+
def get_projects_by_projectid_tasks(self, projectId) -> Any:
|
116
|
+
"""
|
117
|
+
Retrieves a list of tasks associated with a given project ID.
|
118
|
+
|
119
|
+
Args:
|
120
|
+
projectId: str. The unique identifier of the project whose tasks are to be retrieved.
|
121
|
+
|
122
|
+
Returns:
|
123
|
+
dict. A JSON object containing the list of tasks for the specified project.
|
124
|
+
|
125
|
+
Raises:
|
126
|
+
ValueError: If the projectId parameter is None.
|
127
|
+
requests.HTTPError: If the HTTP request to retrieve tasks fails (i.e., non-2xx response).
|
128
|
+
|
129
|
+
Tags:
|
130
|
+
get, list, project-tasks, management, important
|
131
|
+
"""
|
132
|
+
if projectId is None:
|
133
|
+
raise ValueError("Missing required parameter 'projectId'")
|
134
|
+
url = f"{self.base_url}/projects/{projectId}/tasks"
|
135
|
+
query_params = {}
|
136
|
+
response = self._get(url, params=query_params)
|
137
|
+
response.raise_for_status()
|
138
|
+
return response.json()
|
139
|
+
|
140
|
+
def create_task(
|
141
|
+
self,
|
142
|
+
projectId,
|
143
|
+
taskDescription=None,
|
144
|
+
taskName=None,
|
145
|
+
assignee=None,
|
146
|
+
startDate=None,
|
147
|
+
dueDate=None,
|
148
|
+
) -> dict[str, Any]:
|
149
|
+
"""
|
150
|
+
Creates a new task within the specified project, assigning optional details such as description, name, assignee, start date, and due date.
|
151
|
+
|
152
|
+
Args:
|
153
|
+
projectId: str. The unique identifier of the project in which to create the task. Required.
|
154
|
+
taskDescription: Optional[str]. A description of the task to be created.
|
155
|
+
taskName: Optional[str]. The name of the new task.
|
156
|
+
assignee: Optional[str]. The user to whom the task is assigned.
|
157
|
+
startDate: Optional[str]. The starting date for the task, formatted as an ISO 8601 string.
|
158
|
+
dueDate: Optional[str]. The due date for task completion, formatted as an ISO 8601 string.
|
159
|
+
|
160
|
+
Returns:
|
161
|
+
dict[str, Any]: A dictionary containing the details of the created task as returned by the API.
|
162
|
+
|
163
|
+
Raises:
|
164
|
+
ValueError: If 'projectId' is not provided.
|
165
|
+
requests.HTTPError: If the API request fails and returns a non-success HTTP status code.
|
166
|
+
|
167
|
+
Tags:
|
168
|
+
create, task, management, project, api, important
|
169
|
+
"""
|
170
|
+
if projectId is None:
|
171
|
+
raise ValueError("Missing required parameter 'projectId'")
|
172
|
+
request_body = {
|
173
|
+
"taskDescription": taskDescription,
|
174
|
+
"taskName": taskName,
|
175
|
+
"assignee": assignee,
|
176
|
+
"startDate": startDate,
|
177
|
+
"dueDate": dueDate,
|
178
|
+
}
|
179
|
+
request_body = {k: v for k, v in request_body.items() if v is not None}
|
180
|
+
url = f"{self.base_url}/projects/{projectId}/tasks"
|
181
|
+
query_params = {}
|
182
|
+
response = self._post(url, data=request_body, params=query_params)
|
183
|
+
response.raise_for_status()
|
184
|
+
return response.json()
|
185
|
+
|
186
|
+
def list_tools(self):
|
187
|
+
return [
|
188
|
+
self.get_subscription,
|
189
|
+
self.get_home,
|
190
|
+
self.get_all_projects,
|
191
|
+
self.get_projects_by_projectid,
|
192
|
+
self.get_projects_by_projectid_tasks,
|
193
|
+
self.create_task,
|
194
|
+
]
|