universal-mcp-applications 0.1.1__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/ahrefs/README.md +51 -0
- universal_mcp/applications/ahrefs/__init__.py +1 -0
- universal_mcp/applications/ahrefs/app.py +2291 -0
- universal_mcp/applications/airtable/README.md +22 -0
- universal_mcp/applications/airtable/__init__.py +1 -0
- universal_mcp/applications/airtable/app.py +479 -0
- universal_mcp/applications/apollo/README.md +44 -0
- universal_mcp/applications/apollo/__init__.py +1 -0
- universal_mcp/applications/apollo/app.py +1847 -0
- universal_mcp/applications/asana/README.md +199 -0
- universal_mcp/applications/asana/__init__.py +1 -0
- universal_mcp/applications/asana/app.py +9509 -0
- universal_mcp/applications/aws-s3/README.md +0 -0
- universal_mcp/applications/aws-s3/__init__.py +1 -0
- universal_mcp/applications/aws-s3/app.py +552 -0
- universal_mcp/applications/bill/README.md +0 -0
- universal_mcp/applications/bill/__init__.py +1 -0
- universal_mcp/applications/bill/app.py +8705 -0
- universal_mcp/applications/box/README.md +307 -0
- universal_mcp/applications/box/__init__.py +1 -0
- universal_mcp/applications/box/app.py +15987 -0
- universal_mcp/applications/braze/README.md +106 -0
- universal_mcp/applications/braze/__init__.py +1 -0
- universal_mcp/applications/braze/app.py +4754 -0
- universal_mcp/applications/cal-com-v2/README.md +150 -0
- universal_mcp/applications/cal-com-v2/__init__.py +1 -0
- universal_mcp/applications/cal-com-v2/app.py +5541 -0
- universal_mcp/applications/calendly/README.md +53 -0
- universal_mcp/applications/calendly/__init__.py +1 -0
- universal_mcp/applications/calendly/app.py +1436 -0
- universal_mcp/applications/canva/README.md +43 -0
- universal_mcp/applications/canva/__init__.py +1 -0
- universal_mcp/applications/canva/app.py +941 -0
- universal_mcp/applications/clickup/README.md +135 -0
- universal_mcp/applications/clickup/__init__.py +1 -0
- universal_mcp/applications/clickup/app.py +5009 -0
- universal_mcp/applications/coda/README.md +108 -0
- universal_mcp/applications/coda/__init__.py +1 -0
- universal_mcp/applications/coda/app.py +3671 -0
- universal_mcp/applications/confluence/README.md +198 -0
- universal_mcp/applications/confluence/__init__.py +1 -0
- universal_mcp/applications/confluence/app.py +6273 -0
- universal_mcp/applications/contentful/README.md +17 -0
- universal_mcp/applications/contentful/__init__.py +1 -0
- universal_mcp/applications/contentful/app.py +364 -0
- universal_mcp/applications/crustdata/README.md +25 -0
- universal_mcp/applications/crustdata/__init__.py +1 -0
- universal_mcp/applications/crustdata/app.py +586 -0
- universal_mcp/applications/dialpad/README.md +202 -0
- universal_mcp/applications/dialpad/__init__.py +1 -0
- universal_mcp/applications/dialpad/app.py +5949 -0
- universal_mcp/applications/digitalocean/README.md +463 -0
- universal_mcp/applications/digitalocean/__init__.py +1 -0
- universal_mcp/applications/digitalocean/app.py +20835 -0
- universal_mcp/applications/domain-checker/README.md +13 -0
- universal_mcp/applications/domain-checker/__init__.py +1 -0
- universal_mcp/applications/domain-checker/app.py +265 -0
- universal_mcp/applications/e2b/README.md +12 -0
- universal_mcp/applications/e2b/__init__.py +1 -0
- universal_mcp/applications/e2b/app.py +187 -0
- universal_mcp/applications/elevenlabs/README.md +88 -0
- universal_mcp/applications/elevenlabs/__init__.py +1 -0
- universal_mcp/applications/elevenlabs/app.py +3235 -0
- universal_mcp/applications/exa/README.md +15 -0
- universal_mcp/applications/exa/__init__.py +1 -0
- universal_mcp/applications/exa/app.py +221 -0
- universal_mcp/applications/falai/README.md +17 -0
- universal_mcp/applications/falai/__init__.py +1 -0
- universal_mcp/applications/falai/app.py +331 -0
- universal_mcp/applications/figma/README.md +49 -0
- universal_mcp/applications/figma/__init__.py +1 -0
- universal_mcp/applications/figma/app.py +1090 -0
- universal_mcp/applications/firecrawl/README.md +20 -0
- universal_mcp/applications/firecrawl/__init__.py +1 -0
- universal_mcp/applications/firecrawl/app.py +514 -0
- universal_mcp/applications/fireflies/README.md +25 -0
- universal_mcp/applications/fireflies/__init__.py +1 -0
- universal_mcp/applications/fireflies/app.py +506 -0
- universal_mcp/applications/fpl/README.md +23 -0
- universal_mcp/applications/fpl/__init__.py +1 -0
- universal_mcp/applications/fpl/app.py +1327 -0
- universal_mcp/applications/fpl/utils/api.py +142 -0
- universal_mcp/applications/fpl/utils/fixtures.py +629 -0
- universal_mcp/applications/fpl/utils/helper.py +982 -0
- universal_mcp/applications/fpl/utils/league_utils.py +546 -0
- universal_mcp/applications/fpl/utils/position_utils.py +68 -0
- universal_mcp/applications/ghost-content/README.md +25 -0
- universal_mcp/applications/ghost-content/__init__.py +1 -0
- universal_mcp/applications/ghost-content/app.py +654 -0
- universal_mcp/applications/github/README.md +1049 -0
- universal_mcp/applications/github/__init__.py +1 -0
- universal_mcp/applications/github/app.py +50600 -0
- universal_mcp/applications/gong/README.md +63 -0
- universal_mcp/applications/gong/__init__.py +1 -0
- universal_mcp/applications/gong/app.py +2297 -0
- universal_mcp/applications/google-ads/README.md +0 -0
- universal_mcp/applications/google-ads/__init__.py +1 -0
- universal_mcp/applications/google-ads/app.py +23 -0
- universal_mcp/applications/google-calendar/README.md +21 -0
- universal_mcp/applications/google-calendar/__init__.py +1 -0
- universal_mcp/applications/google-calendar/app.py +574 -0
- universal_mcp/applications/google-docs/README.md +25 -0
- universal_mcp/applications/google-docs/__init__.py +1 -0
- universal_mcp/applications/google-docs/app.py +760 -0
- universal_mcp/applications/google-drive/README.md +68 -0
- universal_mcp/applications/google-drive/__init__.py +1 -0
- universal_mcp/applications/google-drive/app.py +4936 -0
- universal_mcp/applications/google-gemini/README.md +25 -0
- universal_mcp/applications/google-gemini/__init__.py +1 -0
- universal_mcp/applications/google-gemini/app.py +663 -0
- universal_mcp/applications/google-mail/README.md +31 -0
- universal_mcp/applications/google-mail/__init__.py +1 -0
- universal_mcp/applications/google-mail/app.py +1354 -0
- universal_mcp/applications/google-searchconsole/README.md +21 -0
- universal_mcp/applications/google-searchconsole/__init__.py +1 -0
- universal_mcp/applications/google-searchconsole/app.py +320 -0
- universal_mcp/applications/google-sheet/README.md +36 -0
- universal_mcp/applications/google-sheet/__init__.py +1 -0
- universal_mcp/applications/google-sheet/app.py +1941 -0
- universal_mcp/applications/hashnode/README.md +20 -0
- universal_mcp/applications/hashnode/__init__.py +1 -0
- universal_mcp/applications/hashnode/app.py +455 -0
- universal_mcp/applications/heygen/README.md +44 -0
- universal_mcp/applications/heygen/__init__.py +1 -0
- universal_mcp/applications/heygen/app.py +961 -0
- universal_mcp/applications/http-tools/README.md +16 -0
- universal_mcp/applications/http-tools/__init__.py +1 -0
- universal_mcp/applications/http-tools/app.py +153 -0
- universal_mcp/applications/hubspot/README.md +239 -0
- universal_mcp/applications/hubspot/__init__.py +1 -0
- universal_mcp/applications/hubspot/app.py +416 -0
- universal_mcp/applications/jira/README.md +600 -0
- universal_mcp/applications/jira/__init__.py +1 -0
- universal_mcp/applications/jira/app.py +28804 -0
- universal_mcp/applications/klaviyo/README.md +313 -0
- universal_mcp/applications/klaviyo/__init__.py +1 -0
- universal_mcp/applications/klaviyo/app.py +11236 -0
- universal_mcp/applications/linkedin/README.md +15 -0
- universal_mcp/applications/linkedin/__init__.py +1 -0
- universal_mcp/applications/linkedin/app.py +243 -0
- universal_mcp/applications/mailchimp/README.md +281 -0
- universal_mcp/applications/mailchimp/__init__.py +1 -0
- universal_mcp/applications/mailchimp/app.py +10937 -0
- universal_mcp/applications/markitdown/README.md +12 -0
- universal_mcp/applications/markitdown/__init__.py +1 -0
- universal_mcp/applications/markitdown/app.py +63 -0
- universal_mcp/applications/miro/README.md +151 -0
- universal_mcp/applications/miro/__init__.py +1 -0
- universal_mcp/applications/miro/app.py +5429 -0
- universal_mcp/applications/ms-teams/README.md +42 -0
- universal_mcp/applications/ms-teams/__init__.py +1 -0
- universal_mcp/applications/ms-teams/app.py +1823 -0
- universal_mcp/applications/neon/README.md +74 -0
- universal_mcp/applications/neon/__init__.py +1 -0
- universal_mcp/applications/neon/app.py +2018 -0
- universal_mcp/applications/notion/README.md +30 -0
- universal_mcp/applications/notion/__init__.py +1 -0
- universal_mcp/applications/notion/app.py +527 -0
- universal_mcp/applications/openai/README.md +22 -0
- universal_mcp/applications/openai/__init__.py +1 -0
- universal_mcp/applications/openai/app.py +759 -0
- universal_mcp/applications/outlook/README.md +20 -0
- universal_mcp/applications/outlook/__init__.py +1 -0
- universal_mcp/applications/outlook/app.py +444 -0
- universal_mcp/applications/perplexity/README.md +12 -0
- universal_mcp/applications/perplexity/__init__.py +1 -0
- universal_mcp/applications/perplexity/app.py +65 -0
- universal_mcp/applications/pipedrive/README.md +284 -0
- universal_mcp/applications/pipedrive/__init__.py +1 -0
- universal_mcp/applications/pipedrive/app.py +12924 -0
- universal_mcp/applications/posthog/README.md +132 -0
- universal_mcp/applications/posthog/__init__.py +1 -0
- universal_mcp/applications/posthog/app.py +7125 -0
- universal_mcp/applications/reddit/README.md +135 -0
- universal_mcp/applications/reddit/__init__.py +1 -0
- universal_mcp/applications/reddit/app.py +4652 -0
- universal_mcp/applications/replicate/README.md +18 -0
- universal_mcp/applications/replicate/__init__.py +1 -0
- universal_mcp/applications/replicate/app.py +495 -0
- universal_mcp/applications/resend/README.md +40 -0
- universal_mcp/applications/resend/__init__.py +1 -0
- universal_mcp/applications/resend/app.py +881 -0
- universal_mcp/applications/retell/README.md +21 -0
- universal_mcp/applications/retell/__init__.py +1 -0
- universal_mcp/applications/retell/app.py +333 -0
- universal_mcp/applications/rocketlane/README.md +70 -0
- universal_mcp/applications/rocketlane/__init__.py +1 -0
- universal_mcp/applications/rocketlane/app.py +4346 -0
- universal_mcp/applications/semanticscholar/README.md +25 -0
- universal_mcp/applications/semanticscholar/__init__.py +1 -0
- universal_mcp/applications/semanticscholar/app.py +482 -0
- universal_mcp/applications/semrush/README.md +44 -0
- universal_mcp/applications/semrush/__init__.py +1 -0
- universal_mcp/applications/semrush/app.py +2081 -0
- universal_mcp/applications/sendgrid/README.md +362 -0
- universal_mcp/applications/sendgrid/__init__.py +1 -0
- universal_mcp/applications/sendgrid/app.py +9752 -0
- universal_mcp/applications/sentry/README.md +186 -0
- universal_mcp/applications/sentry/__init__.py +1 -0
- universal_mcp/applications/sentry/app.py +7471 -0
- universal_mcp/applications/serpapi/README.md +14 -0
- universal_mcp/applications/serpapi/__init__.py +1 -0
- universal_mcp/applications/serpapi/app.py +293 -0
- universal_mcp/applications/sharepoint/README.md +0 -0
- universal_mcp/applications/sharepoint/__init__.py +1 -0
- universal_mcp/applications/sharepoint/app.py +215 -0
- universal_mcp/applications/shopify/README.md +321 -0
- universal_mcp/applications/shopify/__init__.py +1 -0
- universal_mcp/applications/shopify/app.py +15392 -0
- universal_mcp/applications/shortcut/README.md +128 -0
- universal_mcp/applications/shortcut/__init__.py +1 -0
- universal_mcp/applications/shortcut/app.py +4478 -0
- universal_mcp/applications/slack/README.md +0 -0
- universal_mcp/applications/slack/__init__.py +1 -0
- universal_mcp/applications/slack/app.py +570 -0
- universal_mcp/applications/spotify/README.md +91 -0
- universal_mcp/applications/spotify/__init__.py +1 -0
- universal_mcp/applications/spotify/app.py +2526 -0
- universal_mcp/applications/supabase/README.md +87 -0
- universal_mcp/applications/supabase/__init__.py +1 -0
- universal_mcp/applications/supabase/app.py +2970 -0
- universal_mcp/applications/tavily/README.md +12 -0
- universal_mcp/applications/tavily/__init__.py +1 -0
- universal_mcp/applications/tavily/app.py +51 -0
- universal_mcp/applications/trello/README.md +266 -0
- universal_mcp/applications/trello/__init__.py +1 -0
- universal_mcp/applications/trello/app.py +10875 -0
- universal_mcp/applications/twillo/README.md +0 -0
- universal_mcp/applications/twillo/__init__.py +1 -0
- universal_mcp/applications/twillo/app.py +269 -0
- universal_mcp/applications/twitter/README.md +100 -0
- universal_mcp/applications/twitter/__init__.py +1 -0
- universal_mcp/applications/twitter/api_segments/__init__.py +0 -0
- universal_mcp/applications/twitter/api_segments/api_segment_base.py +51 -0
- universal_mcp/applications/twitter/api_segments/compliance_api.py +122 -0
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +255 -0
- universal_mcp/applications/twitter/api_segments/dm_events_api.py +140 -0
- universal_mcp/applications/twitter/api_segments/likes_api.py +159 -0
- universal_mcp/applications/twitter/api_segments/lists_api.py +395 -0
- universal_mcp/applications/twitter/api_segments/openapi_json_api.py +34 -0
- universal_mcp/applications/twitter/api_segments/spaces_api.py +309 -0
- universal_mcp/applications/twitter/api_segments/trends_api.py +40 -0
- universal_mcp/applications/twitter/api_segments/tweets_api.py +1403 -0
- universal_mcp/applications/twitter/api_segments/usage_api.py +40 -0
- universal_mcp/applications/twitter/api_segments/users_api.py +1498 -0
- universal_mcp/applications/twitter/app.py +46 -0
- universal_mcp/applications/unipile/README.md +28 -0
- universal_mcp/applications/unipile/__init__.py +1 -0
- universal_mcp/applications/unipile/app.py +829 -0
- universal_mcp/applications/whatsapp/README.md +23 -0
- universal_mcp/applications/whatsapp/__init__.py +1 -0
- universal_mcp/applications/whatsapp/app.py +595 -0
- universal_mcp/applications/whatsapp-business/README.md +34 -0
- universal_mcp/applications/whatsapp-business/__init__.py +1 -0
- universal_mcp/applications/whatsapp-business/app.py +1065 -0
- universal_mcp/applications/wrike/README.md +46 -0
- universal_mcp/applications/wrike/__init__.py +1 -0
- universal_mcp/applications/wrike/app.py +1583 -0
- universal_mcp/applications/youtube/README.md +57 -0
- universal_mcp/applications/youtube/__init__.py +1 -0
- universal_mcp/applications/youtube/app.py +1696 -0
- universal_mcp/applications/zenquotes/README.md +12 -0
- universal_mcp/applications/zenquotes/__init__.py +1 -0
- universal_mcp/applications/zenquotes/app.py +31 -0
- universal_mcp_applications-0.1.1.dist-info/METADATA +172 -0
- universal_mcp_applications-0.1.1.dist-info/RECORD +268 -0
- universal_mcp_applications-0.1.1.dist-info/WHEEL +4 -0
- universal_mcp_applications-0.1.1.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# OutlookApp MCP Server
|
|
2
|
+
|
|
3
|
+
An MCP Server for the OutlookApp API.
|
|
4
|
+
|
|
5
|
+
## 🛠️ Tool List
|
|
6
|
+
|
|
7
|
+
This is automatically generated from OpenAPI schema for the OutlookApp API.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
| Tool | Description |
|
|
11
|
+
|------|-------------|
|
|
12
|
+
| `users_message_reply` | Replies to a specific message for a user using the POST method, accepting JSON content in the request body and returning status codes indicating success or error. |
|
|
13
|
+
| `user_send_mail` | Sends an email on behalf of the specified user, accepting the email details as JSON in the request body and returning a 204 No Content response on success. |
|
|
14
|
+
| `user_get_mail_folder` | Retrieves a specific mail folder for a specified user using optional query parameters to include hidden folders or select/expand properties. |
|
|
15
|
+
| `user_list_message` | Retrieves a list of messages for a user, allowing optional filtering and sorting of results based on parameters such as includeHiddenMessages, search, filter, top, skip, orderby, select, and expand. |
|
|
16
|
+
| `user_get_message` | Retrieves a specific message for a user, optionally including hidden messages, selecting specific fields, or expanding related data. |
|
|
17
|
+
| `user_delete_message` | Deletes a specific message for a given user using the DELETE method and optional If-Match header for conditional requests. |
|
|
18
|
+
| `user_message_list_attachment` | Retrieves attachments associated with a specified user's message, supporting filtering, pagination, and field selection via query parameters. |
|
|
19
|
+
| `get_user_id` | Retrieves the current user. |
|
|
20
|
+
| `get_from_url` | Makes a GET request to a full @odata.nextLink or @odata.deltaLink URL. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .app import OutlookApp
|
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
from urllib.parse import parse_qs, urlparse
|
|
3
|
+
|
|
4
|
+
from universal_mcp.applications.application import APIApplication
|
|
5
|
+
from universal_mcp.integrations import Integration
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class OutlookApp(APIApplication):
|
|
9
|
+
def __init__(self, integration: Integration = None, **kwargs) -> None:
|
|
10
|
+
super().__init__(name="outlook", integration=integration, **kwargs)
|
|
11
|
+
self.base_url = "https://graph.microsoft.com/v1.0"
|
|
12
|
+
|
|
13
|
+
def users_message_reply(
|
|
14
|
+
self,
|
|
15
|
+
message_id: str,
|
|
16
|
+
user_id: str | None = None,
|
|
17
|
+
comment: str | None = None,
|
|
18
|
+
message: dict[str, Any] | None = None,
|
|
19
|
+
) -> Any:
|
|
20
|
+
"""
|
|
21
|
+
Replies to a specific message for a user using the POST method, accepting JSON content in the request body and returning status codes indicating success or error.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
25
|
+
message_id (string): message-id
|
|
26
|
+
comment (string): A comment to include in the reply. Example: 'Thank you for your email. Here is my reply.'.
|
|
27
|
+
message (object): A message object to specify additional properties for the reply, such as attachments. Example: {'subject': 'RE: Project Update', 'body': {'contentType': 'Text', 'content': 'Thank you for the update. Looking forward to the next steps.'}, 'toRecipients': [{'emailAddress': {'address': 'alice@contoso.com'}}], 'attachments': [{'@odata.type': '#microsoft.graph.fileAttachment', 'name': 'agenda.pdf', 'contentType': 'application/pdf', 'contentBytes': 'SGVsbG8gV29ybGQh'}]}.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Any: Success
|
|
31
|
+
|
|
32
|
+
Raises:
|
|
33
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
34
|
+
|
|
35
|
+
Tags:
|
|
36
|
+
users.message, important
|
|
37
|
+
"""
|
|
38
|
+
# If user_id is not provided, get it automatically
|
|
39
|
+
if user_id is None:
|
|
40
|
+
user_info = self.get_user_id()
|
|
41
|
+
user_id = user_info.get("userPrincipalName")
|
|
42
|
+
if not user_id:
|
|
43
|
+
raise ValueError(
|
|
44
|
+
"Could not retrieve user ID from get_user_id response."
|
|
45
|
+
)
|
|
46
|
+
if message_id is None:
|
|
47
|
+
raise ValueError("Missing required parameter 'message-id'.")
|
|
48
|
+
request_body_data = None
|
|
49
|
+
request_body_data = {
|
|
50
|
+
"comment": comment,
|
|
51
|
+
"message": message,
|
|
52
|
+
}
|
|
53
|
+
request_body_data = {
|
|
54
|
+
k: v for k, v in request_body_data.items() if v is not None
|
|
55
|
+
}
|
|
56
|
+
url = f"{self.base_url}/users/{user_id}/messages/{message_id}/reply"
|
|
57
|
+
query_params = {}
|
|
58
|
+
response = self._post(
|
|
59
|
+
url,
|
|
60
|
+
data=request_body_data,
|
|
61
|
+
params=query_params,
|
|
62
|
+
content_type="application/json",
|
|
63
|
+
)
|
|
64
|
+
return self._handle_response(response)
|
|
65
|
+
|
|
66
|
+
def user_send_mail(
|
|
67
|
+
self,
|
|
68
|
+
message: dict[str, Any],
|
|
69
|
+
user_id: str | None = None,
|
|
70
|
+
saveToSentItems: bool | None = None,
|
|
71
|
+
) -> Any:
|
|
72
|
+
"""
|
|
73
|
+
Sends an email on behalf of the specified user, accepting the email details as JSON in the request body and returning a 204 No Content response on success.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
77
|
+
message (object): message Example: {'subject': 'Meet for lunch?', 'body': {'contentType': 'Text', 'content': 'The new cafeteria is open.'}, 'toRecipients': [{'emailAddress': {'address': 'frannis@contoso.com'}}], 'ccRecipients': [{'emailAddress': {'address': 'danas@contoso.com'}}], 'bccRecipients': [{'emailAddress': {'address': 'bccuser@contoso.com'}}], 'attachments': [{'@odata.type': '#microsoft.graph.fileAttachment', 'name': 'attachment.txt', 'contentType': 'text/plain', 'contentBytes': 'SGVsbG8gV29ybGQh'}]}.
|
|
78
|
+
saveToSentItems (boolean): saveToSentItems Example: 'False'.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Any: Success
|
|
82
|
+
|
|
83
|
+
Raises:
|
|
84
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
85
|
+
|
|
86
|
+
Tags:
|
|
87
|
+
users.user.Actions, important
|
|
88
|
+
"""
|
|
89
|
+
# If user_id is not provided, get it automatically
|
|
90
|
+
if user_id is None:
|
|
91
|
+
user_info = self.get_user_id()
|
|
92
|
+
user_id = user_info.get("userPrincipalName")
|
|
93
|
+
if not user_id:
|
|
94
|
+
raise ValueError(
|
|
95
|
+
"Could not retrieve user ID from get_user_id response."
|
|
96
|
+
)
|
|
97
|
+
request_body_data = None
|
|
98
|
+
request_body_data = {
|
|
99
|
+
"message": message,
|
|
100
|
+
"saveToSentItems": saveToSentItems,
|
|
101
|
+
}
|
|
102
|
+
request_body_data = {
|
|
103
|
+
k: v for k, v in request_body_data.items() if v is not None
|
|
104
|
+
}
|
|
105
|
+
url = f"{self.base_url}/users/{user_id}/sendMail"
|
|
106
|
+
query_params = {}
|
|
107
|
+
response = self._post(
|
|
108
|
+
url,
|
|
109
|
+
data=request_body_data,
|
|
110
|
+
params=query_params,
|
|
111
|
+
content_type="application/json",
|
|
112
|
+
)
|
|
113
|
+
return self._handle_response(response)
|
|
114
|
+
|
|
115
|
+
def user_get_mail_folder(
|
|
116
|
+
self,
|
|
117
|
+
mailFolder_id: str,
|
|
118
|
+
user_id: str | None = None,
|
|
119
|
+
includeHiddenFolders: str | None = None,
|
|
120
|
+
select: list[str] | None = None,
|
|
121
|
+
expand: list[str] | None = None,
|
|
122
|
+
) -> Any:
|
|
123
|
+
"""
|
|
124
|
+
Retrieves a specific mail folder for a specified user using optional query parameters to include hidden folders or select/expand properties.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
128
|
+
mailFolder_id (string): mailFolder-id
|
|
129
|
+
includeHiddenFolders (string): Include Hidden Folders
|
|
130
|
+
select (array): Select properties to be returned
|
|
131
|
+
expand (array): Expand related entities
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
Any: Retrieved navigation property
|
|
135
|
+
|
|
136
|
+
Raises:
|
|
137
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
138
|
+
|
|
139
|
+
Tags:
|
|
140
|
+
users.mailFolder, important
|
|
141
|
+
"""
|
|
142
|
+
# If user_id is not provided, get it automatically
|
|
143
|
+
if user_id is None:
|
|
144
|
+
user_info = self.get_user_id()
|
|
145
|
+
user_id = user_info.get("userPrincipalName")
|
|
146
|
+
if not user_id:
|
|
147
|
+
raise ValueError(
|
|
148
|
+
"Could not retrieve user ID from get_user_id response."
|
|
149
|
+
)
|
|
150
|
+
if mailFolder_id is None:
|
|
151
|
+
raise ValueError("Missing required parameter 'mailFolder-id'.")
|
|
152
|
+
url = f"{self.base_url}/users/{user_id}/mailFolders/{mailFolder_id}"
|
|
153
|
+
query_params = {
|
|
154
|
+
k: v
|
|
155
|
+
for k, v in [
|
|
156
|
+
("includeHiddenFolders", includeHiddenFolders),
|
|
157
|
+
("$select", select),
|
|
158
|
+
("$expand", expand),
|
|
159
|
+
]
|
|
160
|
+
if v is not None
|
|
161
|
+
}
|
|
162
|
+
response = self._get(url, params=query_params)
|
|
163
|
+
return self._handle_response(response)
|
|
164
|
+
|
|
165
|
+
def user_list_message(
|
|
166
|
+
self,
|
|
167
|
+
user_id: str | None = None,
|
|
168
|
+
select: list[str] = ["bodyPreview"],
|
|
169
|
+
includeHiddenMessages: bool | None = None,
|
|
170
|
+
top: int | None = None,
|
|
171
|
+
skip: int | None = None,
|
|
172
|
+
search: str | None = None,
|
|
173
|
+
filter: str | None = None,
|
|
174
|
+
count: bool | None = None,
|
|
175
|
+
orderby: list[str] | None = None,
|
|
176
|
+
expand: list[str] | None = None,
|
|
177
|
+
) -> dict[str, Any]:
|
|
178
|
+
"""
|
|
179
|
+
Retrieves a list of messages for a user, allowing optional filtering and sorting of results based on parameters such as includeHiddenMessages, search, filter, top, skip, orderby, select, and expand.
|
|
180
|
+
|
|
181
|
+
Args:
|
|
182
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
183
|
+
select (list): Select properties to be returned. Defaults to ['bodyPreview'].
|
|
184
|
+
Example: [
|
|
185
|
+
'id', 'categories', 'receivedDateTime', 'sentDateTime', 'hasAttachments', 'internetMessageId',
|
|
186
|
+
'subject', 'body', 'bodyPreview', 'importance', 'parentFolderId', 'conversationId',
|
|
187
|
+
'conversationIndex', 'isDeliveryReceiptRequested', 'isReadReceiptRequested', 'isRead', 'isDraft',
|
|
188
|
+
'webLink', 'inferenceClassification', 'sender', 'from', 'toRecipients', 'ccRecipients',
|
|
189
|
+
'bccRecipients', 'replyTo', 'flag', 'attachments', 'extensions', 'mentions', 'uniqueBody'
|
|
190
|
+
]
|
|
191
|
+
includeHiddenMessages (boolean): Include Hidden Messages
|
|
192
|
+
top (integer): Specify the number of items to be included in the result Example: '50'.
|
|
193
|
+
skip (integer): Specify the number of items to skip in the result Example: '10'.
|
|
194
|
+
search (string): Search items by search phrases
|
|
195
|
+
filter (string): Filter items by property values
|
|
196
|
+
count (boolean): Include count of items
|
|
197
|
+
orderby (array): Order items by property values
|
|
198
|
+
expand (array): Expand related entities
|
|
199
|
+
|
|
200
|
+
Returns:
|
|
201
|
+
dict[str, Any]: Retrieved collection
|
|
202
|
+
|
|
203
|
+
Raises:
|
|
204
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
205
|
+
|
|
206
|
+
Tags:
|
|
207
|
+
users.message, important
|
|
208
|
+
"""
|
|
209
|
+
# If user_id is not provided, get it automatically
|
|
210
|
+
if user_id is None:
|
|
211
|
+
user_info = self.get_user_id()
|
|
212
|
+
user_id = user_info.get("userPrincipalName")
|
|
213
|
+
if not user_id:
|
|
214
|
+
raise ValueError(
|
|
215
|
+
"Could not retrieve user ID from get_user_id response."
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
url = f"{self.base_url}/users/{user_id}/messages"
|
|
219
|
+
|
|
220
|
+
# Handle list parameters by joining with commas
|
|
221
|
+
select_str = ",".join(select) if select else None
|
|
222
|
+
orderby_str = ",".join(orderby) if orderby else None
|
|
223
|
+
expand_str = ",".join(expand) if expand else None
|
|
224
|
+
|
|
225
|
+
query_params = {
|
|
226
|
+
k: v
|
|
227
|
+
for k, v in [
|
|
228
|
+
("includeHiddenMessages", includeHiddenMessages),
|
|
229
|
+
("$top", top),
|
|
230
|
+
("$skip", skip),
|
|
231
|
+
("$search", search),
|
|
232
|
+
("$filter", filter),
|
|
233
|
+
("$count", count),
|
|
234
|
+
("$orderby", orderby_str),
|
|
235
|
+
("$select", select_str),
|
|
236
|
+
("$expand", expand_str),
|
|
237
|
+
]
|
|
238
|
+
if v is not None
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
response = self._get(url, params=query_params)
|
|
242
|
+
return self._handle_response(response)
|
|
243
|
+
|
|
244
|
+
def user_get_message(
|
|
245
|
+
self,
|
|
246
|
+
message_id: str,
|
|
247
|
+
user_id: str | None = None,
|
|
248
|
+
includeHiddenMessages: str | None = None,
|
|
249
|
+
select: list[str] | None = None,
|
|
250
|
+
expand: list[str] | None = None,
|
|
251
|
+
) -> Any:
|
|
252
|
+
"""
|
|
253
|
+
Retrieves a specific message for a user, optionally including hidden messages, selecting specific fields, or expanding related data.
|
|
254
|
+
|
|
255
|
+
Args:
|
|
256
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
257
|
+
message_id (string): message-id
|
|
258
|
+
includeHiddenMessages (string): Include Hidden Messages
|
|
259
|
+
select (array): Select properties to be returned
|
|
260
|
+
expand (array): Expand related entities
|
|
261
|
+
|
|
262
|
+
Returns:
|
|
263
|
+
Any: Retrieved navigation property
|
|
264
|
+
|
|
265
|
+
Raises:
|
|
266
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
267
|
+
|
|
268
|
+
Tags:
|
|
269
|
+
users.message, important
|
|
270
|
+
"""
|
|
271
|
+
# If user_id is not provided, get it automatically
|
|
272
|
+
if user_id is None:
|
|
273
|
+
user_info = self.get_user_id()
|
|
274
|
+
user_id = user_info.get("userPrincipalName")
|
|
275
|
+
if not user_id:
|
|
276
|
+
raise ValueError(
|
|
277
|
+
"Could not retrieve user ID from get_user_id response."
|
|
278
|
+
)
|
|
279
|
+
if message_id is None:
|
|
280
|
+
raise ValueError("Missing required parameter 'message-id'.")
|
|
281
|
+
url = f"{self.base_url}/users/{user_id}/messages/{message_id}"
|
|
282
|
+
query_params = {
|
|
283
|
+
k: v
|
|
284
|
+
for k, v in [
|
|
285
|
+
("includeHiddenMessages", includeHiddenMessages),
|
|
286
|
+
("$select", select),
|
|
287
|
+
("$expand", expand),
|
|
288
|
+
]
|
|
289
|
+
if v is not None
|
|
290
|
+
}
|
|
291
|
+
response = self._get(url, params=query_params)
|
|
292
|
+
return self._handle_response(response)
|
|
293
|
+
|
|
294
|
+
def user_delete_message(
|
|
295
|
+
self, message_id: str, user_id: str | None = None
|
|
296
|
+
) -> Any:
|
|
297
|
+
"""
|
|
298
|
+
Deletes a specific message for a given user using the DELETE method and optional If-Match header for conditional requests.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
302
|
+
message_id (string): message-id
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
Any: Success
|
|
306
|
+
|
|
307
|
+
Raises:
|
|
308
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
309
|
+
|
|
310
|
+
Tags:
|
|
311
|
+
users.message, important
|
|
312
|
+
"""
|
|
313
|
+
# If user_id is not provided, get it automatically
|
|
314
|
+
if user_id is None:
|
|
315
|
+
user_info = self.get_user_id()
|
|
316
|
+
user_id = user_info.get("userPrincipalName")
|
|
317
|
+
if not user_id:
|
|
318
|
+
raise ValueError(
|
|
319
|
+
"Could not retrieve user ID from get_user_id response."
|
|
320
|
+
)
|
|
321
|
+
if message_id is None:
|
|
322
|
+
raise ValueError("Missing required parameter 'message-id'.")
|
|
323
|
+
url = f"{self.base_url}/users/{user_id}/messages/{message_id}"
|
|
324
|
+
query_params = {}
|
|
325
|
+
response = self._delete(url, params=query_params)
|
|
326
|
+
return self._handle_response(response)
|
|
327
|
+
|
|
328
|
+
def user_message_list_attachment(
|
|
329
|
+
self,
|
|
330
|
+
message_id: str,
|
|
331
|
+
user_id: str | None = None,
|
|
332
|
+
top: int | None = None,
|
|
333
|
+
skip: int | None = None,
|
|
334
|
+
search: str | None = None,
|
|
335
|
+
filter: str | None = None,
|
|
336
|
+
count: bool | None = None,
|
|
337
|
+
orderby: list[str] | None = None,
|
|
338
|
+
select: list[str] | None = None,
|
|
339
|
+
expand: list[str] | None = None,
|
|
340
|
+
) -> dict[str, Any]:
|
|
341
|
+
"""
|
|
342
|
+
Retrieves attachments associated with a specified user's message, supporting filtering, pagination, and field selection via query parameters.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
user_id (string, optional): user-id. If not provided, will automatically get the current user's ID.
|
|
346
|
+
message_id (string): message-id
|
|
347
|
+
top (integer): Show only the first n items Example: '50'.
|
|
348
|
+
skip (integer): Skip the first n items
|
|
349
|
+
search (string): Search items by search phrases
|
|
350
|
+
filter (string): Filter items by property values
|
|
351
|
+
count (boolean): Include count of items
|
|
352
|
+
orderby (array): Order items by property values
|
|
353
|
+
select (array): Select properties to be returned
|
|
354
|
+
expand (array): Expand related entities
|
|
355
|
+
|
|
356
|
+
Returns:
|
|
357
|
+
dict[str, Any]: Retrieved collection
|
|
358
|
+
|
|
359
|
+
Raises:
|
|
360
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
361
|
+
|
|
362
|
+
Tags:
|
|
363
|
+
users.message, important
|
|
364
|
+
"""
|
|
365
|
+
# If user_id is not provided, get it automatically
|
|
366
|
+
if user_id is None:
|
|
367
|
+
user_info = self.get_user_id()
|
|
368
|
+
user_id = user_info.get("userPrincipalName")
|
|
369
|
+
if not user_id:
|
|
370
|
+
raise ValueError(
|
|
371
|
+
"Could not retrieve user ID from get_user_id response."
|
|
372
|
+
)
|
|
373
|
+
if message_id is None:
|
|
374
|
+
raise ValueError("Missing required parameter 'message-id'.")
|
|
375
|
+
url = f"{self.base_url}/users/{user_id}/messages/{message_id}/attachments"
|
|
376
|
+
query_params = {
|
|
377
|
+
k: v
|
|
378
|
+
for k, v in [
|
|
379
|
+
("$top", top),
|
|
380
|
+
("$skip", skip),
|
|
381
|
+
("$search", search),
|
|
382
|
+
("$filter", filter),
|
|
383
|
+
("$count", count),
|
|
384
|
+
("$orderby", orderby),
|
|
385
|
+
("$select", select),
|
|
386
|
+
("$expand", expand),
|
|
387
|
+
]
|
|
388
|
+
if v is not None
|
|
389
|
+
}
|
|
390
|
+
response = self._get(url, params=query_params)
|
|
391
|
+
return self._handle_response(response)
|
|
392
|
+
|
|
393
|
+
def get_user_id(
|
|
394
|
+
self,
|
|
395
|
+
) -> dict[str, Any]:
|
|
396
|
+
"""
|
|
397
|
+
Retrieves the current user.
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
Returns:
|
|
401
|
+
dict[str, Any]: Current user information
|
|
402
|
+
|
|
403
|
+
Raises:
|
|
404
|
+
HTTPStatusError: Raised when the API request fails with detailed error information including status code and response body.
|
|
405
|
+
|
|
406
|
+
Tags:
|
|
407
|
+
me, important
|
|
408
|
+
"""
|
|
409
|
+
url = f"{self.base_url}/me"
|
|
410
|
+
query_params = {
|
|
411
|
+
"$select": "userPrincipalName",
|
|
412
|
+
}
|
|
413
|
+
response = self._get(url, params=query_params)
|
|
414
|
+
return self._handle_response(response)
|
|
415
|
+
|
|
416
|
+
def get_from_url(self, url: str) -> dict[str, Any]:
|
|
417
|
+
"""
|
|
418
|
+
Makes a GET request to a full @odata.nextLink or @odata.deltaLink URL.
|
|
419
|
+
"""
|
|
420
|
+
if not url:
|
|
421
|
+
raise ValueError("Missing required parameter 'url'.")
|
|
422
|
+
if not url.startswith(self.base_url):
|
|
423
|
+
raise ValueError(
|
|
424
|
+
f"The provided URL '{url}' does not start with the expected base URL '{self.base_url}'."
|
|
425
|
+
)
|
|
426
|
+
relative_part = url[len(self.base_url) :]
|
|
427
|
+
parsed_relative = urlparse(relative_part)
|
|
428
|
+
path_only = parsed_relative.path
|
|
429
|
+
params = {k: v[0] for k, v in parse_qs(parsed_relative.query).items()}
|
|
430
|
+
response = self._get(path_only, params=params)
|
|
431
|
+
return self._handle_response(response)
|
|
432
|
+
|
|
433
|
+
def list_tools(self):
|
|
434
|
+
return [
|
|
435
|
+
self.users_message_reply,
|
|
436
|
+
self.user_send_mail,
|
|
437
|
+
self.user_get_mail_folder,
|
|
438
|
+
self.user_list_message,
|
|
439
|
+
self.user_get_message,
|
|
440
|
+
self.user_delete_message,
|
|
441
|
+
self.user_message_list_attachment,
|
|
442
|
+
self.get_user_id,
|
|
443
|
+
self.get_from_url,
|
|
444
|
+
]
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Perplexity MCP Server
|
|
2
|
+
|
|
3
|
+
An MCP Server for the Perplexity API.
|
|
4
|
+
|
|
5
|
+
## 🛠️ Tool List
|
|
6
|
+
|
|
7
|
+
This is automatically generated from OpenAPI schema for the Perplexity API.
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
| Tool | Description |
|
|
11
|
+
|------|-------------|
|
|
12
|
+
| `chat` | Initiates a chat completion request to generate AI responses using various models with customizable parameters. |
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from .app import PerplexityApp
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from typing import Any, Literal
|
|
2
|
+
|
|
3
|
+
from universal_mcp.applications.application import APIApplication
|
|
4
|
+
from universal_mcp.integrations import Integration
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PerplexityApp(APIApplication):
|
|
8
|
+
def __init__(self, integration: Integration | None = None) -> None:
|
|
9
|
+
super().__init__(name="perplexity", integration=integration)
|
|
10
|
+
self.base_url = "https://api.perplexity.ai"
|
|
11
|
+
|
|
12
|
+
def chat(
|
|
13
|
+
self,
|
|
14
|
+
query: str,
|
|
15
|
+
model: Literal[
|
|
16
|
+
"r1-1776",
|
|
17
|
+
"sonar",
|
|
18
|
+
"sonar-pro",
|
|
19
|
+
"sonar-reasoning",
|
|
20
|
+
"sonar-reasoning-pro",
|
|
21
|
+
"sonar-deep-research",
|
|
22
|
+
] = "sonar",
|
|
23
|
+
temperature: float = 1,
|
|
24
|
+
system_prompt: str = "Be precise and concise.",
|
|
25
|
+
) -> dict[str, Any] | str:
|
|
26
|
+
"""
|
|
27
|
+
Initiates a chat completion request to generate AI responses using various models with customizable parameters.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
query: The input text/prompt to send to the chat model
|
|
31
|
+
model: The model to use for chat completion. Options include 'r1-1776', 'sonar', 'sonar-pro', 'sonar-reasoning', 'sonar-reasoning-pro', 'sonar-deep-research'. Defaults to 'sonar'
|
|
32
|
+
temperature: Controls randomness in the model's output. Higher values make output more random, lower values more deterministic. Defaults to 1
|
|
33
|
+
system_prompt: Initial system message to guide the model's behavior. Defaults to 'Be precise and concise.'
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
A dictionary containing the generated content and citations, with keys 'content' (str) and 'citations' (list), or a string in some cases
|
|
37
|
+
|
|
38
|
+
Raises:
|
|
39
|
+
AuthenticationError: Raised when API authentication fails due to missing or invalid credentials
|
|
40
|
+
HTTPError: Raised when the API request fails or returns an error status
|
|
41
|
+
|
|
42
|
+
Tags:
|
|
43
|
+
chat, generate, ai, completion, important
|
|
44
|
+
"""
|
|
45
|
+
endpoint = f"{self.base_url}/chat/completions"
|
|
46
|
+
messages = []
|
|
47
|
+
if system_prompt:
|
|
48
|
+
messages.append({"role": "system", "content": system_prompt})
|
|
49
|
+
messages.append({"role": "user", "content": query})
|
|
50
|
+
payload = {
|
|
51
|
+
"model": model,
|
|
52
|
+
"messages": messages,
|
|
53
|
+
"temperature": temperature,
|
|
54
|
+
# "max_tokens": 512,
|
|
55
|
+
}
|
|
56
|
+
data = self._post(endpoint, data=payload)
|
|
57
|
+
response = data.json()
|
|
58
|
+
content = response["choices"][0]["message"]["content"]
|
|
59
|
+
citations = response.get("citations", [])
|
|
60
|
+
return {"content": content, "citations": citations}
|
|
61
|
+
|
|
62
|
+
def list_tools(self):
|
|
63
|
+
return [
|
|
64
|
+
self.chat,
|
|
65
|
+
]
|