universal-mcp-applications 0.1.12__tar.gz → 0.1.14__tar.gz

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.

Files changed (286) hide show
  1. universal_mcp_applications-0.1.14/GEMINI.md +125 -0
  2. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/PKG-INFO +2 -2
  3. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/bump_and_release.sh +0 -1
  4. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/pyproject.toml +2 -2
  5. universal_mcp_applications-0.1.14/src/scripts/docgen.py +516 -0
  6. universal_mcp_applications-0.1.14/src/scripts/prompts.py +28 -0
  7. universal_mcp_applications-0.1.14/src/scripts/run_docgen.py +65 -0
  8. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/aws_s3/app.py +71 -71
  9. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/calendly/app.py +199 -199
  10. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/canva/app.py +189 -189
  11. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/domain_checker/app.py +31 -24
  12. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/e2b/app.py +6 -7
  13. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/elevenlabs/app.py +24 -20
  14. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/exa/app.py +25 -20
  15. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/falai/app.py +44 -41
  16. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/file_system/app.py +20 -12
  17. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/firecrawl/app.py +46 -47
  18. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fireflies/app.py +79 -79
  19. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/app.py +83 -74
  20. universal_mcp_applications-0.1.14/src/universal_mcp/applications/github/README.md +21 -0
  21. universal_mcp_applications-0.1.14/src/universal_mcp/applications/github/app.py +429 -0
  22. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_calendar/app.py +63 -65
  23. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_docs/app.py +78 -78
  24. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_drive/app.py +361 -440
  25. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_gemini/app.py +34 -17
  26. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_mail/app.py +164 -118
  27. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_searchconsole/app.py +41 -47
  28. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_sheet/app.py +157 -164
  29. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/http_tools/app.py +16 -16
  30. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/linkedin/app.py +26 -31
  31. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ms_teams/app.py +190 -190
  32. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/openai/app.py +55 -56
  33. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/outlook/app.py +57 -57
  34. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/perplexity/app.py +17 -17
  35. universal_mcp_applications-0.1.14/src/universal_mcp/applications/reddit/app.py +836 -0
  36. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/replicate/app.py +40 -42
  37. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/resend/app.py +157 -154
  38. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/scraper/app.py +24 -24
  39. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/serpapi/app.py +18 -20
  40. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sharepoint/app.py +46 -36
  41. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/slack/app.py +66 -66
  42. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/tavily/app.py +7 -7
  43. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/compliance_api.py +17 -20
  44. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/dm_conversations_api.py +35 -40
  45. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/dm_events_api.py +18 -21
  46. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/likes_api.py +19 -22
  47. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/lists_api.py +59 -68
  48. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/spaces_api.py +36 -42
  49. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/trends_api.py +7 -8
  50. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/tweets_api.py +159 -185
  51. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/usage_api.py +5 -6
  52. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/users_api.py +230 -264
  53. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/unipile/app.py +99 -105
  54. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp/app.py +86 -82
  55. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp_business/app.py +147 -147
  56. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/youtube/app.py +290 -290
  57. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/zenquotes/app.py +6 -6
  58. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/uv.lock +2 -2
  59. universal_mcp_applications-0.1.12/src/universal_mcp/applications/github/README.md +0 -1049
  60. universal_mcp_applications-0.1.12/src/universal_mcp/applications/github/app.py +0 -50601
  61. universal_mcp_applications-0.1.12/src/universal_mcp/applications/reddit/app.py +0 -4664
  62. universal_mcp_applications-0.1.12/test.py +0 -43
  63. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/.gitignore +0 -0
  64. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/LICENSE +0 -0
  65. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/README.md +0 -0
  66. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/examples/children_story_builder.py +0 -0
  67. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/tests/test_applications.py +0 -0
  68. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ahrefs/README.md +0 -0
  69. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ahrefs/__init__.py +0 -0
  70. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ahrefs/app.py +0 -0
  71. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/airtable/README.md +0 -0
  72. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/airtable/__init__.py +0 -0
  73. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/airtable/app.py +0 -0
  74. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/apollo/README.md +0 -0
  75. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/apollo/__init__.py +0 -0
  76. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/apollo/app.py +0 -0
  77. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/asana/README.md +0 -0
  78. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/asana/__init__.py +0 -0
  79. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/asana/app.py +0 -0
  80. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/aws_s3/README.md +0 -0
  81. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/aws_s3/__init__.py +0 -0
  82. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/bill/README.md +0 -0
  83. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/bill/__init__.py +0 -0
  84. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/bill/app.py +0 -0
  85. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/box/README.md +0 -0
  86. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/box/__init__.py +0 -0
  87. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/box/app.py +0 -0
  88. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/braze/README.md +0 -0
  89. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/braze/__init__.py +0 -0
  90. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/braze/app.py +0 -0
  91. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/cal_com_v2/README.md +0 -0
  92. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/cal_com_v2/__init__.py +0 -0
  93. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/cal_com_v2/app.py +0 -0
  94. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/calendly/README.md +0 -0
  95. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/calendly/__init__.py +0 -0
  96. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/canva/README.md +0 -0
  97. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/canva/__init__.py +0 -0
  98. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/clickup/README.md +0 -0
  99. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/clickup/__init__.py +0 -0
  100. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/clickup/app.py +0 -0
  101. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/coda/README.md +0 -0
  102. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/coda/__init__.py +0 -0
  103. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/coda/app.py +0 -0
  104. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/confluence/README.md +0 -0
  105. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/confluence/__init__.py +0 -0
  106. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/confluence/app.py +0 -0
  107. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/contentful/README.md +0 -0
  108. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/contentful/__init__.py +0 -0
  109. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/contentful/app.py +0 -0
  110. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/crustdata/README.md +0 -0
  111. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/crustdata/__init__.py +0 -0
  112. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/crustdata/app.py +0 -0
  113. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/dialpad/README.md +0 -0
  114. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/dialpad/__init__.py +0 -0
  115. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/dialpad/app.py +0 -0
  116. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/digitalocean/README.md +0 -0
  117. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/digitalocean/__init__.py +0 -0
  118. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/digitalocean/app.py +0 -0
  119. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/domain_checker/README.md +0 -0
  120. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/domain_checker/__init__.py +0 -0
  121. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/e2b/README.md +0 -0
  122. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/e2b/__init__.py +0 -0
  123. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/elevenlabs/README.md +0 -0
  124. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/elevenlabs/__init__.py +0 -0
  125. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/exa/README.md +0 -0
  126. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/exa/__init__.py +0 -0
  127. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/falai/README.md +0 -0
  128. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/falai/__init__.py +0 -0
  129. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/figma/README.md +0 -0
  130. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/figma/__init__.py +0 -0
  131. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/figma/app.py +0 -0
  132. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/file_system/__init__.py +0 -0
  133. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/firecrawl/README.md +0 -0
  134. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/firecrawl/__init__.py +0 -0
  135. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fireflies/README.md +0 -0
  136. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fireflies/__init__.py +0 -0
  137. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/README.md +0 -0
  138. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/__init__.py +0 -0
  139. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/utils/api.py +0 -0
  140. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/utils/fixtures.py +0 -0
  141. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/utils/helper.py +0 -0
  142. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/utils/league_utils.py +0 -0
  143. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/fpl/utils/position_utils.py +0 -0
  144. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ghost_content/README.md +0 -0
  145. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ghost_content/__init__.py +0 -0
  146. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ghost_content/app.py +0 -0
  147. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/github/__init__.py +0 -0
  148. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/gong/README.md +0 -0
  149. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/gong/__init__.py +0 -0
  150. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/gong/app.py +0 -0
  151. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_calendar/README.md +0 -0
  152. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_calendar/__init__.py +0 -0
  153. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_docs/README.md +0 -0
  154. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_docs/__init__.py +0 -0
  155. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_drive/README.md +0 -0
  156. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_drive/__init__.py +0 -0
  157. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_gemini/README.md +0 -0
  158. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_gemini/__init__.py +0 -0
  159. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_mail/README.md +0 -0
  160. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_mail/__init__.py +0 -0
  161. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_searchconsole/README.md +0 -0
  162. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_searchconsole/__init__.py +0 -0
  163. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_sheet/README.md +0 -0
  164. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_sheet/__init__.py +0 -0
  165. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/google_sheet/helper.py +0 -0
  166. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hashnode/README.md +0 -0
  167. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hashnode/__init__.py +0 -0
  168. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hashnode/app.py +0 -0
  169. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/heygen/README.md +0 -0
  170. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/heygen/__init__.py +0 -0
  171. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/heygen/app.py +0 -0
  172. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/http_tools/README.md +0 -0
  173. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/http_tools/__init__.py +0 -0
  174. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hubspot/README.md +0 -0
  175. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hubspot/__init__.py +0 -0
  176. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/hubspot/app.py +0 -0
  177. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/jira/README.md +0 -0
  178. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/jira/__init__.py +0 -0
  179. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/jira/app.py +0 -0
  180. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/klaviyo/README.md +0 -0
  181. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/klaviyo/__init__.py +0 -0
  182. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/klaviyo/app.py +0 -0
  183. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/linkedin/README.md +0 -0
  184. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/linkedin/__init__.py +0 -0
  185. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/mailchimp/README.md +0 -0
  186. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/mailchimp/__init__.py +0 -0
  187. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/mailchimp/app.py +0 -0
  188. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/markitdown/README.md +0 -0
  189. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/markitdown/__init__.py +0 -0
  190. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/markitdown/app.py +0 -0
  191. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/miro/README.md +0 -0
  192. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/miro/__init__.py +0 -0
  193. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/miro/app.py +0 -0
  194. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ms_teams/README.md +0 -0
  195. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/ms_teams/__init__.py +0 -0
  196. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/neon/README.md +0 -0
  197. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/neon/__init__.py +0 -0
  198. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/neon/app.py +0 -0
  199. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/notion/README.md +0 -0
  200. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/notion/__init__.py +0 -0
  201. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/notion/app.py +0 -0
  202. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/openai/README.md +0 -0
  203. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/openai/__init__.py +0 -0
  204. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/outlook/README.md +0 -0
  205. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/outlook/__init__.py +0 -0
  206. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/perplexity/README.md +0 -0
  207. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/perplexity/__init__.py +0 -0
  208. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/pipedrive/README.md +0 -0
  209. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/pipedrive/__init__.py +0 -0
  210. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/pipedrive/app.py +0 -0
  211. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/posthog/README.md +0 -0
  212. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/posthog/__init__.py +0 -0
  213. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/posthog/app.py +0 -0
  214. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/reddit/README.md +0 -0
  215. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/reddit/__init__.py +0 -0
  216. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/replicate/README.md +0 -0
  217. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/replicate/__init__.py +0 -0
  218. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/resend/README.md +0 -0
  219. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/resend/__init__.py +0 -0
  220. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/retell/README.md +0 -0
  221. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/retell/__init__.py +0 -0
  222. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/retell/app.py +0 -0
  223. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/rocketlane/README.md +0 -0
  224. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/rocketlane/__init__.py +0 -0
  225. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/rocketlane/app.py +0 -0
  226. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/scraper/README.md +0 -0
  227. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/scraper/__init__.py +0 -0
  228. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semanticscholar/README.md +0 -0
  229. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semanticscholar/__init__.py +0 -0
  230. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semanticscholar/app.py +0 -0
  231. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semrush/README.md +0 -0
  232. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semrush/__init__.py +0 -0
  233. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/semrush/app.py +0 -0
  234. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sendgrid/README.md +0 -0
  235. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sendgrid/__init__.py +0 -0
  236. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sendgrid/app.py +0 -0
  237. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sentry/README.md +0 -0
  238. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sentry/__init__.py +0 -0
  239. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sentry/app.py +0 -0
  240. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/serpapi/README.md +0 -0
  241. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/serpapi/__init__.py +0 -0
  242. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sharepoint/README.md +0 -0
  243. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/sharepoint/__init__.py +0 -0
  244. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shopify/README.md +0 -0
  245. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shopify/__init__.py +0 -0
  246. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shopify/app.py +0 -0
  247. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shortcut/README.md +0 -0
  248. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shortcut/__init__.py +0 -0
  249. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/shortcut/app.py +0 -0
  250. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/slack/README.md +0 -0
  251. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/slack/__init__.py +0 -0
  252. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/spotify/README.md +0 -0
  253. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/spotify/__init__.py +0 -0
  254. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/spotify/app.py +0 -0
  255. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/supabase/README.md +0 -0
  256. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/supabase/__init__.py +0 -0
  257. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/supabase/app.py +0 -0
  258. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/tavily/README.md +0 -0
  259. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/tavily/__init__.py +0 -0
  260. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/trello/README.md +0 -0
  261. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/trello/__init__.py +0 -0
  262. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/trello/app.py +0 -0
  263. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twilio/README.md +0 -0
  264. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twilio/__init__.py +0 -0
  265. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twilio/app.py +0 -0
  266. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/README.md +0 -0
  267. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/__init__.py +0 -0
  268. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/__init__.py +0 -0
  269. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/api_segment_base.py +0 -0
  270. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/api_segments/openapi_json_api.py +0 -0
  271. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/twitter/app.py +0 -0
  272. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/unipile/README.md +0 -0
  273. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/unipile/__init__.py +0 -0
  274. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp/README.md +0 -0
  275. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp/__init__.py +0 -0
  276. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp/audio.py +0 -0
  277. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp/whatsapp.py +0 -0
  278. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp_business/README.md +0 -0
  279. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/whatsapp_business/__init__.py +0 -0
  280. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/wrike/README.md +0 -0
  281. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/wrike/__init__.py +0 -0
  282. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/wrike/app.py +0 -0
  283. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/youtube/README.md +0 -0
  284. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/youtube/__init__.py +0 -0
  285. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/zenquotes/README.md +0 -0
  286. {universal_mcp_applications-0.1.12 → universal_mcp_applications-0.1.14}/src/universal_mcp/applications/zenquotes/__init__.py +0 -0
