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.
Files changed (268) hide show
  1. universal_mcp/applications/ahrefs/README.md +51 -0
  2. universal_mcp/applications/ahrefs/__init__.py +1 -0
  3. universal_mcp/applications/ahrefs/app.py +2291 -0
  4. universal_mcp/applications/airtable/README.md +22 -0
  5. universal_mcp/applications/airtable/__init__.py +1 -0
  6. universal_mcp/applications/airtable/app.py +479 -0
  7. universal_mcp/applications/apollo/README.md +44 -0
  8. universal_mcp/applications/apollo/__init__.py +1 -0
  9. universal_mcp/applications/apollo/app.py +1847 -0
  10. universal_mcp/applications/asana/README.md +199 -0
  11. universal_mcp/applications/asana/__init__.py +1 -0
  12. universal_mcp/applications/asana/app.py +9509 -0
  13. universal_mcp/applications/aws-s3/README.md +0 -0
  14. universal_mcp/applications/aws-s3/__init__.py +1 -0
  15. universal_mcp/applications/aws-s3/app.py +552 -0
  16. universal_mcp/applications/bill/README.md +0 -0
  17. universal_mcp/applications/bill/__init__.py +1 -0
  18. universal_mcp/applications/bill/app.py +8705 -0
  19. universal_mcp/applications/box/README.md +307 -0
  20. universal_mcp/applications/box/__init__.py +1 -0
  21. universal_mcp/applications/box/app.py +15987 -0
  22. universal_mcp/applications/braze/README.md +106 -0
  23. universal_mcp/applications/braze/__init__.py +1 -0
  24. universal_mcp/applications/braze/app.py +4754 -0
  25. universal_mcp/applications/cal-com-v2/README.md +150 -0
  26. universal_mcp/applications/cal-com-v2/__init__.py +1 -0
  27. universal_mcp/applications/cal-com-v2/app.py +5541 -0
  28. universal_mcp/applications/calendly/README.md +53 -0
  29. universal_mcp/applications/calendly/__init__.py +1 -0
  30. universal_mcp/applications/calendly/app.py +1436 -0
  31. universal_mcp/applications/canva/README.md +43 -0
  32. universal_mcp/applications/canva/__init__.py +1 -0
  33. universal_mcp/applications/canva/app.py +941 -0
  34. universal_mcp/applications/clickup/README.md +135 -0
  35. universal_mcp/applications/clickup/__init__.py +1 -0
  36. universal_mcp/applications/clickup/app.py +5009 -0
  37. universal_mcp/applications/coda/README.md +108 -0
  38. universal_mcp/applications/coda/__init__.py +1 -0
  39. universal_mcp/applications/coda/app.py +3671 -0
  40. universal_mcp/applications/confluence/README.md +198 -0
  41. universal_mcp/applications/confluence/__init__.py +1 -0
  42. universal_mcp/applications/confluence/app.py +6273 -0
  43. universal_mcp/applications/contentful/README.md +17 -0
  44. universal_mcp/applications/contentful/__init__.py +1 -0
  45. universal_mcp/applications/contentful/app.py +364 -0
  46. universal_mcp/applications/crustdata/README.md +25 -0
  47. universal_mcp/applications/crustdata/__init__.py +1 -0
  48. universal_mcp/applications/crustdata/app.py +586 -0
  49. universal_mcp/applications/dialpad/README.md +202 -0
  50. universal_mcp/applications/dialpad/__init__.py +1 -0
  51. universal_mcp/applications/dialpad/app.py +5949 -0
  52. universal_mcp/applications/digitalocean/README.md +463 -0
  53. universal_mcp/applications/digitalocean/__init__.py +1 -0
  54. universal_mcp/applications/digitalocean/app.py +20835 -0
  55. universal_mcp/applications/domain-checker/README.md +13 -0
  56. universal_mcp/applications/domain-checker/__init__.py +1 -0
  57. universal_mcp/applications/domain-checker/app.py +265 -0
  58. universal_mcp/applications/e2b/README.md +12 -0
  59. universal_mcp/applications/e2b/__init__.py +1 -0
  60. universal_mcp/applications/e2b/app.py +187 -0
  61. universal_mcp/applications/elevenlabs/README.md +88 -0
  62. universal_mcp/applications/elevenlabs/__init__.py +1 -0
  63. universal_mcp/applications/elevenlabs/app.py +3235 -0
  64. universal_mcp/applications/exa/README.md +15 -0
  65. universal_mcp/applications/exa/__init__.py +1 -0
  66. universal_mcp/applications/exa/app.py +221 -0
  67. universal_mcp/applications/falai/README.md +17 -0
  68. universal_mcp/applications/falai/__init__.py +1 -0
  69. universal_mcp/applications/falai/app.py +331 -0
  70. universal_mcp/applications/figma/README.md +49 -0
  71. universal_mcp/applications/figma/__init__.py +1 -0
  72. universal_mcp/applications/figma/app.py +1090 -0
  73. universal_mcp/applications/firecrawl/README.md +20 -0
  74. universal_mcp/applications/firecrawl/__init__.py +1 -0
  75. universal_mcp/applications/firecrawl/app.py +514 -0
  76. universal_mcp/applications/fireflies/README.md +25 -0
  77. universal_mcp/applications/fireflies/__init__.py +1 -0
  78. universal_mcp/applications/fireflies/app.py +506 -0
  79. universal_mcp/applications/fpl/README.md +23 -0
  80. universal_mcp/applications/fpl/__init__.py +1 -0
  81. universal_mcp/applications/fpl/app.py +1327 -0
  82. universal_mcp/applications/fpl/utils/api.py +142 -0
  83. universal_mcp/applications/fpl/utils/fixtures.py +629 -0
  84. universal_mcp/applications/fpl/utils/helper.py +982 -0
  85. universal_mcp/applications/fpl/utils/league_utils.py +546 -0
  86. universal_mcp/applications/fpl/utils/position_utils.py +68 -0
  87. universal_mcp/applications/ghost-content/README.md +25 -0
  88. universal_mcp/applications/ghost-content/__init__.py +1 -0
  89. universal_mcp/applications/ghost-content/app.py +654 -0
  90. universal_mcp/applications/github/README.md +1049 -0
  91. universal_mcp/applications/github/__init__.py +1 -0
  92. universal_mcp/applications/github/app.py +50600 -0
  93. universal_mcp/applications/gong/README.md +63 -0
  94. universal_mcp/applications/gong/__init__.py +1 -0
  95. universal_mcp/applications/gong/app.py +2297 -0
  96. universal_mcp/applications/google-ads/README.md +0 -0
  97. universal_mcp/applications/google-ads/__init__.py +1 -0
  98. universal_mcp/applications/google-ads/app.py +23 -0
  99. universal_mcp/applications/google-calendar/README.md +21 -0
  100. universal_mcp/applications/google-calendar/__init__.py +1 -0
  101. universal_mcp/applications/google-calendar/app.py +574 -0
  102. universal_mcp/applications/google-docs/README.md +25 -0
  103. universal_mcp/applications/google-docs/__init__.py +1 -0
  104. universal_mcp/applications/google-docs/app.py +760 -0
  105. universal_mcp/applications/google-drive/README.md +68 -0
  106. universal_mcp/applications/google-drive/__init__.py +1 -0
  107. universal_mcp/applications/google-drive/app.py +4936 -0
  108. universal_mcp/applications/google-gemini/README.md +25 -0
  109. universal_mcp/applications/google-gemini/__init__.py +1 -0
  110. universal_mcp/applications/google-gemini/app.py +663 -0
  111. universal_mcp/applications/google-mail/README.md +31 -0
  112. universal_mcp/applications/google-mail/__init__.py +1 -0
  113. universal_mcp/applications/google-mail/app.py +1354 -0
  114. universal_mcp/applications/google-searchconsole/README.md +21 -0
  115. universal_mcp/applications/google-searchconsole/__init__.py +1 -0
  116. universal_mcp/applications/google-searchconsole/app.py +320 -0
  117. universal_mcp/applications/google-sheet/README.md +36 -0
  118. universal_mcp/applications/google-sheet/__init__.py +1 -0
  119. universal_mcp/applications/google-sheet/app.py +1941 -0
  120. universal_mcp/applications/hashnode/README.md +20 -0
  121. universal_mcp/applications/hashnode/__init__.py +1 -0
  122. universal_mcp/applications/hashnode/app.py +455 -0
  123. universal_mcp/applications/heygen/README.md +44 -0
  124. universal_mcp/applications/heygen/__init__.py +1 -0
  125. universal_mcp/applications/heygen/app.py +961 -0
  126. universal_mcp/applications/http-tools/README.md +16 -0
  127. universal_mcp/applications/http-tools/__init__.py +1 -0
  128. universal_mcp/applications/http-tools/app.py +153 -0
  129. universal_mcp/applications/hubspot/README.md +239 -0
  130. universal_mcp/applications/hubspot/__init__.py +1 -0
  131. universal_mcp/applications/hubspot/app.py +416 -0
  132. universal_mcp/applications/jira/README.md +600 -0
  133. universal_mcp/applications/jira/__init__.py +1 -0
  134. universal_mcp/applications/jira/app.py +28804 -0
  135. universal_mcp/applications/klaviyo/README.md +313 -0
  136. universal_mcp/applications/klaviyo/__init__.py +1 -0
  137. universal_mcp/applications/klaviyo/app.py +11236 -0
  138. universal_mcp/applications/linkedin/README.md +15 -0
  139. universal_mcp/applications/linkedin/__init__.py +1 -0
  140. universal_mcp/applications/linkedin/app.py +243 -0
  141. universal_mcp/applications/mailchimp/README.md +281 -0
  142. universal_mcp/applications/mailchimp/__init__.py +1 -0
  143. universal_mcp/applications/mailchimp/app.py +10937 -0
  144. universal_mcp/applications/markitdown/README.md +12 -0
  145. universal_mcp/applications/markitdown/__init__.py +1 -0
  146. universal_mcp/applications/markitdown/app.py +63 -0
  147. universal_mcp/applications/miro/README.md +151 -0
  148. universal_mcp/applications/miro/__init__.py +1 -0
  149. universal_mcp/applications/miro/app.py +5429 -0
  150. universal_mcp/applications/ms-teams/README.md +42 -0
  151. universal_mcp/applications/ms-teams/__init__.py +1 -0
  152. universal_mcp/applications/ms-teams/app.py +1823 -0
  153. universal_mcp/applications/neon/README.md +74 -0
  154. universal_mcp/applications/neon/__init__.py +1 -0
  155. universal_mcp/applications/neon/app.py +2018 -0
  156. universal_mcp/applications/notion/README.md +30 -0
  157. universal_mcp/applications/notion/__init__.py +1 -0
  158. universal_mcp/applications/notion/app.py +527 -0
  159. universal_mcp/applications/openai/README.md +22 -0
  160. universal_mcp/applications/openai/__init__.py +1 -0
  161. universal_mcp/applications/openai/app.py +759 -0
  162. universal_mcp/applications/outlook/README.md +20 -0
  163. universal_mcp/applications/outlook/__init__.py +1 -0
  164. universal_mcp/applications/outlook/app.py +444 -0
  165. universal_mcp/applications/perplexity/README.md +12 -0
  166. universal_mcp/applications/perplexity/__init__.py +1 -0
  167. universal_mcp/applications/perplexity/app.py +65 -0
  168. universal_mcp/applications/pipedrive/README.md +284 -0
  169. universal_mcp/applications/pipedrive/__init__.py +1 -0
  170. universal_mcp/applications/pipedrive/app.py +12924 -0
  171. universal_mcp/applications/posthog/README.md +132 -0
  172. universal_mcp/applications/posthog/__init__.py +1 -0
  173. universal_mcp/applications/posthog/app.py +7125 -0
  174. universal_mcp/applications/reddit/README.md +135 -0
  175. universal_mcp/applications/reddit/__init__.py +1 -0
  176. universal_mcp/applications/reddit/app.py +4652 -0
  177. universal_mcp/applications/replicate/README.md +18 -0
  178. universal_mcp/applications/replicate/__init__.py +1 -0
  179. universal_mcp/applications/replicate/app.py +495 -0
  180. universal_mcp/applications/resend/README.md +40 -0
  181. universal_mcp/applications/resend/__init__.py +1 -0
  182. universal_mcp/applications/resend/app.py +881 -0
  183. universal_mcp/applications/retell/README.md +21 -0
  184. universal_mcp/applications/retell/__init__.py +1 -0
  185. universal_mcp/applications/retell/app.py +333 -0
  186. universal_mcp/applications/rocketlane/README.md +70 -0
  187. universal_mcp/applications/rocketlane/__init__.py +1 -0
  188. universal_mcp/applications/rocketlane/app.py +4346 -0
  189. universal_mcp/applications/semanticscholar/README.md +25 -0
  190. universal_mcp/applications/semanticscholar/__init__.py +1 -0
  191. universal_mcp/applications/semanticscholar/app.py +482 -0
  192. universal_mcp/applications/semrush/README.md +44 -0
  193. universal_mcp/applications/semrush/__init__.py +1 -0
  194. universal_mcp/applications/semrush/app.py +2081 -0
  195. universal_mcp/applications/sendgrid/README.md +362 -0
  196. universal_mcp/applications/sendgrid/__init__.py +1 -0
  197. universal_mcp/applications/sendgrid/app.py +9752 -0
  198. universal_mcp/applications/sentry/README.md +186 -0
  199. universal_mcp/applications/sentry/__init__.py +1 -0
  200. universal_mcp/applications/sentry/app.py +7471 -0
  201. universal_mcp/applications/serpapi/README.md +14 -0
  202. universal_mcp/applications/serpapi/__init__.py +1 -0
  203. universal_mcp/applications/serpapi/app.py +293 -0
  204. universal_mcp/applications/sharepoint/README.md +0 -0
  205. universal_mcp/applications/sharepoint/__init__.py +1 -0
  206. universal_mcp/applications/sharepoint/app.py +215 -0
  207. universal_mcp/applications/shopify/README.md +321 -0
  208. universal_mcp/applications/shopify/__init__.py +1 -0
  209. universal_mcp/applications/shopify/app.py +15392 -0
  210. universal_mcp/applications/shortcut/README.md +128 -0
  211. universal_mcp/applications/shortcut/__init__.py +1 -0
  212. universal_mcp/applications/shortcut/app.py +4478 -0
  213. universal_mcp/applications/slack/README.md +0 -0
  214. universal_mcp/applications/slack/__init__.py +1 -0
  215. universal_mcp/applications/slack/app.py +570 -0
  216. universal_mcp/applications/spotify/README.md +91 -0
  217. universal_mcp/applications/spotify/__init__.py +1 -0
  218. universal_mcp/applications/spotify/app.py +2526 -0
  219. universal_mcp/applications/supabase/README.md +87 -0
  220. universal_mcp/applications/supabase/__init__.py +1 -0
  221. universal_mcp/applications/supabase/app.py +2970 -0
  222. universal_mcp/applications/tavily/README.md +12 -0
  223. universal_mcp/applications/tavily/__init__.py +1 -0
  224. universal_mcp/applications/tavily/app.py +51 -0
  225. universal_mcp/applications/trello/README.md +266 -0
  226. universal_mcp/applications/trello/__init__.py +1 -0
  227. universal_mcp/applications/trello/app.py +10875 -0
  228. universal_mcp/applications/twillo/README.md +0 -0
  229. universal_mcp/applications/twillo/__init__.py +1 -0
  230. universal_mcp/applications/twillo/app.py +269 -0
  231. universal_mcp/applications/twitter/README.md +100 -0
  232. universal_mcp/applications/twitter/__init__.py +1 -0
  233. universal_mcp/applications/twitter/api_segments/__init__.py +0 -0
  234. universal_mcp/applications/twitter/api_segments/api_segment_base.py +51 -0
  235. universal_mcp/applications/twitter/api_segments/compliance_api.py +122 -0
  236. universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +255 -0
  237. universal_mcp/applications/twitter/api_segments/dm_events_api.py +140 -0
  238. universal_mcp/applications/twitter/api_segments/likes_api.py +159 -0
  239. universal_mcp/applications/twitter/api_segments/lists_api.py +395 -0
  240. universal_mcp/applications/twitter/api_segments/openapi_json_api.py +34 -0
  241. universal_mcp/applications/twitter/api_segments/spaces_api.py +309 -0
  242. universal_mcp/applications/twitter/api_segments/trends_api.py +40 -0
  243. universal_mcp/applications/twitter/api_segments/tweets_api.py +1403 -0
  244. universal_mcp/applications/twitter/api_segments/usage_api.py +40 -0
  245. universal_mcp/applications/twitter/api_segments/users_api.py +1498 -0
  246. universal_mcp/applications/twitter/app.py +46 -0
  247. universal_mcp/applications/unipile/README.md +28 -0
  248. universal_mcp/applications/unipile/__init__.py +1 -0
  249. universal_mcp/applications/unipile/app.py +829 -0
  250. universal_mcp/applications/whatsapp/README.md +23 -0
  251. universal_mcp/applications/whatsapp/__init__.py +1 -0
  252. universal_mcp/applications/whatsapp/app.py +595 -0
  253. universal_mcp/applications/whatsapp-business/README.md +34 -0
  254. universal_mcp/applications/whatsapp-business/__init__.py +1 -0
  255. universal_mcp/applications/whatsapp-business/app.py +1065 -0
  256. universal_mcp/applications/wrike/README.md +46 -0
  257. universal_mcp/applications/wrike/__init__.py +1 -0
  258. universal_mcp/applications/wrike/app.py +1583 -0
  259. universal_mcp/applications/youtube/README.md +57 -0
  260. universal_mcp/applications/youtube/__init__.py +1 -0
  261. universal_mcp/applications/youtube/app.py +1696 -0
  262. universal_mcp/applications/zenquotes/README.md +12 -0
  263. universal_mcp/applications/zenquotes/__init__.py +1 -0
  264. universal_mcp/applications/zenquotes/app.py +31 -0
  265. universal_mcp_applications-0.1.1.dist-info/METADATA +172 -0
  266. universal_mcp_applications-0.1.1.dist-info/RECORD +268 -0
  267. universal_mcp_applications-0.1.1.dist-info/WHEEL +4 -0
  268. universal_mcp_applications-0.1.1.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,760 @@
