universal-mcp-applications 0.1.33__py3-none-any.whl → 0.1.39rc16__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.
Potentially problematic release.
This version of universal-mcp-applications might be problematic. Click here for more details.
- universal_mcp/applications/BEST_PRACTICES.md +1 -1
- universal_mcp/applications/ahrefs/app.py +92 -238
- universal_mcp/applications/airtable/app.py +36 -135
- universal_mcp/applications/apollo/app.py +124 -477
- universal_mcp/applications/asana/app.py +605 -1755
- universal_mcp/applications/aws_s3/app.py +63 -119
- universal_mcp/applications/bill/app.py +644 -2055
- universal_mcp/applications/box/app.py +1246 -4159
- universal_mcp/applications/braze/app.py +410 -1476
- universal_mcp/applications/browser_use/README.md +15 -1
- universal_mcp/applications/browser_use/__init__.py +1 -0
- universal_mcp/applications/browser_use/app.py +91 -26
- universal_mcp/applications/cal_com_v2/app.py +207 -625
- universal_mcp/applications/calendly/app.py +103 -242
- universal_mcp/applications/canva/app.py +75 -140
- universal_mcp/applications/clickup/app.py +331 -798
- universal_mcp/applications/coda/app.py +240 -520
- universal_mcp/applications/confluence/app.py +497 -1285
- universal_mcp/applications/contentful/app.py +40 -155
- universal_mcp/applications/crustdata/app.py +44 -123
- universal_mcp/applications/dialpad/app.py +451 -924
- universal_mcp/applications/digitalocean/app.py +2071 -6082
- universal_mcp/applications/domain_checker/app.py +3 -54
- universal_mcp/applications/e2b/app.py +17 -68
- universal_mcp/applications/elevenlabs/README.md +27 -3
- universal_mcp/applications/elevenlabs/app.py +741 -74
- universal_mcp/applications/exa/README.md +8 -4
- universal_mcp/applications/exa/app.py +415 -186
- universal_mcp/applications/falai/README.md +5 -7
- universal_mcp/applications/falai/app.py +156 -232
- universal_mcp/applications/figma/app.py +91 -175
- universal_mcp/applications/file_system/app.py +2 -13
- universal_mcp/applications/firecrawl/app.py +198 -176
- universal_mcp/applications/fireflies/app.py +59 -281
- universal_mcp/applications/fpl/app.py +92 -529
- universal_mcp/applications/fpl/utils/fixtures.py +15 -49
- universal_mcp/applications/fpl/utils/helper.py +25 -89
- universal_mcp/applications/fpl/utils/league_utils.py +20 -64
- universal_mcp/applications/ghost_content/app.py +70 -179
- universal_mcp/applications/github/app.py +30 -67
- universal_mcp/applications/gong/app.py +142 -302
- universal_mcp/applications/google_calendar/app.py +26 -78
- universal_mcp/applications/google_docs/README.md +15 -14
- universal_mcp/applications/google_docs/app.py +103 -206
- universal_mcp/applications/google_drive/app.py +194 -793
- universal_mcp/applications/google_gemini/app.py +68 -59
- universal_mcp/applications/google_mail/README.md +1 -0
- universal_mcp/applications/google_mail/app.py +93 -214
- universal_mcp/applications/google_searchconsole/app.py +25 -58
- universal_mcp/applications/google_sheet/README.md +2 -1
- universal_mcp/applications/google_sheet/app.py +226 -624
- universal_mcp/applications/google_sheet/helper.py +26 -53
- universal_mcp/applications/hashnode/app.py +57 -269
- universal_mcp/applications/heygen/README.md +10 -32
- universal_mcp/applications/heygen/app.py +339 -811
- universal_mcp/applications/http_tools/app.py +10 -32
- universal_mcp/applications/hubspot/README.md +1 -1
- universal_mcp/applications/hubspot/app.py +7508 -99
- universal_mcp/applications/jira/app.py +2419 -8334
- universal_mcp/applications/klaviyo/app.py +739 -1621
- universal_mcp/applications/linkedin/README.md +18 -1
- universal_mcp/applications/linkedin/app.py +729 -251
- universal_mcp/applications/mailchimp/app.py +696 -1851
- universal_mcp/applications/markitdown/app.py +8 -20
- universal_mcp/applications/miro/app.py +333 -815
- universal_mcp/applications/ms_teams/app.py +420 -1407
- universal_mcp/applications/neon/app.py +144 -250
- universal_mcp/applications/notion/app.py +38 -53
- universal_mcp/applications/onedrive/app.py +26 -48
- universal_mcp/applications/openai/app.py +43 -166
- universal_mcp/applications/outlook/README.md +22 -9
- universal_mcp/applications/outlook/app.py +403 -141
- universal_mcp/applications/perplexity/README.md +2 -1
- universal_mcp/applications/perplexity/app.py +161 -20
- universal_mcp/applications/pipedrive/app.py +1021 -3331
- universal_mcp/applications/posthog/app.py +272 -541
- universal_mcp/applications/reddit/app.py +65 -164
- universal_mcp/applications/resend/app.py +72 -139
- universal_mcp/applications/retell/app.py +23 -50
- universal_mcp/applications/rocketlane/app.py +252 -965
- universal_mcp/applications/scraper/app.py +114 -142
- universal_mcp/applications/semanticscholar/app.py +36 -78
- universal_mcp/applications/semrush/app.py +44 -78
- universal_mcp/applications/sendgrid/app.py +826 -1576
- universal_mcp/applications/sentry/app.py +444 -1079
- universal_mcp/applications/serpapi/app.py +44 -146
- universal_mcp/applications/sharepoint/app.py +27 -49
- universal_mcp/applications/shopify/app.py +1748 -4486
- universal_mcp/applications/shortcut/app.py +275 -536
- universal_mcp/applications/slack/app.py +43 -125
- universal_mcp/applications/spotify/app.py +206 -405
- universal_mcp/applications/supabase/app.py +174 -283
- universal_mcp/applications/tavily/app.py +2 -2
- universal_mcp/applications/trello/app.py +853 -2816
- universal_mcp/applications/twilio/app.py +27 -62
- universal_mcp/applications/twitter/api_segments/compliance_api.py +4 -14
- universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +6 -18
- universal_mcp/applications/twitter/api_segments/likes_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/lists_api.py +5 -15
- universal_mcp/applications/twitter/api_segments/trends_api.py +1 -3
- universal_mcp/applications/twitter/api_segments/tweets_api.py +9 -31
- universal_mcp/applications/twitter/api_segments/usage_api.py +1 -5
- universal_mcp/applications/twitter/api_segments/users_api.py +14 -42
- universal_mcp/applications/whatsapp/app.py +35 -186
- universal_mcp/applications/whatsapp/audio.py +2 -6
- universal_mcp/applications/whatsapp/whatsapp.py +17 -51
- universal_mcp/applications/whatsapp_business/app.py +86 -299
- universal_mcp/applications/wrike/app.py +80 -153
- universal_mcp/applications/yahoo_finance/app.py +19 -65
- universal_mcp/applications/youtube/app.py +120 -306
- universal_mcp/applications/zenquotes/app.py +3 -3
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/METADATA +4 -2
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/RECORD +115 -119
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/WHEEL +1 -1
- universal_mcp/applications/hubspot/api_segments/__init__.py +0 -0
- universal_mcp/applications/hubspot/api_segments/api_segment_base.py +0 -54
- universal_mcp/applications/hubspot/api_segments/crm_api.py +0 -7337
- universal_mcp/applications/hubspot/api_segments/marketing_api.py +0 -1467
- {universal_mcp_applications-0.1.33.dist-info → universal_mcp_applications-0.1.39rc16.dist-info}/licenses/LICENSE +0 -0
|
@@ -3,8 +3,7 @@ import io
|
|
|
3
3
|
import os
|
|
4
4
|
import uuid
|
|
5
5
|
import wave
|
|
6
|
-
from typing import Annotated
|
|
7
|
-
|
|
6
|
+
from typing import Annotated, Literal
|
|
8
7
|
from google import genai
|
|
9
8
|
from google.genai import types
|
|
10
9
|
from PIL import Image
|
|
@@ -17,16 +16,11 @@ class GoogleGeminiApp(APIApplication):
|
|
|
17
16
|
super().__init__(name="google_gemini", integration=integration, **kwargs)
|
|
18
17
|
self._genai_client = None
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
def genai_client(self) -> genai.Client:
|
|
19
|
+
async def get_genai_client(self) -> genai.Client:
|
|
22
20
|
if self._genai_client is not None:
|
|
23
21
|
return self._genai_client
|
|
24
|
-
credentials = self.integration.
|
|
25
|
-
api_key = (
|
|
26
|
-
credentials.get("api_key")
|
|
27
|
-
or credentials.get("API_KEY")
|
|
28
|
-
or credentials.get("apiKey")
|
|
29
|
-
)
|
|
22
|
+
credentials = await self.integration.get_credentials_async()
|
|
23
|
+
api_key = credentials.get("api_key") or credentials.get("API_KEY") or credentials.get("apiKey")
|
|
30
24
|
if not api_key:
|
|
31
25
|
raise ValueError("API key not found in integration credentials")
|
|
32
26
|
self._genai_client = genai.Client(api_key=api_key)
|
|
@@ -35,7 +29,12 @@ class GoogleGeminiApp(APIApplication):
|
|
|
35
29
|
async def generate_text(
|
|
36
30
|
self,
|
|
37
31
|
prompt: Annotated[str, "The prompt to generate text from"],
|
|
38
|
-
model:
|
|
32
|
+
model: Literal[
|
|
33
|
+
"gemini-2.5-flash",
|
|
34
|
+
"gemini-2.5-pro",
|
|
35
|
+
"gemini-3-flash-preview",
|
|
36
|
+
"gemini-3-pro-preview",
|
|
37
|
+
] = "gemini-2.5-flash",
|
|
39
38
|
) -> str:
|
|
40
39
|
"""Generates text using the Google Gemini model based on a given prompt.
|
|
41
40
|
This tool is suitable for various natural language processing tasks such as content generation, summarization, translation, and question answering.
|
|
@@ -54,16 +53,15 @@ class GoogleGeminiApp(APIApplication):
|
|
|
54
53
|
Tags:
|
|
55
54
|
text, generate, llm, important
|
|
56
55
|
"""
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
56
|
+
client = await self.get_genai_client()
|
|
57
|
+
response = client.models.generate_content(contents=prompt, model=model)
|
|
60
58
|
return response.text
|
|
61
59
|
|
|
62
60
|
async def generate_image(
|
|
63
61
|
self,
|
|
64
62
|
prompt: Annotated[str, "The prompt to generate image from"],
|
|
65
|
-
images: Annotated[list[str], "The reference image URLs"] | None = None,
|
|
66
|
-
model:
|
|
63
|
+
images: Annotated[list[str], "The reference image URLs"] | None = None,
|
|
64
|
+
model: Literal["gemini-3-pro-image-preview", "gemini-2.5-flash-image"] = "gemini-2.5-flash-image",
|
|
67
65
|
) -> dict:
|
|
68
66
|
"""
|
|
69
67
|
Generates an image based on a text prompt and an optional reference image using the Google Gemini model.
|
|
@@ -73,12 +71,12 @@ class GoogleGeminiApp(APIApplication):
|
|
|
73
71
|
Args:
|
|
74
72
|
prompt (str): The descriptive text prompt to guide the image generation. For example: "A futuristic city at sunset with flying cars."
|
|
75
73
|
images (list[str], optional): An optional list of URLs to reference images. These images will be used as a basis for the generation.
|
|
76
|
-
model (str, optional): The Gemini model to use for image generation. Defaults to "gemini-2.5-flash-image
|
|
74
|
+
model (str, optional): The Gemini model to use for image generation. Defaults to "gemini-2.5-flash-image".
|
|
77
75
|
|
|
78
76
|
Returns:
|
|
79
77
|
dict: A dictionary containing:
|
|
80
78
|
- 'type' (str): Always "image".
|
|
81
|
-
- 'data' (str): The base64 encoded image data.
|
|
79
|
+
- 'data' (str): The base64 encoded image data. Either upload or save this and then render the file path/link in markdown to the user. DO NOT use a data url.
|
|
82
80
|
- 'mime_type' (str): The MIME type of the image (e.g., "image/png").
|
|
83
81
|
- 'file_name' (str): A suggested file name for the generated image.
|
|
84
82
|
- 'text' (str): Any accompanying text generated by the model.
|
|
@@ -91,7 +89,7 @@ class GoogleGeminiApp(APIApplication):
|
|
|
91
89
|
Tags:
|
|
92
90
|
image, generate, vision, important
|
|
93
91
|
"""
|
|
94
|
-
|
|
92
|
+
client = await self.get_genai_client()
|
|
95
93
|
contents = [prompt]
|
|
96
94
|
if images:
|
|
97
95
|
for image in images:
|
|
@@ -104,35 +102,22 @@ class GoogleGeminiApp(APIApplication):
|
|
|
104
102
|
else:
|
|
105
103
|
image = Image.open(image)
|
|
106
104
|
contents.append(image)
|
|
107
|
-
response =
|
|
108
|
-
model=model,
|
|
109
|
-
contents=contents,
|
|
110
|
-
)
|
|
105
|
+
response = client.models.generate_content(model=model, contents=contents)
|
|
111
106
|
candidate = response.candidates[0]
|
|
112
107
|
text = ""
|
|
113
108
|
for part in candidate.content.parts:
|
|
114
109
|
if part.text is not None:
|
|
115
110
|
text += part.text
|
|
116
111
|
elif part.inline_data is not None:
|
|
117
|
-
# Return the raw image bytes
|
|
118
112
|
image_bytes = part.inline_data.data
|
|
119
|
-
|
|
120
113
|
img_base64 = base64.b64encode(image_bytes).decode("utf-8")
|
|
121
|
-
|
|
122
114
|
file_name = f"{uuid.uuid4()}.png"
|
|
123
|
-
|
|
124
|
-
return {
|
|
125
|
-
"type": "image",
|
|
126
|
-
"data": img_base64,
|
|
127
|
-
"mime_type": "image/png",
|
|
128
|
-
"file_name": file_name,
|
|
129
|
-
"text": text,
|
|
130
|
-
}
|
|
115
|
+
return {"type": "image", "data": img_base64, "mime_type": "image/png", "file_name": file_name, "text": text}
|
|
131
116
|
|
|
132
117
|
async def generate_audio(
|
|
133
118
|
self,
|
|
134
119
|
prompt: Annotated[str, "The prompt to generate audio from"],
|
|
135
|
-
model:
|
|
120
|
+
model: Literal["gemini-2.5-flash-preview-tts", "gemini-2.5-pro-preview-tts"] = "gemini-2.5-flash-preview-tts",
|
|
136
121
|
) -> str:
|
|
137
122
|
"""Generates audio from a given text prompt using the Google Gemini model's Text-to-Speech (TTS) capabilities.
|
|
138
123
|
This tool is useful for converting text into spoken audio, which can be used for voiceovers, accessibility features, or interactive applications.
|
|
@@ -155,8 +140,8 @@ class GoogleGeminiApp(APIApplication):
|
|
|
155
140
|
Tags:
|
|
156
141
|
audio, generate, tts, speech, important
|
|
157
142
|
"""
|
|
143
|
+
client = await self.get_genai_client()
|
|
158
144
|
|
|
159
|
-
# Set up the wave file to save the output:
|
|
160
145
|
def wave_file(filename, pcm, channels=1, rate=24000, sample_width=2):
|
|
161
146
|
with wave.open(filename, "wb") as wf:
|
|
162
147
|
wf.setnchannels(channels)
|
|
@@ -164,58 +149,82 @@ class GoogleGeminiApp(APIApplication):
|
|
|
164
149
|
wf.setframerate(rate)
|
|
165
150
|
wf.writeframes(pcm)
|
|
166
151
|
|
|
167
|
-
response =
|
|
152
|
+
response = client.models.generate_content(
|
|
168
153
|
model=model,
|
|
169
154
|
contents=prompt,
|
|
170
155
|
config=types.GenerateContentConfig(
|
|
171
156
|
response_modalities=["AUDIO"],
|
|
172
157
|
speech_config=types.SpeechConfig(
|
|
173
|
-
voice_config=types.VoiceConfig(
|
|
174
|
-
prebuilt_voice_config=types.PrebuiltVoiceConfig(
|
|
175
|
-
voice_name="Kore",
|
|
176
|
-
)
|
|
177
|
-
)
|
|
158
|
+
voice_config=types.VoiceConfig(prebuilt_voice_config=types.PrebuiltVoiceConfig(voice_name="Kore"))
|
|
178
159
|
),
|
|
179
160
|
),
|
|
180
161
|
)
|
|
181
|
-
|
|
182
162
|
data = response.candidates[0].content.parts[0].inline_data.data
|
|
183
|
-
|
|
184
163
|
file_name = f"{uuid.uuid4()}.wav"
|
|
185
164
|
wave_file(file_name, data)
|
|
186
|
-
|
|
187
|
-
# read the file
|
|
188
165
|
with open(file_name, "rb") as f:
|
|
189
166
|
data = f.read()
|
|
190
|
-
|
|
191
|
-
# delete the file
|
|
192
167
|
os.remove(file_name)
|
|
193
|
-
|
|
194
|
-
# Convert to base64
|
|
195
168
|
import base64
|
|
196
169
|
|
|
197
170
|
audio_base64 = base64.b64encode(data).decode("utf-8")
|
|
171
|
+
return {"type": "audio", "data": audio_base64, "mime_type": "audio/wav", "file_name": file_name}
|
|
172
|
+
|
|
173
|
+
async def analyze_image(
|
|
174
|
+
self,
|
|
175
|
+
images: Annotated[list[str], "The reference image URLs"],
|
|
176
|
+
prompt: Annotated[str, "The prompt to describe or ask about the image"] = "Describe this image",
|
|
177
|
+
model: Literal["gemini-2.5-flash", "gemini-2.5-pro"] = "gemini-2.5-flash",
|
|
178
|
+
) -> str:
|
|
179
|
+
"""
|
|
180
|
+
Analyzes one or more images based on a text prompt using the Google Gemini model.
|
|
181
|
+
This tool is capable of describing images, answering questions about them, or performing visual reasoning.
|
|
182
|
+
It accepts image URLs and a text prompt, returning a natural language response.
|
|
198
183
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
"
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
184
|
+
Args:
|
|
185
|
+
images (list[str]): A list of URLs for the images to be analyzed.
|
|
186
|
+
prompt (str, optional): The text prompt or question about the images. Defaults to "Describe this image".
|
|
187
|
+
model (str, optional): The Gemini model to use for analysis. Defaults to "gemini-2.5-flash".
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
str: The generated text response containing the analysis or description of the images.
|
|
191
|
+
|
|
192
|
+
Raises:
|
|
193
|
+
requests.exceptions.RequestException: If there's an issue fetching a remote image.
|
|
194
|
+
FileNotFoundError: If a local image path is invalid.
|
|
195
|
+
Exception: If the underlying Gemini API call fails.
|
|
196
|
+
|
|
197
|
+
Tags:
|
|
198
|
+
image, analyze, vision, describe, question, important
|
|
199
|
+
"""
|
|
200
|
+
client = await self.get_genai_client()
|
|
201
|
+
contents = [prompt]
|
|
202
|
+
if images:
|
|
203
|
+
for image in images:
|
|
204
|
+
if image.startswith(("http://", "https://")):
|
|
205
|
+
import requests
|
|
206
|
+
|
|
207
|
+
response = requests.get(image)
|
|
208
|
+
response.raise_for_status()
|
|
209
|
+
image = Image.open(io.BytesIO(response.content))
|
|
210
|
+
else:
|
|
211
|
+
image = Image.open(image)
|
|
212
|
+
contents.append(image)
|
|
213
|
+
response = client.models.generate_content(model=model, contents=contents)
|
|
214
|
+
return response.text
|
|
205
215
|
|
|
206
216
|
def list_tools(self):
|
|
207
217
|
return [
|
|
208
218
|
self.generate_text,
|
|
209
219
|
self.generate_image,
|
|
220
|
+
self.analyze_image,
|
|
210
221
|
self.generate_audio,
|
|
211
222
|
]
|
|
212
223
|
|
|
213
224
|
|
|
214
225
|
async def test_google_gemini():
|
|
215
226
|
app = GoogleGeminiApp()
|
|
216
|
-
await app.generate_image(
|
|
217
|
-
"A beautiful women potrait with red green hair color"
|
|
218
|
-
)
|
|
227
|
+
await app.generate_image("A beautiful women potrait with red green hair color")
|
|
219
228
|
|
|
220
229
|
|
|
221
230
|
if __name__ == "__main__":
|
|
@@ -16,6 +16,7 @@ This is automatically generated from OpenAPI schema for the GoogleMailApp API.
|
|
|
16
16
|
| `list_drafts` | Fetches a list of email drafts, allowing filtering by a search query and limiting results. It can optionally include drafts from spam and trash, returning a collection of draft objects. This is distinct from `get_draft`, which retrieves only a single, specific draft by its ID. |
|
|
17
17
|
| `get_message_details` | Retrieves a specific email from Gmail by its ID. It parses the API response to extract and format key details—including sender, subject, body, and attachments—into a structured dictionary. This function provides detailed data for a single message, distinguishing it from `list_messages` which fetches multiple messages. |
|
|
18
18
|
| `list_messages` | Fetches a paginated list of detailed email messages using optional search queries. It concurrently retrieves full content (sender, subject, body) for each message, returning the results and a pagination token. This differs from `get_message_details`, which fetches only a single message. |
|
|
19
|
+
| `get_email_thread` | Fetches a complete email conversation by its unique thread ID. Unlike `get_message_details`, which retrieves a single message, this returns all messages and metadata for the entire thread, providing the full context of the conversation. |
|
|
19
20
|
| `list_labels` | Fetches a complete list of all available labels from the user's Gmail account via the API. It retrieves both system-defined (e.g., INBOX) and user-created labels, returning their names and IDs, complementing management functions like `create_label` and `update_label`. |
|
|
20
21
|
| `create_label` | Creates a new Gmail label with a specified name, hardcoding its visibility to ensure it appears in both label and message lists. This function complements `update_label` and `delete_label` by adding new organizational tags to the user's account via the API. |
|
|
21
22
|
| `get_profile` | Retrieves the authenticated user's Gmail profile from the API. The profile includes the user's email address, total message and thread counts, and the mailbox's history ID, offering a high-level summary of the account's state. |
|