@@ -0,0 +1,125 @@
1
+ # Agent.md — Python + uv
2
+
3
+ Purpose
4
+ - This repository uses Python managed by uv for dependency resolution, virtual environments, locking, and execution. Always prefer uv subcommands (add/remove/run/sync/export) over raw pip/venv commands.
5
+
6
+ Core rules
7
+ - Use `uv add` to add or upgrade dependencies so that both `pyproject.toml` and `uv.lock` stay in sync; do not use `pip install` directly.
8
+ - Keep runtime dependencies in `[project.dependencies]` and development-only tools in the `dev` group via `uv add --dev ...`.
9
+ - Use `uv run` to execute Python, test, and tooling commands without manually activating a virtual environment.
10
+
11
+ Project bootstrap
12
+ - New project (scaffold files): `uv init`
13
+ - First install or clean install: `uv sync`
14
+ - Run the app: `uv run python -m <your_module>` or `uv run main.py`
15
+ - REPL: `uv run python`
16
+ - Scripts in pyproject: prefer `uv run <command>` to ensure the correct environment is used
17
+
18
+ Managing dependencies
19
+ - Add runtime dependency: `uv add <name>` (e.g., `uv add httpx`)
20
+ - Add dev dependencies: `uv add --dev pytest ruff`
21
+ - Pin/upgrade by constraint: `uv add "httpx>=0.27"` or adjust `pyproject.toml` and then `uv sync`
22
+ - Remove dependency: `uv remove <name>`
23
+ - Export lock for external tooling: `uv export --format requirements-txt --output-file requirements.txt`
24
+
25
+ Locking and environments
26
+ - `uv run` and `uv sync` will ensure the environment matches `pyproject.toml` and `uv.lock`
27
+ - Avoid manual `pip install` or manual `venv` activation; let uv manage the environment
28
+ - Commit `uv.lock` to version control for reproducible installs
29
+
30
+ pyproject guidance
31
+ - Dependencies live under `[project]` → `dependencies = [...]`
32
+ - Development-only tooling should go under a dev group (e.g., `uv add --dev ruff pytest`) for clean separation
33
+ - Keep `requires-python` current (e.g., `>=3.12`) to match the team’s baseline
34
+
35
+ Usage in this repo
36
+ - When adding libraries or changing versions, propose `uv add ...` changes that update both `pyproject.toml` and `uv.lock`, then run `uv run pytest -q` to validate
37
+ - Prefer minimal diffs, explain the plan, apply changes, and run tests/tooling via `uv run`
38
+ - If build/test fails, inspect error context, adjust constraints or code, and re-run via `uv run`
39
+
40
+ Common commands (copy/paste)
41
+ - Initialize: `uv init` | Install deps: `uv sync`
42
+ - Add runtime: `uv add <pkg>` | Add dev: `uv add --dev <pkg>`
43
+ - Remove: `uv remove <pkg>`
44
+ - Run app: `uv run python -m <your_module>` or `uv run main.py`
45
+ - Tests: `uv run pytest -q`
46
+ - Lint/format: `uv run ruff check .` and/or `uv run ruff format .`
47
+ - Export: `uv export --format requirements-txt --output-file requirements.txt`
48
+
49
+ Of course. Based on your request and the example `app.py` you provided, here is a new section that you can append to your `gemini.md` file. This section provides clear guidance on how to write effective tool names and descriptions, using the Perplexity `chat` function as a concrete example.
50
+
51
+ The proposed changes will make the function's purpose much clearer, especially its ability to access and cite real-time web information, which is a key feature.
52
+
53
+ ***
54
+
55
+ ### Tool Function Naming and Descriptions
56
+
57
+ To ensure the AI agent can effectively understand and use the tools available, function names and their descriptions (docstrings) must be clear, descriptive, and accurate. A good description outlines the tool's purpose, its key capabilities, and what it returns.
58
+
59
+ **Core Principles:**
60
+ - **Use Action-Oriented Names:** Function names should be verbs that clearly state what the tool *does* (e.g., `search`, `create_file`, `list_users`).
61
+ - **Be Specific in Descriptions:** The docstring is the primary source of context for the AI. It should explicitly mention the service it interacts with (e.g., "Perplexity AI") and its unique features (e.g., "performs real-time web searches," "provides citations").
62
+ - **Detail Inputs and Outputs:** Clearly describe the purpose of each argument and what the function returns, as this helps the agent formulate correct calls.
63
+
64
+ **Example: Improving the Perplexity Tool**
65
+
66
+ Let's refine the tool in `app.py` to be more descriptive and unlock its full potential. The original `chat` function is too generic. We will rename it to `search` and significantly improve its docstring.
67
+
68
+ **BEFORE:** The original function name and description are too simple.
69
+
70
+ ```python
71
+ # from app.py
72
+ def chat(
73
+ self,
74
+ query: str,
75
+ model: Literal[...] = "sonar",
76
+ temperature: float = 1,
77
+ system_prompt: str = "Be precise and concise.",
78
+ ) -> dict[str, Any] | str:
79
+ """
80
+ Initiates a chat completion request to generate AI responses using various models with customizable parameters.
81
+ ...
82
+ Tags:
83
+ chat, generate, ai, completion, important
84
+ """
85
+ ```
86
+
87
+ **AFTER:** The updated name and description are highly specific, highlighting the core web search and citation capabilities. Do not leave any empty lines between the descriptions.
88
+
89
+ ```python
90
+ # from app.py
91
+ def search(
92
+ self,
93
+ query: str,
94
+ model: Literal[
95
+ "r1-1776",
96
+ "sonar",
97
+ "sonar-pro",
98
+ "sonar-reasoning",
99
+ "sonar-reasoning-pro",
100
+ "sonar-deep-research",
101
+ ] = "sonar-pro",
102
+ temperature: float = 1,
103
+ system_prompt: str = "You are a helpful AI assistant that answers questions using real-time information from the web.",
104
+ ) -> dict[str, Any] | str:
105
+ """
106
+ Performs a real-time web search using Perplexity AI to answer a query with up-to-date information and citations.
107
+ This tool is ideal for questions about current events, facts, or any topic that requires access to the latest information from the internet. It returns a natural language answer along with the sources used.
108
+
109
+ Args:
110
+ query: The search query or question to ask. For example: "What are the latest developments in AI regulation?"
111
+ model: The Perplexity model to use. 'sonar-pro' is recommended for comprehensive, up-to-date answers.
112
+ temperature: Controls randomness in the model's output. Higher values make the output more random, lower values make it more deterministic. Defaults to 1.
113
+ system_prompt: The initial system message to guide the model's behavior.
114
+
115
+ Returns:
116
+ A dictionary containing the generated 'content' (str) and a list of 'citations' (list) from the web search.
117
+
118
+ Raises:
119
+ AuthenticationError: Raised when API authentication fails due to missing or invalid credentials.
120
+ HTTPError: Raised when the API request fails or returns an error status.
121
+
122
+ Tags:
123
+ search, web, research, citations, current events, important
124
+ """
125
+ ```
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: universal-mcp-applications
3
- Version: 0.1.12
3
+ Version: 0.1.14
4
4
  Summary: A Universal MCP Application: universal_mcp_applications