1
+ from typing import Any
2
+
3
+ from universal_mcp.applications.application import APIApplication
4
+ from universal_mcp.integrations import Integration
5
+
6
+
7
+ class GoogleDocsApp(APIApplication):
8
+ def __init__(self, integration: Integration) -> None:
9
+ super().__init__(name="google-docs", integration=integration)
10
+ self.base_api_url = "https://docs.googleapis.com/v1/documents"
11
+
12
+ def create_document(self, title: str) -> dict[str, Any]:
13
+ """
14
+ Creates a new blank Google Document with the specified title and returns the API response.
15
+
16
+ Args:
17
+ title: The title for the new Google Document to be created
18
+
19
+ Returns:
20
+ A dictionary containing the Google Docs API response with document details and metadata
21
+
22
+ Raises:
23
+ HTTPError: If the API request fails due to network issues, authentication errors, or invalid parameters
24
+ RequestException: If there are connection errors or timeout issues during the API request
25
+
26
+ Tags:
27
+ create, document, api, important, google-docs, http
28
+ """
29
+ url = self.base_api_url
30
+ document_data = {"title": title}
31
+ response = self._post(url, data=document_data)
32
+ response.raise_for_status()
33
+ return response.json()
34
+
35
+ def get_document(self, document_id: str) -> dict[str, Any]:
36
+ """
37
+ Retrieves the latest version of a specified document from the Google Docs API.
38
+
39
+ Args:
40
+ document_id: The unique identifier of the document to retrieve
41
+
42
+ Returns:
43
+ A dictionary containing the document data from the Google Docs API response
44
+
45
+ Raises:
46
+ HTTPError: If the API request fails or the document is not found
47
+ JSONDecodeError: If the API response cannot be parsed as JSON
48
+
49
+ Tags:
50
+ retrieve, read, api, document, google-docs, important
51
+ """
52
+ url = f"{self.base_api_url}/{document_id}"
53
+ response = self._get(url)
54
+ return response.json()
55
+
56
+ def add_content(
57
+ self, document_id: str, content: str, index: int = 1
58
+ ) -> dict[str, Any]:
59
+ """
60
+ Adds text content at a specified position in an existing Google Document via the Google Docs API.
61
+
62
+ Args:
63
+ document_id: The unique identifier of the Google Document to be updated
64
+ content: The text content to be inserted into the document
65
+ index: The zero-based position in the document where the text should be inserted (default: 1)
66
+
67
+ Returns:
68
+ A dictionary containing the Google Docs API response after performing the batch update operation
69
+
70
+ Raises:
71
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
72
+ RequestException: When there are network connectivity issues or API endpoint problems
73
+
74
+ Tags:
75
+ update, insert, document, api, google-docs, batch, content-management, important
76
+ """
77
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
78
+ batch_update_data = {
79
+ "requests": [
80
+ {"insertText": {"location": {"index": index}, "text": content}}
81
+ ]
82
+ }
83
+ response = self._post(url, data=batch_update_data)
84
+ response.raise_for_status()
85
+ return response.json()
86
+
87
+ def style_text(
88
+ self,
89
+ document_id: str,
90
+ start_index: int,
91
+ end_index: int,
92
+ bold: bool = False,
93
+ italic: bool = False,
94
+ underline: bool = False,
95
+ font_size: float | None = None,
96
+ link_url: str | None = None,
97
+ foreground_color: dict[str, float] | None = None,
98
+ background_color: dict[str, float] | None = None,
99
+ ) -> dict[str, Any]:
100
+ """
101
+ Simplified text styling for Google Document - handles most common cases.
102
+
103
+ Args:
104
+ document_id: The unique identifier of the Google Document to be updated
105
+ start_index: The zero-based start index of the text range to style
106
+ end_index: The zero-based end index of the text range to style (exclusive)
107
+ bold: Whether the text should be bold
108
+ italic: Whether the text should be italicized
109
+ underline: Whether the text should be underlined
110
+ font_size: The font size in points (e.g., 12.0 for 12pt)
111
+ link_url: URL to make the text a hyperlink
112
+ foreground_color: RGB color dict with 'red', 'green', 'blue' values (0.0 to 1.0)
113
+ background_color: RGB color dict with 'red', 'green', 'blue' values (0.0 to 1.0)
114
+
115
+ Returns:
116
+ A dictionary containing the Google Docs API response
117
+
118
+ Raises:
119
+ HTTPError: When the API request fails
120
+ RequestException: When there are network connectivity issues
121
+
122
+ Tags:
123
+ style, format, text, document, api, google-docs, simple
124
+ """
125
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
126
+
127
+ # Build the text style object with only common properties
128
+ text_style = {}
129
+ fields_to_update = []
130
+
131
+ if bold:
132
+ text_style["bold"] = True
133
+ fields_to_update.append("bold")
134
+
135
+ if italic:
136
+ text_style["italic"] = True
137
+ fields_to_update.append("italic")
138
+
139
+ if underline:
140
+ text_style["underline"] = True
141
+ fields_to_update.append("underline")
142
+
143
+ if font_size is not None:
144
+ text_style["fontSize"] = {"magnitude": font_size, "unit": "PT"}
145
+ fields_to_update.append("fontSize")
146
+
147
+ if link_url is not None:
148
+ text_style["link"] = {"url": link_url}
149
+ fields_to_update.append("link")
150
+
151
+ if foreground_color is not None:
152
+ text_style["foregroundColor"] = {
153
+ "color": {
154
+ "rgbColor": {
155
+ "red": foreground_color.get("red", 0.0),
156
+ "green": foreground_color.get("green", 0.0),
157
+ "blue": foreground_color.get("blue", 0.0),
158
+ }
159
+ }
160
+ }
161
+ fields_to_update.append("foregroundColor")
162
+
163
+ if background_color is not None:
164
+ text_style["backgroundColor"] = {
165
+ "color": {
166
+ "rgbColor": {
167
+ "red": background_color.get("red", 0.0),
168
+ "green": background_color.get("green", 0.0),
169
+ "blue": background_color.get("blue", 0.0),
170
+ }
171
+ }
172
+ }
173
+ fields_to_update.append("backgroundColor")
174
+
175
+ # If no styling requested, return early
176
+ if not text_style:
177
+ return {"message": "No styling applied"}
178
+
179
+ batch_update_data = {
180
+ "requests": [
181
+ {
182
+ "updateTextStyle": {
183
+ "range": {"startIndex": start_index, "endIndex": end_index},
184
+ "textStyle": text_style,
185
+ "fields": ",".join(fields_to_update),
186
+ }
187
+ }
188
+ ]
189
+ }
190
+
191
+ response = self._post(url, data=batch_update_data)
192
+ return self._handle_response(response)
193
+
194
+ def update_paragraph_style(
195
+ self,
196
+ document_id: str,
197
+ start_index: int,
198
+ end_index: int,
199
+ named_style_type: str | None = None,
200
+ alignment: str | None = None,
201
+ direction: str | None = None,
202
+ spacing_mode: str | None = None,
203
+ segment_id: str | None = None,
204
+ tab_id: str | None = None,
205
+ ) -> dict[str, Any]:
206
+ """
207
+ Updates paragraph styling for a specified range in a Google Document.
208
+
209
+ Args:
210
+ document_id: The unique identifier of the Google Document to be updated
211
+ start_index: The zero-based start index of the paragraph range to style
212
+ end_index: The zero-based end index of the paragraph range to style (exclusive)
213
+ named_style_type: The named style type (e.g., 'NORMAL_TEXT', 'TITLE', 'HEADING_1', etc.)
214
+ alignment: The paragraph alignment ('START', 'CENTER', 'END', 'JUSTIFIED')
215
+ direction: The content direction ('LEFT_TO_RIGHT', 'RIGHT_TO_LEFT')
216
+ spacing_mode: The spacing mode ('NEVER_COLLAPSE', 'COLLAPSE_LISTS')
217
+ segment_id: The segment ID for the range (optional)
218
+ tab_id: The tab ID for the range (optional)
219
+
220
+ Returns:
221
+ A dictionary containing the Google Docs API response
222
+
223
+ Raises:
224
+ HTTPError: When the API request fails
225
+ RequestException: When there are network connectivity issues
226
+
227
+ Tags:
228
+ style, format, paragraph, document, api, google-docs, batch, content-management
229
+ """
230
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
231
+
232
+ # Build the paragraph style object with only specified properties
233
+ paragraph_style = {}
234
+ fields_to_update = []
235
+
236
+ if named_style_type is not None:
237
+ paragraph_style["namedStyleType"] = named_style_type
238
+ fields_to_update.append("namedStyleType")
239
+
240
+ if alignment is not None:
241
+ paragraph_style["alignment"] = alignment
242
+ fields_to_update.append("alignment")
243
+
244
+ if direction is not None:
245
+ paragraph_style["direction"] = direction
246
+ fields_to_update.append("direction")
247
+
248
+ if spacing_mode is not None:
249
+ paragraph_style["spacingMode"] = spacing_mode
250
+ fields_to_update.append("spacingMode")
251
+
252
+ # If no styling requested, return early
253
+ if not paragraph_style:
254
+ return {"message": "No paragraph styling applied"}
255
+
256
+ # Build the range object
257
+ range_obj: dict[str, Any] = {"startIndex": start_index, "endIndex": end_index}
258
+
259
+ # Add optional parameters if provided
260
+ if segment_id is not None:
261
+ range_obj["segmentId"] = segment_id
262
+ if tab_id is not None:
263
+ range_obj["tabId"] = tab_id
264
+
265
+ batch_update_data = {
266
+ "requests": [
267
+ {
268
+ "updateParagraphStyle": {
269
+ "range": range_obj,
270
+ "paragraphStyle": paragraph_style,
271
+ "fields": ",".join(fields_to_update),
272
+ }
273
+ }
274
+ ]
275
+ }
276
+
277
+ response = self._post(url, data=batch_update_data)
278
+ return self._handle_response(response)
279
+
280
+ def delete_content(
281
+ self,
282
+ document_id: str,
283
+ start_index: int,
284
+ end_index: int,
285
+ segment_id: str | None = None,
286
+ tab_id: str | None = None,
287
+ ) -> dict[str, Any]:
288
+ """
289
+ Deletes content from a specified range in a Google Document.
290
+
291
+ Args:
292
+ document_id: The unique identifier of the Google Document to be updated
293
+ start_index: The zero-based start index of the content range to delete
294
+ end_index: The zero-based end index of the content range to delete (exclusive)
295
+ segment_id: The ID of the header, footer, or footnote segment (optional)
296
+ tab_id: The ID of the tab containing the content to delete (optional)
297
+
298
+ Returns:
299
+ A dictionary containing the Google Docs API response after performing the delete operation
300
+
301
+ Raises:
302
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
303
+ RequestException: When there are network connectivity issues or API endpoint problems
304
+
305
+ Tags:
306
+ delete, remove, content, document, api, google-docs, batch, content-management, important
307
+ """
308
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
309
+
310
+ # Build the delete content range request
311
+ delete_request: dict[str, Any] = {
312
+ "range": {"startIndex": start_index, "endIndex": end_index}
313
+ }
314
+
315
+ # Add optional parameters if provided
316
+ if segment_id is not None:
317
+ delete_request["range"]["segmentId"] = segment_id
318
+ if tab_id is not None:
319
+ delete_request["tabId"] = tab_id
320
+
321
+ batch_update_data = {"requests": [{"deleteContentRange": delete_request}]}
322
+
323
+ response = self._post(url, data=batch_update_data)
324
+ return self._handle_response(response)
325
+
326
+ def insert_table(
327
+ self,
328
+ document_id: str,
329
+ location_index: int,
330
+ rows: int,
331
+ columns: int,
332
+ segment_id: str = None,
333
+ tab_id: str = None,
334
+ ) -> dict[str, Any]:
335
+ """
336
+ Inserts a table at the specified location in a Google Document.
337
+
338
+ Args:
339
+ document_id: The unique identifier of the Google Document to be updated
340
+ location_index: The zero-based index where the table should be inserted
341
+ rows: The number of rows in the table
342
+ columns: The number of columns in the table
343
+ segment_id: The ID of the header, footer or footnote segment (optional)
344
+ tab_id: The ID of the tab containing the location (optional)
345
+
346
+ Returns:
347
+ A dictionary containing the Google Docs API response after performing the insert table operation
348
+
349
+ Raises:
350
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
351
+ RequestException: When there are network connectivity issues or API endpoint problems
352
+
353
+ Tags:
354
+ table, insert, document, api, google-docs, batch, content-management
355
+ """
356
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
357
+
358
+ # Build the location object according to Google Docs API specification
359
+ location = {"index": location_index}
360
+
361
+ # Add segment_id if provided (empty string for document body, specific ID for header/footer/footnote)
362
+ if segment_id is not None:
363
+ location["segmentId"] = segment_id
364
+
365
+ # Add tab_id if provided
366
+ if tab_id is not None:
367
+ location["tabId"] = tab_id
368
+
369
+ batch_update_data = {
370
+ "requests": [
371
+ {
372
+ "insertTable": {
373
+ "location": location,
374
+ "rows": rows,
375
+ "columns": columns,
376
+ }
377
+ }
378
+ ]
379
+ }
380
+
381
+ response = self._post(url, data=batch_update_data)
382
+ return self._handle_response(response)
383
+
384
+ def create_footer(
385
+ self,
386
+ document_id: str,
387
+ footer_type: str = "DEFAULT",
388
+ section_break_location_index: int = None,
389
+ section_break_segment_id: str = None,
390
+ section_break_tab_id: str = None,
391
+ ) -> dict[str, Any]:
392
+ """
393
+ Creates a Footer in a Google Document.
394
+
395
+ Args:
396
+ document_id: The unique identifier of the Google Document to be updated
397
+ footer_type: The type of footer to create (DEFAULT, HEADER_FOOTER_TYPE_UNSPECIFIED)
398
+ section_break_location_index: The index of the SectionBreak location (optional)
399
+ section_break_segment_id: The segment ID of the SectionBreak location (optional)
400
+ section_break_tab_id: The tab ID of the SectionBreak location (optional)
401
+
402
+ Returns:
403
+ A dictionary containing the Google Docs API response after performing the create footer operation
404
+
405
+ Raises:
406
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
407
+ RequestException: When there are network connectivity issues or API endpoint problems
408
+
409
+ Tags:
410
+ footer, create, document, api, google-docs, batch, content-management
411
+ """
412
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
413
+
414
+ # Build the create footer request
415
+ create_footer_request = {"type": footer_type}
416
+
417
+ # Add section break location if provided
418
+ if section_break_location_index is not None:
419
+ section_break_location = {"index": section_break_location_index}
420
+
421
+ if section_break_segment_id is not None:
422
+ section_break_location["segmentId"] = section_break_segment_id
423
+
424
+ if section_break_tab_id is not None:
425
+ section_break_location["tabId"] = section_break_tab_id
426
+
427
+ create_footer_request["sectionBreakLocation"] = section_break_location
428
+
429
+ batch_update_data = {"requests": [{"createFooter": create_footer_request}]}
430
+
431
+ response = self._post(url, data=batch_update_data)
432
+ return self._handle_response(response)
433
+
434
+ def create_footnote(
435
+ self,
436
+ document_id: str,
437
+ location_index: int = None,
438
+ location_segment_id: str = None,
439
+ location_tab_id: str = None,
440
+ end_of_segment_location: bool = False,
441
+ end_of_segment_segment_id: str = None,
442
+ end_of_segment_tab_id: str = None,
443
+ ) -> dict[str, Any]:
444
+ """
445
+ Creates a Footnote segment and inserts a new FootnoteReference at the given location.
446
+
447
+ Args:
448
+ document_id: The unique identifier of the Google Document to be updated
449
+ location_index: The index where to insert the footnote reference (optional)
450
+ location_segment_id: The segment ID for the location (optional, must be empty for body)
451
+ location_tab_id: The tab ID for the location (optional)
452
+ end_of_segment_location: Whether to insert at end of segment (optional)
453
+ end_of_segment_segment_id: The segment ID for end of segment location (optional)
454
+ end_of_segment_tab_id: The tab ID for end of segment location (optional)
455
+
456
+ Returns:
457
+ A dictionary containing the Google Docs API response after performing the create footnote operation
458
+
459
+ Raises:
460
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
461
+ RequestException: When there are network connectivity issues or API endpoint problems
462
+
463
+ Tags:
464
+ footnote, create, document, api, google-docs, batch, content-management
465
+ """
466
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
467
+
468
+ # Build the create footnote request
469
+ create_footnote_request = {}
470
+
471
+ if end_of_segment_location:
472
+ # Use endOfSegmentLocation
473
+ end_of_segment_location_obj = {}
474
+
475
+ if end_of_segment_segment_id is not None:
476
+ end_of_segment_location_obj["segmentId"] = end_of_segment_segment_id
477
+
478
+ if end_of_segment_tab_id is not None:
479
+ end_of_segment_location_obj["tabId"] = end_of_segment_tab_id
480
+
481
+ create_footnote_request["endOfSegmentLocation"] = (
482
+ end_of_segment_location_obj
483
+ )
484
+ else:
485
+ # Use specific location
486
+ location = {"index": location_index}
487
+
488
+ if location_segment_id is not None:
489
+ location["segmentId"] = location_segment_id
490
+
491
+ if location_tab_id is not None:
492
+ location["tabId"] = location_tab_id
493
+
494
+ create_footnote_request["location"] = location
495
+
496
+ batch_update_data = {"requests": [{"createFootnote": create_footnote_request}]}
497
+
498
+ response = self._post(url, data=batch_update_data)
499
+ return self._handle_response(response)
500
+
501
+ def delete_footer(
502
+ self,
503
+ document_id: str,
504
+ footer_id: str,
505
+ tab_id: str = None,
506
+ ) -> dict[str, Any]:
507
+ """
508
+ Deletes a Footer from the document.
509
+
510
+ Args:
511
+ document_id: The unique identifier of the Google Document to be updated
512
+ footer_id: The ID of the footer to delete
513
+ tab_id: The tab that contains the footer to delete (optional)
514
+
515
+ Returns:
516
+ A dictionary containing the Google Docs API response after performing the delete footer operation
517
+
518
+ Raises:
519
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
520
+ RequestException: When there are network connectivity issues or API endpoint problems
521
+
522
+ Tags:
523
+ footer, delete, remove, document, api, google-docs, batch, content-management
524
+ """
525
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
526
+
527
+ # Build the delete footer request
528
+ delete_footer_request = {"footerId": footer_id}
529
+
530
+ # Add tab_id if provided
531
+ if tab_id is not None:
532
+ delete_footer_request["tabId"] = tab_id
533
+
534
+ batch_update_data = {"requests": [{"deleteFooter": delete_footer_request}]}
535
+
536
+ response = self._post(url, data=batch_update_data)
537
+ return self._handle_response(response)
538
+
539
+ def create_header(
540
+ self,
541
+ document_id: str,
542
+ header_type: str = "DEFAULT",
543
+ section_break_location_index: int = None,
544
+ section_break_segment_id: str = None,
545
+ section_break_tab_id: str = None,
546
+ ) -> dict[str, Any]:
547
+ """
548
+ Creates a Header in a Google Document.
549
+
550
+ Args:
551
+ document_id: The unique identifier of the Google Document to be updated
552
+ header_type: The type of header to create (DEFAULT, HEADER_FOOTER_TYPE_UNSPECIFIED)
553
+ section_break_location_index: The index of the SectionBreak location (optional)
554
+ section_break_segment_id: The segment ID of the SectionBreak location (optional)
555
+ section_break_tab_id: The tab ID of the SectionBreak location (optional)
556
+
557
+ Returns:
558
+ A dictionary containing the Google Docs API response after performing the create header operation
559
+
560
+ Raises:
561
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
562
+ RequestException: When there are network connectivity issues or API endpoint problems
563
+
564
+ Tags:
565
+ header, create, document, api, google-docs, batch, content-management, important
566
+ """
567
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
568
+
569
+ # Build the create header request
570
+ create_header_request = {"type": header_type}
571
+
572
+ # Add section break location if provided
573
+ if section_break_location_index is not None:
574
+ section_break_location = {"index": section_break_location_index}
575
+
576
+ if section_break_segment_id is not None:
577
+ section_break_location["segmentId"] = section_break_segment_id
578
+
579
+ if section_break_tab_id is not None:
580
+ section_break_location["tabId"] = section_break_tab_id
581
+
582
+ create_header_request["sectionBreakLocation"] = section_break_location
583
+
584
+ batch_update_data = {"requests": [{"createHeader": create_header_request}]}
585
+
586
+ response = self._post(url, data=batch_update_data)
587
+ return self._handle_response(response)
588
+
589
+ def delete_header(
590
+ self,
591
+ document_id: str,
592
+ header_id: str,
593
+ tab_id: str = None,
594
+ ) -> dict[str, Any]:
595
+ """
596
+ Deletes a Header from the document.
597
+
598
+ Args:
599
+ document_id: The unique identifier of the Google Document to be updated
600
+ header_id: The ID of the header to delete
601
+ tab_id: The tab containing the header to delete (optional)
602
+
603
+ Returns:
604
+ A dictionary containing the Google Docs API response after performing the delete header operation
605
+
606
+ Raises:
607
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
608
+ RequestException: When there are network connectivity issues or API endpoint problems
609
+
610
+ Tags:
611
+ header, delete, remove, document, api, google-docs, batch, content-management
612
+ """
613
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
614
+
615
+ # Build the delete header request
616
+ delete_header_request = {"headerId": header_id}
617
+
618
+ # Add tab_id if provided
619
+ if tab_id is not None:
620
+ delete_header_request["tabId"] = tab_id
621
+
622
+ batch_update_data = {"requests": [{"deleteHeader": delete_header_request}]}
623
+
624
+ response = self._post(url, data=batch_update_data)
625
+ return self._handle_response(response)
626
+
627
+ def create_paragraph_bullets(
628
+ self,
629
+ document_id: str,
630
+ start_index: int,
631
+ end_index: int,
632
+ bullet_preset: str,
633
+ segment_id: str = None,
634
+ tab_id: str = None,
635
+ ) -> dict[str, Any]:
636
+ """
637
+ Creates bullets for all of the paragraphs that overlap with the given range.
638
+
639
+ Args:
640
+ document_id: The unique identifier of the Google Document to be updated
641
+ start_index: The zero-based start index of the range to apply bullets to
642
+ end_index: The zero-based end index of the range to apply bullets to (exclusive)
643
+ bullet_preset: The kind of bullet glyphs to use. Available options:
644
+ - BULLET_GLYPH_PRESET_UNSPECIFIED: The bullet glyph preset is unspecified
645
+ - BULLET_DISC_CIRCLE_SQUARE: DISC, CIRCLE and SQUARE for first 3 nesting levels
646
+ - BULLET_DIAMONDX_ARROW3D_SQUARE: DIAMONDX, ARROW3D and SQUARE for first 3 nesting levels
647
+ - BULLET_CHECKBOX: CHECKBOX bullet glyphs for all nesting levels
648
+ - BULLET_ARROW_DIAMOND_DISC: ARROW, DIAMOND and DISC for first 3 nesting levels
649
+ - BULLET_STAR_CIRCLE_SQUARE: STAR, CIRCLE and SQUARE for first 3 nesting levels
650
+ - BULLET_ARROW3D_CIRCLE_SQUARE: ARROW3D, CIRCLE and SQUARE for first 3 nesting levels
651
+ - BULLET_LEFTTRIANGLE_DIAMOND_DISC: LEFTTRIANGLE, DIAMOND and DISC for first 3 nesting levels
652
+ - BULLET_DIAMONDX_HOLLOWDIAMOND_SQUARE: DIAMONDX, HOLLOWDIAMOND and SQUARE for first 3 nesting levels
653
+ - BULLET_DIAMOND_CIRCLE_SQUARE: DIAMOND, CIRCLE and SQUARE for first 3 nesting levels
654
+ - NUMBERED_DECIMAL_ALPHA_ROMAN: DECIMAL, ALPHA and ROMAN with periods
655
+ - NUMBERED_DECIMAL_ALPHA_ROMAN_PARENS: DECIMAL, ALPHA and ROMAN with parenthesis
656
+ - NUMBERED_DECIMAL_NESTED: DECIMAL with nested numbering (1., 1.1., 2., 2.2.)
657
+ - NUMBERED_UPPERALPHA_ALPHA_ROMAN: UPPERALPHA, ALPHA and ROMAN with periods
658
+ - NUMBERED_UPPERROMAN_UPPERALPHA_DECIMAL: UPPERROMAN, UPPERALPHA and DECIMAL with periods
659
+ - NUMBERED_ZERODECIMAL_ALPHA_ROMAN: ZERODECIMAL, ALPHA and ROMAN with periods
660
+ segment_id: The segment ID for the range (optional)
661
+ tab_id: The tab ID for the range (optional)
662
+
663
+ Returns:
664
+ A dictionary containing the Google Docs API response after performing the create bullets operation
665
+
666
+ Raises:
667
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
668
+ RequestException: When there are network connectivity issues or API endpoint problems
669
+
670
+ Tags:
671
+ bullets, list, paragraph, document, api, google-docs, batch, content-management
672
+ """
673
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
674
+
675
+ # Build the range object
676
+ range_obj = {"startIndex": start_index, "endIndex": end_index}
677
+
678
+ # Add optional parameters if provided
679
+ if segment_id is not None:
680
+ range_obj["segmentId"] = segment_id
681
+ if tab_id is not None:
682
+ range_obj["tabId"] = tab_id
683
+
684
+ batch_update_data = {
685
+ "requests": [
686
+ {
687
+ "createParagraphBullets": {
688
+ "range": range_obj,
689
+ "bulletPreset": bullet_preset,
690
+ }
691
+ }
692
+ ]
693
+ }
694
+
695
+ response = self._post(url, data=batch_update_data)
696
+ return self._handle_response(response)
697
+
698
+ def delete_paragraph_bullets(
699
+ self,
700
+ document_id: str,
701
+ start_index: int,
702
+ end_index: int,
703
+ segment_id: str = None,
704
+ tab_id: str = None,
705
+ ) -> dict[str, Any]:
706
+ """
707
+ Deletes bullets from all of the paragraphs that overlap with the given range.
708
+
709
+ Args:
710
+ document_id: The unique identifier of the Google Document to be updated
711
+ start_index: The zero-based start index of the range to remove bullets from
712
+ end_index: The zero-based end index of the range to remove bullets from (exclusive)
713
+ segment_id: The segment ID for the range (optional)
714
+ tab_id: The tab ID for the range (optional)
715
+
716
+ Returns:
717
+ A dictionary containing the Google Docs API response after performing the delete bullets operation
718
+
719
+ Raises:
720
+ HTTPError: When the API request fails, such as invalid document_id or insufficient permissions
721
+ RequestException: When there are network connectivity issues or API endpoint problems
722
+
723
+ Tags:
724
+ bullets, delete, remove, list, paragraph, document, api, google-docs, batch, content-management
725
+ """
726
+ url = f"{self.base_api_url}/{document_id}:batchUpdate"
727
+
728
+ # Build the range object
729
+ range_obj = {"startIndex": start_index, "endIndex": end_index}
730
+
731
+ # Add optional parameters if provided
732
+ if segment_id is not None:
733
+ range_obj["segmentId"] = segment_id
734
+ if tab_id is not None:
735
+ range_obj["tabId"] = tab_id
736
+
737
+ batch_update_data = {
738
+ "requests": [{"deleteParagraphBullets": {"range": range_obj}}]
739
+ }
740
+
741
+ response = self._post(url, data=batch_update_data)
742
+ return self._handle_response(response)
743
+
744
+ def list_tools(self):
745
+ return [
746
+ self.create_document,
747
+ self.get_document,
748
+ self.add_content,
749
+ self.style_text,
750
+ self.delete_content,
751
+ self.insert_table,
752
+ self.create_footer,
753
+ self.create_footnote,
754
+ self.delete_footer,
755
+ self.create_header,
756
+ self.delete_header,
757
+ self.create_paragraph_bullets,
758
+ self.delete_paragraph_bullets,
759
+ self.update_paragraph_style,
760
+ ]