5
5
  Project-URL: Homepage, https://github.com/universal-mcp/applications
6
6
  Project-URL: Repository, https://github.com/universal-mcp/applications
@@ -22,7 +22,7 @@ Requires-Dist: google-genai>=1.33.0
22
22
  Requires-Dist: google-search-results>=2.4.2
23
23
  Requires-Dist: gql[all]>=3.5.2
24
24
  Requires-Dist: httpx-aiohttp>=0.1.8
25
- Requires-Dist: markitdown[audio-transcription,az-doc-intel,docx,outlook,pdf,pptx,xls,xlsx]==0.1.3
25
+ Requires-Dist: markitdown[audio-transcription,az-doc-intel,docx,outlook,pdf,pptx,xls,xlsx]>=0.1.3
26
26
  Requires-Dist: office365-rest-python-client>=2.6.2
27
27
  Requires-Dist: openai>=1.75.0
28
28
  Requires-Dist: pyairtable>=3.1.1
@@ -81,7 +81,6 @@ if [ "$1" = "release" ]; then
81
81
  rm -rf .pytest_cache
82
82
  rm -rf .ruff_cache
83
83
  rm -rf .mypy_cache
84
- rm -rf .venv
85
84
  rm -rf .cache
86
85
  rm -rf .DS_Store
87
86
  rm -rf .idea
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "universal-mcp-applications"
9
- version = "0.1.12"
9
+ version = "0.1.14"
10
10
  description = "A Universal MCP Application: universal_mcp_applications"
11
11
  readme = "README.md"
12
12
  requires-python = ">=3.11"
@@ -30,7 +30,7 @@ dependencies = [
30
30
  "google-search-results>=2.4.2",
31
31
  "gql[all]>=3.5.2",
32
32
  "httpx-aiohttp>=0.1.8",
33
- "markitdown[audio-transcription,az-doc-intel,docx,outlook,pdf,pptx,xls,xlsx]==0.1.3",
33
+ "markitdown[audio-transcription,az-doc-intel,docx,outlook,pdf,pptx,xls,xlsx]>=0.1.3",
34
34
  "office365-rest-python-client>=2.6.2",
35
35
  "openai>=1.75.0",
36
36
  "pyairtable>=3.1.1",
@@ -0,0 +1,516 @@
1
+ """Docstring generator using litellm with structured output.
2
+
3
+ This module provides a simple way to generate docstrings and suggest improved
4
+ names for Python functions using LLMs with structured output.
5
+ """
6
+
7
+ import ast
8
+ import json
9
+ import os
10
+ from pathlib import Path
11
+ import re
12
+ import sys
13
+ import time
14
+ import traceback
15
+ from typing import Optional
16
+
17
+ import typer
18
+ from rich.console import Console
19
+
20
+ console = Console()
21
+
22
+ import litellm
23
+ from pydantic import BaseModel, Field
24
+
25
+ # --- CHANGE 1: Import prompts from the new prompts.py file ---
26
+ from src.scripts.prompts import SYSTEM_PROMPT_TEMPLATE, USER_PROMPT_TEMPLATE
27
+
28
+
29
+ class DescriptionOutput(BaseModel):
30
+ """Structure for the generated description output."""
31
+
32
+ description: str = Field(description="A clear, detailed description of what the function does")
33
+ suggested_name: Optional[str] = Field(None, description="A better name for the function, if applicable")
34
+
35
+
36
+ class FunctionExtractor(ast.NodeVisitor):
37
+ """
38
+ An AST node visitor that collects the source code of all function
39
+ and method definitions within a Python script.
40
+ """
41
+
42
+ def __init__(self, source_code: str):
43
+ self.source_lines = source_code.splitlines(keepends=True)
44
+ self.functions: list[tuple[str, str]] = [] # Store tuples of (function_name, function_source)
45
+
46
+ def _get_source_segment(self, node: ast.AST) -> str | None:
47
+ """Safely extracts the source segment for a node using ast.get_source_segment."""
48
+ try:
49
+ source_segment = ast.get_source_segment("".join(self.source_lines), node)
50
+ return source_segment
51
+ except Exception as e:
52
+ print(
53
+ f"Warning: Could not retrieve source for node {getattr(node, 'name', 'unknown')} at line {getattr(node, 'lineno', 'unknown')}: {e}"
54
+ )
55
+ return None
56
+
57
+ def visit_FunctionDef(self, node: ast.FunctionDef):
58
+ """Visits a regular function definition and collects it if not excluded."""
59
+ if not node.name.startswith("_") and node.name != "list_tools":
60
+ source_code = self._get_source_segment(node)
61
+ if source_code:
62
+ self.functions.append((node.name, source_code))
63
+ self.generic_visit(node)
64
+
65
+ def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef):
66
+ """Visits an asynchronous function definition and collects it if not excluded."""
67
+ if not node.name.startswith("_") and node.name != "list_tools":
68
+ source_code = self._get_source_segment(node)
69
+ if source_code:
70
+ self.functions.append((node.name, source_code))
71
+ self.generic_visit(node)
72
+
73
+
74
+ def extract_functions_from_script(file_path: str) -> list[tuple[str, str]]:
75
+ """
76
+ Reads a Python script and extracts the source code of all functions.
77
+
78
+ Args:
79
+ file_path: The path to the Python (.py) script.
80
+
81
+ Returns:
82
+ A list of tuples, where each tuple contains the function name (str)
83
+ and its full source code (str), including decorators.
84
+ Returns an empty list if the file cannot be read, parsed, or contains no functions.
85
+
86
+ Raises:
87
+ FileNotFoundError: If the file_path does not exist.
88
+ SyntaxError: If the file contains invalid Python syntax.
89
+ Exception: For other potential I/O or AST processing errors.
90
+ """
91
+ try:
92
+ with open(file_path, encoding="utf-8") as f:
93
+ source_code = f.read()
94
+ except FileNotFoundError:
95
+ print(f"Error: File not found at {file_path}")
96
+ raise
97
+ except Exception as e:
98
+ print(f"Error reading file {file_path}: {e}")
99
+ raise
100
+
101
+ try:
102
+ tree = ast.parse(source_code, filename=file_path)
103
+ except SyntaxError as e:
104
+ print(f"Error: Invalid Python syntax in {file_path} at line {e.lineno}, offset {e.offset}: {e.msg}")
105
+ raise
106
+ except Exception as e:
107
+ print(f"Error parsing {file_path} into AST: {e}")
108
+ raise
109
+
110
+ try:
111
+ extractor = FunctionExtractor(source_code)
112
+ extractor.visit(tree)
113
+
114
+ if not extractor.functions:
115
+ print("Warning: No functions found in the file.")
116
+
117
+ return extractor.functions
118
+ except Exception as e:
119
+ print(f"Error during function extraction: {e}")
120
+ import traceback
121
+
122
+ traceback.print_exc()
123
+ return []
124
+
125
+
126
+ def extract_json_from_text(text):
127
+ """Extract valid JSON from text that might contain additional content.
128
+
129
+ Args:
130
+ text: Raw text response from the model
131
+
132
+ Returns:
133
+ Dict containing the extracted JSON data
134
+
135
+ Raises:
136
+ ValueError: If no valid JSON could be extracted
137
+ """
138
+ json_match = re.search(r"```(?:json)?\s*([\s\S]*?)\s*```", text)
139
+ if json_match:
140
+ try:
141
+ return json.loads(json_match.group(1))
142
+ except json.JSONDecodeError:
143
+ pass
144
+
145
+ try:
146
+ start = text.find("{")
147
+ if start >= 0:
148
+ brace_count = 0
149
+ for i in range(start, len(text)):
150
+ if text[i] == "{":
151
+ brace_count += 1
152
+ elif text[i] == "}":
153
+ brace_count -= 1
154
+ if brace_count == 0:
155
+ return json.loads(text[start : i + 1])
156
+ except json.JSONDecodeError:
157
+ pass
158
+
159
+ try:
160
+ return json.loads(text)
161
+ except json.JSONDecodeError as e:
162
+ raise ValueError("Could not extract valid JSON from the response") from e
163
+
164
+
165
+ def parse_existing_docstring(docstring: str | None) -> tuple[str, str]:
166
+ """
167
+ Parses an existing docstring to separate the summary from the rest.
168
+
169
+ Args:
170
+ docstring: The existing docstring string.
171
+
172
+ Returns:
173
+ A tuple containing (summary, rest_of_docstring).
174
+ 'rest_of_docstring' will include Args, Returns, etc.
175
+ """
176
+ if not docstring:
177
+ return "", ""
178
+
179
+ lines = docstring.strip().split('\n')
180
+ summary_lines = []
181
+ rest_lines = []
182
+ summary_done = False
183
+
184
+ # Sections that mark the end of the summary
185
+ section_markers = ("Args:", "Returns:", "Raises:", "Tags:", "Example:", "Examples:")
186
+
187
+ for i, line in enumerate(lines):
188
+ stripped_line = line.strip()
189
+ if not summary_done and stripped_line and not stripped_line.startswith(section_markers):
190
+ summary_lines.append(line.strip())
191
+ elif not summary_done and not stripped_line and summary_lines:
192
+ # This blank line marks the end of the summary
193
+ summary_done = True
194
+ rest_lines = lines[i+1:]
195
+ break
196
+ elif stripped_line.startswith(section_markers):
197
+ # A section starts immediately after the summary
198
+ summary_done = True
199
+ rest_lines = lines[i:]
200
+ break
201
+ else:
202
+ # We are already in the rest of the docstring
203
+ rest_lines.append(line)
204
+
205
+ summary = " ".join(summary_lines)
206
+ # Reconstruct the rest of the docstring, preserving original indentation
207
+ rest_of_docstring = "\n".join(rest_lines)
208
+
209
+ return summary, rest_of_docstring
210
+
211
+
212
+ def generate_description(
213
+ function_code: str, file_content: str, model: str = "perplexity/sonar"
214
+ ) -> DescriptionOutput:
215
+ """
216
+ Generate a high-quality description and suggest a name for a Python function.
217
+
218
+ Args:
219
+ function_code: The source code of the function to document.
220
+ file_content: The entire content of the Python file for context.
221
+ model: The model to use for generating the description.
222
+
223
+ Returns:
224
+ A DescriptionOutput object containing the description and optional name.
225
+ """
226
+ system_prompt = SYSTEM_PROMPT_TEMPLATE.format(file_content=file_content)
227
+ user_prompt = USER_PROMPT_TEMPLATE.format(function_code=function_code)
228
+
229
+ # --- NEW: Retry logic with exponential backoff ---
230
+ max_retries = 3
231
+ base_delay = 2 # in seconds
232
+
233
+ for attempt in range(max_retries):
234
+ try:
235
+ response = litellm.completion(
236
+ model=model,
237
+ messages=[
238
+ {"role": "system", "content": system_prompt},
239
+ {"role": "user", "content": user_prompt},
240
+ ],
241
+ )
242
+ response_text = response.choices[0].message.content
243
+ try:
244
+ parsed_data = extract_json_from_text(response_text)
245
+ return DescriptionOutput(
246
+ description=parsed_data.get("description", "No description available."),
247
+ suggested_name=parsed_data.get("suggested_name"),
248
+ )
249
+ except ValueError as e:
250
+ print(f" - JSON extraction failed: {e}")
251
+ return DescriptionOutput(description="Failed to extract description.")
252
+
253
+ except litellm.InternalServerError as e:
254
+ if attempt < max_retries - 1:
255
+ delay = base_delay * (2**attempt)
256
+ print(
257
+ f" - Server error occurred: {e}. Retrying in {delay} seconds... (Attempt {attempt + 1}/{max_retries})",
258
+ file=sys.stderr,
259
+ )
260
+ time.sleep(delay)
261
+ else:
262
+ print(f" - Max retries reached. Error generating description: {e}", file=sys.stderr)
263
+ return DescriptionOutput(description=f"Error generating description after {max_retries} retries: {e}")
264
+
265
+ except Exception as e:
266
+ print(f" - An unexpected error occurred: {e}", file=sys.stderr)
267
+ return DescriptionOutput(description=f"An unexpected error occurred: {e}")
268
+
269
+ return DescriptionOutput(description="Failed to generate description after all retries.")
270
+
271
+ def insert_docstring_into_function(function_code: str, docstring: str) -> str:
272
+ """
273
+ Insert a docstring into a function's code, replacing an existing one if present.
274
+
275
+ Args:
276
+ function_code: The source code of the function snippet.
277
+ docstring: The formatted docstring string content.
278
+
279
+ Returns:
280
+ The updated function code with the docstring inserted.
281
+ """
282
+ try:
283
+ lines = function_code.splitlines(keepends=True)
284
+ tree = ast.parse(function_code)
285
+ if not tree.body or not isinstance(tree.body[0], (ast.FunctionDef, ast.AsyncFunctionDef)):
286
+ return function_code
287
+
288
+ func_node = tree.body[0]
289
+
290
+ # --- REVISED INDENTATION LOGIC ---
291
+ # Determine the correct indentation from the function's existing body.
292
+ if func_node.body:
293
+ # Use the indentation of the first statement in the body (e.g., the old docstring).
294
+ first_body_line_str = lines[func_node.body[0].lineno - 1]
295
+ body_indent = first_body_line_str[: len(first_body_line_str) - len(first_body_line_str.lstrip())]
296
+ else:
297
+ # Fallback for empty functions: calculate from the 'def' line.
298
+ def_line = lines[func_node.lineno - 1]
299
+ def_indent = def_line[: len(def_line) - len(def_line.lstrip())]
300
+ body_indent = def_indent + " "
301
+ # --- END OF REVISED LOGIC ---
302
+
303
+ # Format the new docstring with the determined indentation
304
+ new_docstring_lines_formatted = [f'{body_indent}"""\n']
305
+ new_docstring_lines_formatted.extend([f"{body_indent}{line}\n" for line in docstring.splitlines()])
306
+ new_docstring_lines_formatted.append(f'{body_indent}"""\n')
307
+
308
+ # Check if the first statement is an existing docstring
309
+ existing_docstring_node = None
310
+ if (
311
+ func_node.body and
312
+ isinstance(func_node.body[0], ast.Expr) and
313
+ isinstance(func_node.body[0].value, ast.Constant) and
314
+ isinstance(func_node.body[0].value.value, str)
315
+ ):
316
+ existing_docstring_node = func_node.body[0]
317
+
318
+ # Splice the code
319
+ insert_idx = func_node.body[0].lineno - 1 if func_node.body else func_node.lineno
320
+ pre_insertion_lines = lines[:insert_idx]
321
+
322
+ if existing_docstring_node:
323
+ post_insertion_lines = lines[existing_docstring_node.end_lineno:]
324
+ else:
325
+ post_insertion_lines = lines[insert_idx:]
326
+
327
+ output_lines = pre_insertion_lines + new_docstring_lines_formatted + post_insertion_lines
328
+
329
+ final_code = "".join(output_lines)
330
+ ast.parse(final_code) # Validate syntax
331
+ return final_code
332
+
333
+ except Exception as e:
334
+ print(f"Error processing function snippet for insertion: {e}", file=sys.stderr)
335
+ traceback.print_exc(file=sys.stderr)
336
+ return function_code
337
+
338
+
339
+ def rename_function_in_code(function_code: str, old_name: str, new_name: str) -> str:
340
+ """
341
+ Safely renames a function within its source code snippet.
342
+
343
+ Args:
344
+ function_code: The source code of the function.
345
+ old_name: The original name of the function.
346
+ new_name: The new name for the function.
347
+
348
+ Returns:
349
+ The function code with the updated name.
350
+ """
351
+ # This regex looks for 'def' or 'async def' followed by the old name
352
+ pattern = r"(async\s+def|def)\s+" + re.escape(old_name) + r"(\s*\()"
353
+ replacement = r"\1 " + new_name + r"\2"
354
+
355
+ new_function_code, num_replacements = re.subn(pattern, replacement, function_code, 1)
356
+
357
+ if num_replacements == 0:
358
+ print(f" - Warning: Could not rename function '{old_name}'. Name not found in definition.")
359
+ return function_code
360
+
361
+ return new_function_code
362
+
363
+
364
+ def update_list_tools_method(content: str, old_name: str, new_name: str) -> str:
365
+ """
366
+ Updates the list_tools method by renaming a function reference.
367
+
368
+ This function uses regex to find the `list_tools` method and replace
369
+ `self.old_name` with `self.new_name` within its return list, preserving
370
+ surrounding code and formatting.
371
+
372
+ Args:
373
+ content: The full source code of the file as a string.
374
+ old_name: The original name of the function to replace.
375
+ new_name: The new name for the function.
376
+
377
+ Returns:
378
+ The updated file content with the function renamed in list_tools.
379
+ """
380
+ # Regex to find `self.old_name` followed by a comma, newline, or closing bracket
381
+ # This ensures we only replace the specific tool reference in the list.
382
+ pattern = r"(self\.)" + re.escape(old_name) + r"(?=\s*[,\]])"
383
+ replacement = r"\1" + new_name
384
+
385
+ # First, find the list_tools method definition to narrow the search area
386
+ list_tools_match = re.search(r"def\s+list_tools\s*\([^)]*\):\s*return\s*\[[^\]]*\]", content, re.DOTALL)
387
+
388
+ if not list_tools_match:
389
+ print(" - Warning: `list_tools` method not found or has an unexpected format. Cannot update tool list.")
390
+ return content
391
+
392
+ list_tools_code = list_tools_match.group(0)
393
+
394
+ # Perform the replacement only within the found method block
395
+ updated_list_tools_code, num_replacements = re.subn(pattern, replacement, list_tools_code)
396
+
397
+ if num_replacements > 0:
398
+ print(f" - Renamed '{old_name}' to '{new_name}' in `list_tools` method.")
399
+ return content.replace(list_tools_code, updated_list_tools_code)
400
+ else:
401
+ print(f" - Warning: Function '{old_name}' not found in `list_tools` method.")
402
+ return content
403
+
404
+
405
+ def process_file(file_path: str, model: str = "perplexity/sonar") -> int:
406
+ """
407
+ Process a Python file to update docstrings and optionally rename functions.
408
+
409
+ Args:
410
+ file_path: Path to the Python file to process.
411
+ model: The model to use for generating descriptions.
412
+
413
+ Returns:
414
+ Number of functions processed.
415
+ """
416
+ if not os.path.exists(file_path):
417
+ raise FileNotFoundError(f"File not found: {file_path}")
418
+
419
+ with open(file_path, encoding="utf-8") as f:
420
+ original_content = f.read()
421
+
422
+ functions = extract_functions_from_script(file_path)
423
+ if not functions:
424
+ print(f"No functions found in {file_path}")
425
+ return 0
426
+
427
+ updated_content = original_content
428
+ count = 0
429
+
430
+ for function_name, function_code in functions:
431
+ print(f"Processing function: {function_name}")
432
+
433
+ try:
434
+ func_tree = ast.parse(function_code)
435
+ func_node = func_tree.body[0]
436
+ existing_docstring = ast.get_docstring(func_node, clean=True)
437
+ _, rest_of_docstring = parse_existing_docstring(existing_docstring)
438
+ except (SyntaxError, IndexError):
439
+ print(f" - Could not parse function '{function_name}', skipping.")
440
+ continue
441
+
442
+ # 1. Generate new description and check for suggested name
443
+ output = generate_description(function_code, original_content, model)
444
+ new_description = output.description.strip()
445
+ suggested_name = output.suggested_name
446
+
447
+ if not new_description or "Error generating description" in new_description:
448
+ print(f" - Failed to generate description for '{function_name}', skipping.")
449
+ continue
450
+
451
+ # 2. Reconstruct the full docstring content
452
+ reconstructed_docstring = new_description
453
+ if rest_of_docstring:
454
+ reconstructed_docstring += "\n\n" + rest_of_docstring
455
+
456
+ # 3. Handle function renaming if suggested
457
+ code_to_update = function_code
458
+ is_renamed = False
459
+ if suggested_name and suggested_name != function_name:
460
+ print(f" - Renaming function '{function_name}' to '{suggested_name}'")
461
+ code_to_update = rename_function_in_code(code_to_update, function_name, suggested_name)
462
+ is_renamed = True
463
+
464
+ # 4. Insert the new docstring back into the (potentially renamed) function code
465
+ updated_function_block = insert_docstring_into_function(code_to_update, reconstructed_docstring)
466
+
467
+ # 5. If any changes were made, update the main content
468
+ if updated_function_block != function_code:
469
+ updated_content = updated_content.replace(function_code, updated_function_block)
470
+ count += 1
471
+ print(f" - Updated function block for '{suggested_name or function_name}'.")
472
+
473
+ # 6. If the function was renamed, also update the list_tools method
474
+ if is_renamed:
475
+ updated_content = update_list_tools_method(updated_content, function_name, suggested_name)
476
+
477
+ if updated_content != original_content:
478
+ with open(file_path, "w", encoding="utf-8") as f:
479
+ f.write(updated_content)
480
+ print(f"\nUpdated {count} functions in {file_path}")
481
+ else:
482
+ print("\nNo changes made to the file.")
483
+
484
+ return count
485
+
486
+
487
+ app = typer.Typer()
488
+ @app.command()
489
+ def docgen(
490
+ file_path: Path = typer.Argument(..., help="Path to the Python file to process"),
491
+ model: str = typer.Option(
492
+ "gemini/gemini-2.5-pro",
493
+ "--model",
494
+ "-m",
495
+ help="Model to use for generating docstrings",
496
+ ),
497
+ ):
498
+ """
499
+ Generate/update docstrings and function names in Python files using LLMs.
500
+
501
+ This command uses litellm to generate high-quality docstring descriptions
502
+ and suggest better function names, updating the file accordingly.
503
+ """
504
+ if not file_path.exists():
505
+ console.print(f"[red]Error: File not found: {file_path}[/red]")
506
+ raise typer.Exit(1)
507
+
508
+ try:
509
+ processed = process_file(str(file_path), model)
510
+ console.print(f"[green]Successfully processed {processed} functions[/green]")
511
+ except Exception as e:
512
+ console.print(f"[red]Error: {e}[/red]")
513
+ raise typer.Exit(1) from e
514
+
515
+ if __name__ == "__main__":
516
+ app()