ai-parrot 0.17.2__cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.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 (535) hide show
  1. agentui/.prettierrc +15 -0
  2. agentui/QUICKSTART.md +272 -0
  3. agentui/README.md +59 -0
  4. agentui/env.example +16 -0
  5. agentui/jsconfig.json +14 -0
  6. agentui/package-lock.json +4242 -0
  7. agentui/package.json +34 -0
  8. agentui/scripts/postinstall/apply-patches.mjs +260 -0
  9. agentui/src/app.css +61 -0
  10. agentui/src/app.d.ts +13 -0
  11. agentui/src/app.html +12 -0
  12. agentui/src/components/LoadingSpinner.svelte +64 -0
  13. agentui/src/components/ThemeSwitcher.svelte +159 -0
  14. agentui/src/components/index.js +4 -0
  15. agentui/src/lib/api/bots.ts +60 -0
  16. agentui/src/lib/api/chat.ts +22 -0
  17. agentui/src/lib/api/http.ts +25 -0
  18. agentui/src/lib/components/BotCard.svelte +33 -0
  19. agentui/src/lib/components/ChatBubble.svelte +63 -0
  20. agentui/src/lib/components/Toast.svelte +21 -0
  21. agentui/src/lib/config.ts +20 -0
  22. agentui/src/lib/stores/auth.svelte.ts +73 -0
  23. agentui/src/lib/stores/theme.svelte.js +64 -0
  24. agentui/src/lib/stores/toast.svelte.ts +31 -0
  25. agentui/src/lib/utils/conversation.ts +39 -0
  26. agentui/src/routes/+layout.svelte +20 -0
  27. agentui/src/routes/+page.svelte +232 -0
  28. agentui/src/routes/login/+page.svelte +200 -0
  29. agentui/src/routes/talk/[agentId]/+page.svelte +297 -0
  30. agentui/src/routes/talk/[agentId]/+page.ts +7 -0
  31. agentui/static/README.md +1 -0
  32. agentui/svelte.config.js +11 -0
  33. agentui/tailwind.config.ts +53 -0
  34. agentui/tsconfig.json +3 -0
  35. agentui/vite.config.ts +10 -0
  36. ai_parrot-0.17.2.dist-info/METADATA +472 -0
  37. ai_parrot-0.17.2.dist-info/RECORD +535 -0
  38. ai_parrot-0.17.2.dist-info/WHEEL +6 -0
  39. ai_parrot-0.17.2.dist-info/entry_points.txt +2 -0
  40. ai_parrot-0.17.2.dist-info/licenses/LICENSE +21 -0
  41. ai_parrot-0.17.2.dist-info/top_level.txt +6 -0
  42. crew-builder/.prettierrc +15 -0
  43. crew-builder/QUICKSTART.md +259 -0
  44. crew-builder/README.md +113 -0
  45. crew-builder/env.example +17 -0
  46. crew-builder/jsconfig.json +14 -0
  47. crew-builder/package-lock.json +4182 -0
  48. crew-builder/package.json +37 -0
  49. crew-builder/scripts/postinstall/apply-patches.mjs +260 -0
  50. crew-builder/src/app.css +62 -0
  51. crew-builder/src/app.d.ts +13 -0
  52. crew-builder/src/app.html +12 -0
  53. crew-builder/src/components/LoadingSpinner.svelte +64 -0
  54. crew-builder/src/components/ThemeSwitcher.svelte +149 -0
  55. crew-builder/src/components/index.js +9 -0
  56. crew-builder/src/lib/api/bots.ts +60 -0
  57. crew-builder/src/lib/api/chat.ts +80 -0
  58. crew-builder/src/lib/api/client.ts +56 -0
  59. crew-builder/src/lib/api/crew/crew.ts +136 -0
  60. crew-builder/src/lib/api/index.ts +5 -0
  61. crew-builder/src/lib/api/o365/auth.ts +65 -0
  62. crew-builder/src/lib/auth/auth.ts +54 -0
  63. crew-builder/src/lib/components/AgentNode.svelte +43 -0
  64. crew-builder/src/lib/components/BotCard.svelte +33 -0
  65. crew-builder/src/lib/components/ChatBubble.svelte +67 -0
  66. crew-builder/src/lib/components/ConfigPanel.svelte +278 -0
  67. crew-builder/src/lib/components/JsonTreeNode.svelte +76 -0
  68. crew-builder/src/lib/components/JsonViewer.svelte +24 -0
  69. crew-builder/src/lib/components/MarkdownEditor.svelte +48 -0
  70. crew-builder/src/lib/components/ThemeToggle.svelte +36 -0
  71. crew-builder/src/lib/components/Toast.svelte +67 -0
  72. crew-builder/src/lib/components/Toolbar.svelte +157 -0
  73. crew-builder/src/lib/components/index.ts +10 -0
  74. crew-builder/src/lib/config.ts +8 -0
  75. crew-builder/src/lib/stores/auth.svelte.ts +228 -0
  76. crew-builder/src/lib/stores/crewStore.ts +369 -0
  77. crew-builder/src/lib/stores/theme.svelte.js +145 -0
  78. crew-builder/src/lib/stores/toast.svelte.ts +69 -0
  79. crew-builder/src/lib/utils/conversation.ts +39 -0
  80. crew-builder/src/lib/utils/markdown.ts +122 -0
  81. crew-builder/src/lib/utils/talkHistory.ts +47 -0
  82. crew-builder/src/routes/+layout.svelte +20 -0
  83. crew-builder/src/routes/+page.svelte +539 -0
  84. crew-builder/src/routes/agents/+page.svelte +247 -0
  85. crew-builder/src/routes/agents/[agentId]/+page.svelte +288 -0
  86. crew-builder/src/routes/agents/[agentId]/+page.ts +7 -0
  87. crew-builder/src/routes/builder/+page.svelte +204 -0
  88. crew-builder/src/routes/crew/ask/+page.svelte +1052 -0
  89. crew-builder/src/routes/crew/ask/+page.ts +1 -0
  90. crew-builder/src/routes/integrations/o365/+page.svelte +304 -0
  91. crew-builder/src/routes/login/+page.svelte +197 -0
  92. crew-builder/src/routes/talk/[agentId]/+page.svelte +487 -0
  93. crew-builder/src/routes/talk/[agentId]/+page.ts +7 -0
  94. crew-builder/static/README.md +1 -0
  95. crew-builder/svelte.config.js +11 -0
  96. crew-builder/tailwind.config.ts +53 -0
  97. crew-builder/tsconfig.json +3 -0
  98. crew-builder/vite.config.ts +10 -0
  99. mcp_servers/calculator_server.py +309 -0
  100. parrot/__init__.py +27 -0
  101. parrot/__pycache__/__init__.cpython-310.pyc +0 -0
  102. parrot/__pycache__/version.cpython-310.pyc +0 -0
  103. parrot/_version.py +34 -0
  104. parrot/a2a/__init__.py +48 -0
  105. parrot/a2a/client.py +658 -0
  106. parrot/a2a/discovery.py +89 -0
  107. parrot/a2a/mixin.py +257 -0
  108. parrot/a2a/models.py +376 -0
  109. parrot/a2a/server.py +770 -0
  110. parrot/agents/__init__.py +29 -0
  111. parrot/bots/__init__.py +12 -0
  112. parrot/bots/a2a_agent.py +19 -0
  113. parrot/bots/abstract.py +3139 -0
  114. parrot/bots/agent.py +1129 -0
  115. parrot/bots/basic.py +9 -0
  116. parrot/bots/chatbot.py +669 -0
  117. parrot/bots/data.py +1618 -0
  118. parrot/bots/database/__init__.py +5 -0
  119. parrot/bots/database/abstract.py +3071 -0
  120. parrot/bots/database/cache.py +286 -0
  121. parrot/bots/database/models.py +468 -0
  122. parrot/bots/database/prompts.py +154 -0
  123. parrot/bots/database/retries.py +98 -0
  124. parrot/bots/database/router.py +269 -0
  125. parrot/bots/database/sql.py +41 -0
  126. parrot/bots/db/__init__.py +6 -0
  127. parrot/bots/db/abstract.py +556 -0
  128. parrot/bots/db/bigquery.py +602 -0
  129. parrot/bots/db/cache.py +85 -0
  130. parrot/bots/db/documentdb.py +668 -0
  131. parrot/bots/db/elastic.py +1014 -0
  132. parrot/bots/db/influx.py +898 -0
  133. parrot/bots/db/mock.py +96 -0
  134. parrot/bots/db/multi.py +783 -0
  135. parrot/bots/db/prompts.py +185 -0
  136. parrot/bots/db/sql.py +1255 -0
  137. parrot/bots/db/tools.py +212 -0
  138. parrot/bots/document.py +680 -0
  139. parrot/bots/hrbot.py +15 -0
  140. parrot/bots/kb.py +170 -0
  141. parrot/bots/mcp.py +36 -0
  142. parrot/bots/orchestration/README.md +463 -0
  143. parrot/bots/orchestration/__init__.py +1 -0
  144. parrot/bots/orchestration/agent.py +155 -0
  145. parrot/bots/orchestration/crew.py +3330 -0
  146. parrot/bots/orchestration/fsm.py +1179 -0
  147. parrot/bots/orchestration/hr.py +434 -0
  148. parrot/bots/orchestration/storage/__init__.py +4 -0
  149. parrot/bots/orchestration/storage/memory.py +100 -0
  150. parrot/bots/orchestration/storage/mixin.py +119 -0
  151. parrot/bots/orchestration/verify.py +202 -0
  152. parrot/bots/product.py +204 -0
  153. parrot/bots/prompts/__init__.py +96 -0
  154. parrot/bots/prompts/agents.py +155 -0
  155. parrot/bots/prompts/data.py +216 -0
  156. parrot/bots/prompts/output_generation.py +8 -0
  157. parrot/bots/scraper/__init__.py +3 -0
  158. parrot/bots/scraper/models.py +122 -0
  159. parrot/bots/scraper/scraper.py +1173 -0
  160. parrot/bots/scraper/templates.py +115 -0
  161. parrot/bots/stores/__init__.py +5 -0
  162. parrot/bots/stores/local.py +172 -0
  163. parrot/bots/webdev.py +81 -0
  164. parrot/cli.py +17 -0
  165. parrot/clients/__init__.py +16 -0
  166. parrot/clients/base.py +1491 -0
  167. parrot/clients/claude.py +1191 -0
  168. parrot/clients/factory.py +129 -0
  169. parrot/clients/google.py +4567 -0
  170. parrot/clients/gpt.py +1975 -0
  171. parrot/clients/grok.py +432 -0
  172. parrot/clients/groq.py +986 -0
  173. parrot/clients/hf.py +582 -0
  174. parrot/clients/models.py +18 -0
  175. parrot/conf.py +395 -0
  176. parrot/embeddings/__init__.py +9 -0
  177. parrot/embeddings/base.py +157 -0
  178. parrot/embeddings/google.py +98 -0
  179. parrot/embeddings/huggingface.py +74 -0
  180. parrot/embeddings/openai.py +84 -0
  181. parrot/embeddings/processor.py +88 -0
  182. parrot/exceptions.c +13868 -0
  183. parrot/exceptions.cpython-310-x86_64-linux-gnu.so +0 -0
  184. parrot/exceptions.pxd +22 -0
  185. parrot/exceptions.pxi +15 -0
  186. parrot/exceptions.pyx +44 -0
  187. parrot/generators/__init__.py +29 -0
  188. parrot/generators/base.py +200 -0
  189. parrot/generators/html.py +293 -0
  190. parrot/generators/react.py +205 -0
  191. parrot/generators/streamlit.py +203 -0
  192. parrot/generators/template.py +105 -0
  193. parrot/handlers/__init__.py +4 -0
  194. parrot/handlers/agent.py +861 -0
  195. parrot/handlers/agents/__init__.py +1 -0
  196. parrot/handlers/agents/abstract.py +900 -0
  197. parrot/handlers/bots.py +338 -0
  198. parrot/handlers/chat.py +915 -0
  199. parrot/handlers/creation.sql +192 -0
  200. parrot/handlers/crew/ARCHITECTURE.md +362 -0
  201. parrot/handlers/crew/README_BOTMANAGER_PERSISTENCE.md +303 -0
  202. parrot/handlers/crew/README_REDIS_PERSISTENCE.md +366 -0
  203. parrot/handlers/crew/__init__.py +0 -0
  204. parrot/handlers/crew/handler.py +801 -0
  205. parrot/handlers/crew/models.py +229 -0
  206. parrot/handlers/crew/redis_persistence.py +523 -0
  207. parrot/handlers/jobs/__init__.py +10 -0
  208. parrot/handlers/jobs/job.py +384 -0
  209. parrot/handlers/jobs/mixin.py +627 -0
  210. parrot/handlers/jobs/models.py +115 -0
  211. parrot/handlers/jobs/worker.py +31 -0
  212. parrot/handlers/models.py +596 -0
  213. parrot/handlers/o365_auth.py +105 -0
  214. parrot/handlers/stream.py +337 -0
  215. parrot/interfaces/__init__.py +6 -0
  216. parrot/interfaces/aws.py +143 -0
  217. parrot/interfaces/credentials.py +113 -0
  218. parrot/interfaces/database.py +27 -0
  219. parrot/interfaces/google.py +1123 -0
  220. parrot/interfaces/hierarchy.py +1227 -0
  221. parrot/interfaces/http.py +651 -0
  222. parrot/interfaces/images/__init__.py +0 -0
  223. parrot/interfaces/images/plugins/__init__.py +24 -0
  224. parrot/interfaces/images/plugins/abstract.py +58 -0
  225. parrot/interfaces/images/plugins/analisys.py +148 -0
  226. parrot/interfaces/images/plugins/classify.py +150 -0
  227. parrot/interfaces/images/plugins/classifybase.py +182 -0
  228. parrot/interfaces/images/plugins/detect.py +150 -0
  229. parrot/interfaces/images/plugins/exif.py +1103 -0
  230. parrot/interfaces/images/plugins/hash.py +52 -0
  231. parrot/interfaces/images/plugins/vision.py +104 -0
  232. parrot/interfaces/images/plugins/yolo.py +66 -0
  233. parrot/interfaces/images/plugins/zerodetect.py +197 -0
  234. parrot/interfaces/o365.py +978 -0
  235. parrot/interfaces/onedrive.py +822 -0
  236. parrot/interfaces/sharepoint.py +1435 -0
  237. parrot/interfaces/soap.py +257 -0
  238. parrot/loaders/__init__.py +8 -0
  239. parrot/loaders/abstract.py +1131 -0
  240. parrot/loaders/audio.py +199 -0
  241. parrot/loaders/basepdf.py +53 -0
  242. parrot/loaders/basevideo.py +1568 -0
  243. parrot/loaders/csv.py +409 -0
  244. parrot/loaders/docx.py +116 -0
  245. parrot/loaders/epubloader.py +316 -0
  246. parrot/loaders/excel.py +199 -0
  247. parrot/loaders/factory.py +55 -0
  248. parrot/loaders/files/__init__.py +0 -0
  249. parrot/loaders/files/abstract.py +39 -0
  250. parrot/loaders/files/html.py +26 -0
  251. parrot/loaders/files/text.py +63 -0
  252. parrot/loaders/html.py +152 -0
  253. parrot/loaders/markdown.py +442 -0
  254. parrot/loaders/pdf.py +373 -0
  255. parrot/loaders/pdfmark.py +320 -0
  256. parrot/loaders/pdftables.py +506 -0
  257. parrot/loaders/ppt.py +476 -0
  258. parrot/loaders/qa.py +63 -0
  259. parrot/loaders/splitters/__init__.py +10 -0
  260. parrot/loaders/splitters/base.py +138 -0
  261. parrot/loaders/splitters/md.py +228 -0
  262. parrot/loaders/splitters/token.py +143 -0
  263. parrot/loaders/txt.py +26 -0
  264. parrot/loaders/video.py +89 -0
  265. parrot/loaders/videolocal.py +218 -0
  266. parrot/loaders/videounderstanding.py +377 -0
  267. parrot/loaders/vimeo.py +167 -0
  268. parrot/loaders/web.py +599 -0
  269. parrot/loaders/youtube.py +504 -0
  270. parrot/manager/__init__.py +5 -0
  271. parrot/manager/manager.py +1030 -0
  272. parrot/mcp/__init__.py +28 -0
  273. parrot/mcp/adapter.py +105 -0
  274. parrot/mcp/cli.py +174 -0
  275. parrot/mcp/client.py +119 -0
  276. parrot/mcp/config.py +75 -0
  277. parrot/mcp/integration.py +842 -0
  278. parrot/mcp/oauth.py +933 -0
  279. parrot/mcp/server.py +225 -0
  280. parrot/mcp/transports/__init__.py +3 -0
  281. parrot/mcp/transports/base.py +279 -0
  282. parrot/mcp/transports/grpc_session.py +163 -0
  283. parrot/mcp/transports/http.py +312 -0
  284. parrot/mcp/transports/mcp.proto +108 -0
  285. parrot/mcp/transports/quic.py +1082 -0
  286. parrot/mcp/transports/sse.py +330 -0
  287. parrot/mcp/transports/stdio.py +309 -0
  288. parrot/mcp/transports/unix.py +395 -0
  289. parrot/mcp/transports/websocket.py +547 -0
  290. parrot/memory/__init__.py +16 -0
  291. parrot/memory/abstract.py +209 -0
  292. parrot/memory/agent.py +32 -0
  293. parrot/memory/cache.py +175 -0
  294. parrot/memory/core.py +555 -0
  295. parrot/memory/file.py +153 -0
  296. parrot/memory/mem.py +131 -0
  297. parrot/memory/redis.py +613 -0
  298. parrot/models/__init__.py +46 -0
  299. parrot/models/basic.py +118 -0
  300. parrot/models/compliance.py +208 -0
  301. parrot/models/crew.py +395 -0
  302. parrot/models/detections.py +654 -0
  303. parrot/models/generation.py +85 -0
  304. parrot/models/google.py +223 -0
  305. parrot/models/groq.py +23 -0
  306. parrot/models/openai.py +30 -0
  307. parrot/models/outputs.py +285 -0
  308. parrot/models/responses.py +938 -0
  309. parrot/notifications/__init__.py +743 -0
  310. parrot/openapi/__init__.py +3 -0
  311. parrot/openapi/components.yaml +641 -0
  312. parrot/openapi/config.py +322 -0
  313. parrot/outputs/__init__.py +32 -0
  314. parrot/outputs/formats/__init__.py +108 -0
  315. parrot/outputs/formats/altair.py +359 -0
  316. parrot/outputs/formats/application.py +122 -0
  317. parrot/outputs/formats/base.py +351 -0
  318. parrot/outputs/formats/bokeh.py +356 -0
  319. parrot/outputs/formats/card.py +424 -0
  320. parrot/outputs/formats/chart.py +436 -0
  321. parrot/outputs/formats/d3.py +255 -0
  322. parrot/outputs/formats/echarts.py +310 -0
  323. parrot/outputs/formats/generators/__init__.py +0 -0
  324. parrot/outputs/formats/generators/abstract.py +61 -0
  325. parrot/outputs/formats/generators/panel.py +145 -0
  326. parrot/outputs/formats/generators/streamlit.py +86 -0
  327. parrot/outputs/formats/generators/terminal.py +63 -0
  328. parrot/outputs/formats/holoviews.py +310 -0
  329. parrot/outputs/formats/html.py +147 -0
  330. parrot/outputs/formats/jinja2.py +46 -0
  331. parrot/outputs/formats/json.py +87 -0
  332. parrot/outputs/formats/map.py +933 -0
  333. parrot/outputs/formats/markdown.py +172 -0
  334. parrot/outputs/formats/matplotlib.py +237 -0
  335. parrot/outputs/formats/mixins/__init__.py +0 -0
  336. parrot/outputs/formats/mixins/emaps.py +855 -0
  337. parrot/outputs/formats/plotly.py +341 -0
  338. parrot/outputs/formats/seaborn.py +310 -0
  339. parrot/outputs/formats/table.py +397 -0
  340. parrot/outputs/formats/template_report.py +138 -0
  341. parrot/outputs/formats/yaml.py +125 -0
  342. parrot/outputs/formatter.py +152 -0
  343. parrot/outputs/templates/__init__.py +95 -0
  344. parrot/pipelines/__init__.py +0 -0
  345. parrot/pipelines/abstract.py +210 -0
  346. parrot/pipelines/detector.py +124 -0
  347. parrot/pipelines/models.py +90 -0
  348. parrot/pipelines/planogram.py +3002 -0
  349. parrot/pipelines/table.sql +97 -0
  350. parrot/plugins/__init__.py +106 -0
  351. parrot/plugins/importer.py +80 -0
  352. parrot/py.typed +0 -0
  353. parrot/registry/__init__.py +18 -0
  354. parrot/registry/registry.py +594 -0
  355. parrot/scheduler/__init__.py +1189 -0
  356. parrot/scheduler/models.py +60 -0
  357. parrot/security/__init__.py +16 -0
  358. parrot/security/prompt_injection.py +268 -0
  359. parrot/security/security_events.sql +25 -0
  360. parrot/services/__init__.py +1 -0
  361. parrot/services/mcp/__init__.py +8 -0
  362. parrot/services/mcp/config.py +13 -0
  363. parrot/services/mcp/server.py +295 -0
  364. parrot/services/o365_remote_auth.py +235 -0
  365. parrot/stores/__init__.py +7 -0
  366. parrot/stores/abstract.py +352 -0
  367. parrot/stores/arango.py +1090 -0
  368. parrot/stores/bigquery.py +1377 -0
  369. parrot/stores/cache.py +106 -0
  370. parrot/stores/empty.py +10 -0
  371. parrot/stores/faiss_store.py +1157 -0
  372. parrot/stores/kb/__init__.py +9 -0
  373. parrot/stores/kb/abstract.py +68 -0
  374. parrot/stores/kb/cache.py +165 -0
  375. parrot/stores/kb/doc.py +325 -0
  376. parrot/stores/kb/hierarchy.py +346 -0
  377. parrot/stores/kb/local.py +457 -0
  378. parrot/stores/kb/prompt.py +28 -0
  379. parrot/stores/kb/redis.py +659 -0
  380. parrot/stores/kb/store.py +115 -0
  381. parrot/stores/kb/user.py +374 -0
  382. parrot/stores/models.py +59 -0
  383. parrot/stores/pgvector.py +3 -0
  384. parrot/stores/postgres.py +2853 -0
  385. parrot/stores/utils/__init__.py +0 -0
  386. parrot/stores/utils/chunking.py +197 -0
  387. parrot/telemetry/__init__.py +3 -0
  388. parrot/telemetry/mixin.py +111 -0
  389. parrot/template/__init__.py +3 -0
  390. parrot/template/engine.py +259 -0
  391. parrot/tools/__init__.py +23 -0
  392. parrot/tools/abstract.py +644 -0
  393. parrot/tools/agent.py +363 -0
  394. parrot/tools/arangodbsearch.py +537 -0
  395. parrot/tools/arxiv_tool.py +188 -0
  396. parrot/tools/calculator/__init__.py +3 -0
  397. parrot/tools/calculator/operations/__init__.py +38 -0
  398. parrot/tools/calculator/operations/calculus.py +80 -0
  399. parrot/tools/calculator/operations/statistics.py +76 -0
  400. parrot/tools/calculator/tool.py +150 -0
  401. parrot/tools/cloudwatch.py +988 -0
  402. parrot/tools/codeinterpreter/__init__.py +127 -0
  403. parrot/tools/codeinterpreter/executor.py +371 -0
  404. parrot/tools/codeinterpreter/internals.py +473 -0
  405. parrot/tools/codeinterpreter/models.py +643 -0
  406. parrot/tools/codeinterpreter/prompts.py +224 -0
  407. parrot/tools/codeinterpreter/tool.py +664 -0
  408. parrot/tools/company_info/__init__.py +6 -0
  409. parrot/tools/company_info/tool.py +1138 -0
  410. parrot/tools/correlationanalysis.py +437 -0
  411. parrot/tools/database/abstract.py +286 -0
  412. parrot/tools/database/bq.py +115 -0
  413. parrot/tools/database/cache.py +284 -0
  414. parrot/tools/database/models.py +95 -0
  415. parrot/tools/database/pg.py +343 -0
  416. parrot/tools/databasequery.py +1159 -0
  417. parrot/tools/db.py +1800 -0
  418. parrot/tools/ddgo.py +370 -0
  419. parrot/tools/decorators.py +271 -0
  420. parrot/tools/dftohtml.py +282 -0
  421. parrot/tools/document.py +549 -0
  422. parrot/tools/ecs.py +819 -0
  423. parrot/tools/edareport.py +368 -0
  424. parrot/tools/elasticsearch.py +1049 -0
  425. parrot/tools/employees.py +462 -0
  426. parrot/tools/epson/__init__.py +96 -0
  427. parrot/tools/excel.py +683 -0
  428. parrot/tools/file/__init__.py +13 -0
  429. parrot/tools/file/abstract.py +76 -0
  430. parrot/tools/file/gcs.py +378 -0
  431. parrot/tools/file/local.py +284 -0
  432. parrot/tools/file/s3.py +511 -0
  433. parrot/tools/file/tmp.py +309 -0
  434. parrot/tools/file/tool.py +501 -0
  435. parrot/tools/file_reader.py +129 -0
  436. parrot/tools/flowtask/__init__.py +19 -0
  437. parrot/tools/flowtask/tool.py +761 -0
  438. parrot/tools/gittoolkit.py +508 -0
  439. parrot/tools/google/__init__.py +18 -0
  440. parrot/tools/google/base.py +169 -0
  441. parrot/tools/google/tools.py +1251 -0
  442. parrot/tools/googlelocation.py +5 -0
  443. parrot/tools/googleroutes.py +5 -0
  444. parrot/tools/googlesearch.py +5 -0
  445. parrot/tools/googlesitesearch.py +5 -0
  446. parrot/tools/googlevoice.py +2 -0
  447. parrot/tools/gvoice.py +695 -0
  448. parrot/tools/ibisworld/README.md +225 -0
  449. parrot/tools/ibisworld/__init__.py +11 -0
  450. parrot/tools/ibisworld/tool.py +366 -0
  451. parrot/tools/jiratoolkit.py +1718 -0
  452. parrot/tools/manager.py +1098 -0
  453. parrot/tools/math.py +152 -0
  454. parrot/tools/metadata.py +476 -0
  455. parrot/tools/msteams.py +1621 -0
  456. parrot/tools/msword.py +635 -0
  457. parrot/tools/multidb.py +580 -0
  458. parrot/tools/multistoresearch.py +369 -0
  459. parrot/tools/networkninja.py +167 -0
  460. parrot/tools/nextstop/__init__.py +4 -0
  461. parrot/tools/nextstop/base.py +286 -0
  462. parrot/tools/nextstop/employee.py +733 -0
  463. parrot/tools/nextstop/store.py +462 -0
  464. parrot/tools/notification.py +435 -0
  465. parrot/tools/o365/__init__.py +42 -0
  466. parrot/tools/o365/base.py +295 -0
  467. parrot/tools/o365/bundle.py +522 -0
  468. parrot/tools/o365/events.py +554 -0
  469. parrot/tools/o365/mail.py +992 -0
  470. parrot/tools/o365/onedrive.py +497 -0
  471. parrot/tools/o365/sharepoint.py +641 -0
  472. parrot/tools/openapi_toolkit.py +904 -0
  473. parrot/tools/openweather.py +527 -0
  474. parrot/tools/pdfprint.py +1001 -0
  475. parrot/tools/powerbi.py +518 -0
  476. parrot/tools/powerpoint.py +1113 -0
  477. parrot/tools/pricestool.py +146 -0
  478. parrot/tools/products/__init__.py +246 -0
  479. parrot/tools/prophet_tool.py +171 -0
  480. parrot/tools/pythonpandas.py +630 -0
  481. parrot/tools/pythonrepl.py +910 -0
  482. parrot/tools/qsource.py +436 -0
  483. parrot/tools/querytoolkit.py +395 -0
  484. parrot/tools/quickeda.py +827 -0
  485. parrot/tools/resttool.py +553 -0
  486. parrot/tools/retail/__init__.py +0 -0
  487. parrot/tools/retail/bby.py +528 -0
  488. parrot/tools/sandboxtool.py +703 -0
  489. parrot/tools/sassie/__init__.py +352 -0
  490. parrot/tools/scraping/__init__.py +7 -0
  491. parrot/tools/scraping/docs/select.md +466 -0
  492. parrot/tools/scraping/documentation.md +1278 -0
  493. parrot/tools/scraping/driver.py +436 -0
  494. parrot/tools/scraping/models.py +576 -0
  495. parrot/tools/scraping/options.py +85 -0
  496. parrot/tools/scraping/orchestrator.py +517 -0
  497. parrot/tools/scraping/readme.md +740 -0
  498. parrot/tools/scraping/tool.py +3115 -0
  499. parrot/tools/seasonaldetection.py +642 -0
  500. parrot/tools/shell_tool/__init__.py +5 -0
  501. parrot/tools/shell_tool/actions.py +408 -0
  502. parrot/tools/shell_tool/engine.py +155 -0
  503. parrot/tools/shell_tool/models.py +322 -0
  504. parrot/tools/shell_tool/tool.py +442 -0
  505. parrot/tools/site_search.py +214 -0
  506. parrot/tools/textfile.py +418 -0
  507. parrot/tools/think.py +378 -0
  508. parrot/tools/toolkit.py +298 -0
  509. parrot/tools/webapp_tool.py +187 -0
  510. parrot/tools/whatif.py +1279 -0
  511. parrot/tools/workday/MULTI_WSDL_EXAMPLE.md +249 -0
  512. parrot/tools/workday/__init__.py +6 -0
  513. parrot/tools/workday/models.py +1389 -0
  514. parrot/tools/workday/tool.py +1293 -0
  515. parrot/tools/yfinance_tool.py +306 -0
  516. parrot/tools/zipcode.py +217 -0
  517. parrot/utils/__init__.py +2 -0
  518. parrot/utils/helpers.py +73 -0
  519. parrot/utils/parsers/__init__.py +5 -0
  520. parrot/utils/parsers/toml.c +12078 -0
  521. parrot/utils/parsers/toml.cpython-310-x86_64-linux-gnu.so +0 -0
  522. parrot/utils/parsers/toml.pyx +21 -0
  523. parrot/utils/toml.py +11 -0
  524. parrot/utils/types.cpp +20936 -0
  525. parrot/utils/types.cpython-310-x86_64-linux-gnu.so +0 -0
  526. parrot/utils/types.pyx +213 -0
  527. parrot/utils/uv.py +11 -0
  528. parrot/version.py +10 -0
  529. parrot/yaml-rs/Cargo.lock +350 -0
  530. parrot/yaml-rs/Cargo.toml +19 -0
  531. parrot/yaml-rs/pyproject.toml +19 -0
  532. parrot/yaml-rs/python/yaml_rs/__init__.py +81 -0
  533. parrot/yaml-rs/src/lib.rs +222 -0
  534. requirements/docker-compose.yml +24 -0
  535. requirements/requirements-dev.txt +21 -0
@@ -0,0 +1,842 @@
1
+ import os
2
+ from typing import Dict, List, Any, Optional, Union
3
+ import logging
4
+ from pathlib import Path
5
+ # AI-Parrot imports
6
+ from ..tools.abstract import AbstractTool, ToolResult
7
+ from ..tools.manager import ToolManager
8
+ from .oauth import (
9
+ OAuthManager,
10
+ InMemoryTokenStore,
11
+ RedisTokenStore
12
+ )
13
+ from .client import (
14
+ MCPClientConfig as MCPServerConfig,
15
+ MCPConnectionError
16
+ )
17
+ from .transports.stdio import StdioMCPSession
18
+ from .transports.unix import UnixMCPSession
19
+ from .transports.http import HttpMCPSession
20
+ from .transports.websocket import WebSocketMCPSession
21
+ from .transports.sse import SseMCPSession
22
+ from .transports.quic import (
23
+ QuicMCPSession,
24
+ QuicMCPConfig,
25
+ SerializationFormat
26
+ )
27
+
28
+
29
+ class MCPToolProxy(AbstractTool):
30
+ """Proxy tool that wraps an individual MCP tool."""
31
+
32
+ def __init__(
33
+ self,
34
+ mcp_tool_def: Dict[str, Any],
35
+ mcp_client: 'MCPClient',
36
+ server_name: str,
37
+ **kwargs
38
+ ):
39
+ super().__init__(**kwargs)
40
+
41
+ self.mcp_tool_def = mcp_tool_def
42
+ self.mcp_client = mcp_client
43
+ self.server_name = server_name
44
+
45
+ self.name = f"mcp_{server_name}_{mcp_tool_def['name']}"
46
+ self.description = mcp_tool_def.get('description', f"MCP tool: {mcp_tool_def['name']}")
47
+ self.input_schema = mcp_tool_def.get('inputSchema', {})
48
+
49
+ self.logger = logging.getLogger(f"MCPTool.{self.name}")
50
+
51
+ async def _execute(self, **kwargs) -> ToolResult:
52
+ """Execute the MCP tool."""
53
+ try:
54
+ result = await self.mcp_client.call_tool(
55
+ self.mcp_tool_def['name'],
56
+ kwargs
57
+ )
58
+
59
+ result_text = self._extract_result_text(result)
60
+
61
+ return ToolResult(
62
+ status="success",
63
+ result=result_text,
64
+ metadata={
65
+ "server": self.server_name,
66
+ "tool": self.mcp_tool_def['name'],
67
+ "transport": self.mcp_client.config.transport,
68
+ "mcp_response_type": type(result).__name__
69
+ }
70
+ )
71
+
72
+ except Exception as e:
73
+ self.logger.error(f"Error executing MCP tool {self.name}: {e}")
74
+ return ToolResult(
75
+ status="error",
76
+ result=None,
77
+ error=str(e),
78
+ metadata={
79
+ "server": self.server_name,
80
+ "tool": self.mcp_tool_def['name']
81
+ }
82
+ )
83
+
84
+ def _extract_result_text(self, result) -> str:
85
+ """Extract text content from MCP response."""
86
+ if hasattr(result, 'content') and result.content:
87
+ content_parts = []
88
+ for item in result.content:
89
+ if hasattr(item, 'text'):
90
+ content_parts.append(item.text)
91
+ elif isinstance(item, dict):
92
+ content_parts.append(item.get('text', str(item)))
93
+ else:
94
+ content_parts.append(str(item))
95
+ return "\n".join(content_parts) if content_parts else str(result)
96
+ return str(result)
97
+
98
+
99
+ class MCPClient:
100
+ """Complete MCP client with stdio and HTTP transport support."""
101
+
102
+ def __init__(self, config: MCPServerConfig):
103
+ self.config = config
104
+ self.logger = logging.getLogger(f"MCPClient.{config.name}")
105
+ self._session = None
106
+ self._connected = False
107
+ self._available_tools = []
108
+
109
+ def _detect_transport(self) -> str:
110
+ """Auto-detect transport type."""
111
+ if self.config.transport != "auto":
112
+ return self.config.transport
113
+
114
+ if self.config.socket_path:
115
+ return "unix"
116
+ if self.config.url:
117
+ # Check if URL looks like SSE endpoint
118
+ if "events" in self.config.url or "sse" in self.config.url:
119
+ return "sse"
120
+ else:
121
+ return "http"
122
+ elif self.config.command:
123
+ return "stdio"
124
+ else:
125
+ raise ValueError(
126
+ "Cannot auto-detect transport. "
127
+ "Please specify socket_path, url, or command."
128
+ )
129
+
130
+ async def connect(self):
131
+ """Connect to MCP server using appropriate transport."""
132
+ if self._connected:
133
+ return
134
+
135
+ transport = self._detect_transport()
136
+
137
+ try:
138
+ if transport == "stdio":
139
+ self._session = StdioMCPSession(self.config, self.logger)
140
+ elif transport == "http":
141
+ self._session = HttpMCPSession(self.config, self.logger)
142
+ elif transport == "sse":
143
+ self._session = SseMCPSession(self.config, self.logger)
144
+ elif transport == "unix":
145
+ self._session = UnixMCPSession(self.config, self.logger)
146
+ elif transport == "websocket":
147
+
148
+ self._session = WebSocketMCPSession(self.config, self.logger)
149
+ elif transport == "quic":
150
+ try:
151
+ self._session = QuicMCPSession(self.config, self.logger)
152
+ except ImportError as e:
153
+ raise ImportError(
154
+ "QUIC transport requires 'aioquic' package. Install with: pip install aioquic msgpack"
155
+ ) from e
156
+ else:
157
+ raise ValueError(
158
+ f"Unsupported transport: {transport}"
159
+ )
160
+
161
+ await self._session.connect()
162
+ self._available_tools = await self._session.list_tools()
163
+ self._connected = True
164
+
165
+ self.logger.info(
166
+ f"Connected to MCP server {self.config.name} "
167
+ f"via {transport} with {len(self._available_tools)} tools"
168
+ )
169
+
170
+ except Exception as e:
171
+ self.logger.error(f"Failed to connect: {e}")
172
+ await self.disconnect()
173
+ raise
174
+
175
+ async def call_tool(self, tool_name: str, arguments: Dict[str, Any]):
176
+ """Call an MCP tool."""
177
+ if not self._connected:
178
+ raise MCPConnectionError("Not connected to MCP server")
179
+
180
+ return await self._session.call_tool(tool_name, arguments)
181
+
182
+ def get_available_tools(self) -> List[Dict[str, Any]]:
183
+ """Get available tools as dictionaries."""
184
+ tools = []
185
+ for tool in self._available_tools:
186
+ tool_dict = {
187
+ 'name': getattr(tool, 'name', 'unknown'),
188
+ 'description': getattr(tool, 'description', ''),
189
+ 'inputSchema': getattr(tool, 'inputSchema', {})
190
+ }
191
+ tools.append(tool_dict)
192
+ return tools
193
+
194
+ async def disconnect(self):
195
+ """Disconnect from MCP server."""
196
+ if not self._connected:
197
+ return
198
+
199
+ self._connected = False
200
+
201
+ if self._session:
202
+ await self._session.disconnect()
203
+ self._session = None
204
+
205
+ self._available_tools = []
206
+ self.logger.info(f"Disconnected from {self.config.name}")
207
+
208
+ async def __aenter__(self):
209
+ await self.connect()
210
+ return self
211
+
212
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
213
+ await self.disconnect()
214
+
215
+
216
+ class MCPToolManager:
217
+ """Manages multiple MCP servers and their tools."""
218
+
219
+ def __init__(self, tool_manager: ToolManager):
220
+ self.tool_manager = tool_manager
221
+ self.mcp_clients: Dict[str, MCPClient] = {}
222
+ self.logger = logging.getLogger("MCPToolManager")
223
+
224
+ async def add_mcp_server(self, config: MCPServerConfig) -> List[str]:
225
+ """Add an MCP server and register its tools."""
226
+ client = MCPClient(config)
227
+
228
+ try:
229
+ await client.connect()
230
+ self.mcp_clients[config.name] = client
231
+
232
+ available_tools = client.get_available_tools()
233
+ registered_tools = []
234
+
235
+ for tool_def in available_tools:
236
+ tool_name = tool_def.get('name', 'unknown')
237
+
238
+ if self._should_skip_tool(tool_name, config):
239
+ continue
240
+
241
+ proxy_tool = MCPToolProxy(
242
+ mcp_tool_def=tool_def,
243
+ mcp_client=client,
244
+ server_name=config.name
245
+ )
246
+
247
+ self.tool_manager.register_tool(proxy_tool)
248
+ registered_tools.append(proxy_tool.name)
249
+ self.logger.info(f"Registered MCP tool: {proxy_tool.name}")
250
+
251
+ transport = getattr(client, '_session', None)
252
+ transport_type = config.transport if config.transport != "auto" else "detected"
253
+
254
+ self.logger.info(
255
+ f"Successfully added MCP server {config.name} "
256
+ f"({transport_type} transport) with {len(registered_tools)} tools"
257
+ )
258
+ return registered_tools
259
+
260
+ except Exception as e:
261
+ self.logger.error(f"Failed to add MCP server {config.name}: {e}")
262
+ await self._cleanup_failed_client(config.name, client)
263
+ raise
264
+
265
+ def _should_skip_tool(self, tool_name: str, config: MCPServerConfig) -> bool:
266
+ """Check if tool should be skipped based on filtering rules."""
267
+ if config.allowed_tools and tool_name not in config.allowed_tools:
268
+ self.logger.debug(f"Skipping tool {tool_name} (not in allowed_tools)")
269
+ return True
270
+ if config.blocked_tools and tool_name in config.blocked_tools:
271
+ self.logger.debug(f"Skipping tool {tool_name} (in blocked_tools)")
272
+ return True
273
+ return False
274
+
275
+ async def _cleanup_failed_client(self, server_name: str, client: MCPClient):
276
+ """Clean up a failed client connection."""
277
+ if server_name in self.mcp_clients:
278
+ del self.mcp_clients[server_name]
279
+
280
+ try:
281
+ await client.disconnect()
282
+ except Exception:
283
+ pass
284
+
285
+ async def remove_mcp_server(self, server_name: str):
286
+ """Remove an MCP server and unregister its tools."""
287
+ if server_name not in self.mcp_clients:
288
+ self.logger.warning(f"MCP server {server_name} not found")
289
+ return
290
+
291
+ client = self.mcp_clients[server_name]
292
+
293
+ tools_to_remove = [
294
+ tool_name for tool_name in self.tool_manager.list_tools()
295
+ if tool_name.startswith(f"mcp_{server_name}_")
296
+ ]
297
+
298
+ for tool_name in tools_to_remove:
299
+ self.tool_manager.unregister_tool(tool_name)
300
+ self.logger.info(f"Unregistered MCP tool: {tool_name}")
301
+
302
+ await client.disconnect()
303
+ del self.mcp_clients[server_name]
304
+
305
+ async def reconfigure_mcp_server(self, config: MCPServerConfig) -> List[str]:
306
+ """Reconfigure an existing MCP server with new configuration.
307
+
308
+ This method removes the existing server connection and re-adds it with the
309
+ new configuration. Useful for updating credentials or connection parameters.
310
+
311
+ Args:
312
+ config: New MCPServerConfig with updated parameters
313
+
314
+ Returns:
315
+ List of registered tool names
316
+
317
+ Example:
318
+ >>> # Update Fireflies API key for a different user
319
+ >>> new_config = create_fireflies_mcp_server(api_key="new-user-api-key")
320
+ >>> tools = await manager.reconfigure_mcp_server(new_config)
321
+ """
322
+ server_name = config.name
323
+
324
+ # Remove existing server if it exists
325
+ if server_name in self.mcp_clients:
326
+ self.logger.info(f"Reconfiguring MCP server: {server_name}")
327
+ await self.remove_mcp_server(server_name)
328
+ else:
329
+ self.logger.info(f"Adding new MCP server: {server_name}")
330
+
331
+ # Add with new configuration
332
+ return await self.add_mcp_server(config)
333
+
334
+ async def disconnect_all(self):
335
+ """Disconnect all MCP clients."""
336
+ for client in list(self.mcp_clients.values()):
337
+ await client.disconnect()
338
+ self.mcp_clients.clear()
339
+
340
+ def list_mcp_servers(self) -> List[str]:
341
+ return list(self.mcp_clients.keys())
342
+
343
+ def get_mcp_client(self, server_name: str) -> Optional[MCPClient]:
344
+ return self.mcp_clients.get(server_name)
345
+
346
+
347
+ # Convenience functions for different server types
348
+ def create_local_mcp_server(
349
+ name: str,
350
+ script_path: Union[str, Path],
351
+ interpreter: str = "python",
352
+ **kwargs
353
+ ) -> MCPServerConfig:
354
+ """Create configuration for local stdio MCP server."""
355
+ script_path = Path(script_path)
356
+ if not script_path.exists():
357
+ raise FileNotFoundError(f"MCP server script not found: {script_path}")
358
+
359
+ return MCPServerConfig(
360
+ name=name,
361
+ command=interpreter,
362
+ args=[str(script_path)],
363
+ transport="stdio",
364
+ **kwargs
365
+ )
366
+
367
+
368
+ def create_http_mcp_server(
369
+ name: str,
370
+ url: str,
371
+ auth_type: Optional[str] = None,
372
+ auth_config: Optional[Dict[str, Any]] = None,
373
+ headers: Optional[Dict[str, str]] = None,
374
+ **kwargs
375
+ ) -> MCPServerConfig:
376
+ """Create configuration for HTTP MCP server."""
377
+ return MCPServerConfig(
378
+ name=name,
379
+ url=url,
380
+ transport="http",
381
+ auth_type=auth_type,
382
+ auth_config=auth_config or {},
383
+ headers=headers or {},
384
+ **kwargs
385
+ )
386
+
387
+ def create_oauth_mcp_server(
388
+ *,
389
+ name: str,
390
+ url: str,
391
+ user_id: str,
392
+ client_id: str,
393
+ auth_url: str,
394
+ token_url: str,
395
+ scopes: list[str],
396
+ client_secret: str | None = None,
397
+ redis=None, # pass an aioredis client if you have it; else None -> in-memory
398
+ redirect_host: str = "127.0.0.1",
399
+ redirect_port: int = 8765,
400
+ redirect_path: str = "/mcp/oauth/callback",
401
+ extra_token_params: dict | None = None,
402
+ headers: dict | None = None,
403
+ ) -> MCPServerConfig:
404
+ token_store = RedisTokenStore(redis) if redis else InMemoryTokenStore()
405
+ oauth = OAuthManager(
406
+ user_id=user_id,
407
+ server_name=name,
408
+ client_id=client_id,
409
+ client_secret=client_secret,
410
+ auth_url=auth_url,
411
+ token_url=token_url,
412
+ scopes=scopes,
413
+ redirect_host=redirect_host,
414
+ redirect_port=redirect_port,
415
+ redirect_path=redirect_path,
416
+ token_store=token_store,
417
+ extra_token_params=extra_token_params,
418
+ )
419
+
420
+ cfg = MCPServerConfig(
421
+ name=name,
422
+ transport="http",
423
+ url=url,
424
+ headers=headers or {"Content-Type": "application/json"},
425
+ auth_type="oauth",
426
+ auth_config={
427
+ "auth_url": auth_url,
428
+ "token_url": token_url,
429
+ "scopes": scopes,
430
+ "client_id": client_id,
431
+ "client_secret": bool(client_secret),
432
+ "redirect_uri": oauth.redirect_uri,
433
+ },
434
+ token_supplier=oauth.token_supplier, # this is called before each request
435
+ )
436
+
437
+ # Attach a small helper so the client can ensure token before using the server.
438
+ cfg._ensure_oauth_token = oauth.ensure_token # attribute on purpose
439
+ return cfg
440
+
441
+ def create_unix_mcp_server(
442
+ name: str,
443
+ socket_path: str,
444
+ **kwargs
445
+ ) -> MCPServerConfig:
446
+ """Create a Unix socket MCP server configuration.
447
+
448
+ Args:
449
+ name: Server name
450
+ socket_path: Path to Unix socket
451
+ **kwargs: Additional MCPServerConfig parameters
452
+
453
+ Returns:
454
+ MCPServerConfig configured for Unix socket transport
455
+
456
+ Example:
457
+ >>> config = create_unix_mcp_server(
458
+ ... "workday",
459
+ ... "/tmp/parrot-mcp-workday.sock"
460
+ ... )
461
+ >>> async with MCPClient(config) as client:
462
+ ... tools = await client.list_tools()
463
+ """
464
+ return MCPServerConfig(
465
+ name=name,
466
+ transport="unix",
467
+ socket_path=socket_path,
468
+ **kwargs
469
+ )
470
+
471
+
472
+ def create_websocket_mcp_server(
473
+ name: str,
474
+ url: str,
475
+ auth_type: Optional[str] = None,
476
+ auth_config: Optional[Dict[str, Any]] = None,
477
+ headers: Optional[Dict[str, str]] = None,
478
+ **kwargs
479
+ ) -> MCPServerConfig:
480
+ """Create a WebSocket MCP server configuration.
481
+
482
+ Args:
483
+ name: Server name
484
+ url: WebSocket URL (ws:// or wss://)
485
+ auth_type: Authentication type ("bearer", "api_key", "oauth", or None)
486
+ auth_config: Authentication configuration dict
487
+ headers: Additional HTTP headers for WebSocket upgrade
488
+ **kwargs: Additional MCPServerConfig parameters
489
+
490
+ Returns:
491
+ MCPServerConfig configured for WebSocket transport
492
+
493
+ Example:
494
+ >>> config = create_websocket_mcp_server(
495
+ ... "my-ws-server",
496
+ ... "ws://localhost:8766/mcp/ws",
497
+ ... auth_type="bearer",
498
+ ... auth_config={"token": "my-secret-token"}
499
+ ... )
500
+ >>> async with MCPClient(config) as client:
501
+ ... tools = await client.list_tools()
502
+ """
503
+ return MCPServerConfig(
504
+ name=name,
505
+ url=url,
506
+ transport="websocket",
507
+ auth_type=auth_type,
508
+ auth_config=auth_config or {},
509
+ headers=headers or {},
510
+ **kwargs
511
+ )
512
+
513
+
514
+ def create_api_key_mcp_server(
515
+ name: str,
516
+ url: str,
517
+ api_key: str,
518
+ header_name: str = "X-API-Key",
519
+ use_bearer_prefix: bool = False,
520
+ **kwargs
521
+ ) -> MCPServerConfig:
522
+ """Create configuration for API key authenticated MCP server.
523
+
524
+ Args:
525
+ name: Unique name for the MCP server
526
+ url: Base URL of the MCP server
527
+ api_key: API key for authentication
528
+ header_name: Header name for the API key (default: "X-API-Key")
529
+ use_bearer_prefix: If True, prepend "Bearer " to the API key value (default: False)
530
+ **kwargs: Additional MCPServerConfig parameters
531
+
532
+ Returns:
533
+ MCPServerConfig instance
534
+ """
535
+ return create_http_mcp_server(
536
+ name=name,
537
+ url=url,
538
+ auth_type="api_key",
539
+ auth_config={
540
+ "api_key": api_key,
541
+ "header_name": header_name,
542
+ "use_bearer_prefix": use_bearer_prefix
543
+ },
544
+ **kwargs
545
+ )
546
+
547
+
548
+ def create_fireflies_mcp_server(
549
+ *,
550
+ api_key: str,
551
+ api_base: str = "https://api.fireflies.ai/mcp",
552
+ **kwargs
553
+ ) -> MCPServerConfig:
554
+ """Create configuration for Fireflies MCP server using stdio transport.
555
+
556
+ Fireflies MCP requires using npx mcp-remote as a command-line proxy.
557
+
558
+ Args:
559
+ api_key: Fireflies API key
560
+ api_base: Base URL of the Fireflies MCP endpoint
561
+ **kwargs: Additional MCPServerConfig parameters
562
+
563
+ Returns:
564
+ MCPServerConfig instance configured for stdio transport
565
+ """
566
+ return MCPServerConfig(
567
+ name="fireflies",
568
+ command="npx",
569
+ args=[
570
+ "mcp-remote",
571
+ api_base,
572
+ "--header",
573
+ f"Authorization: Bearer {api_key}"
574
+ ],
575
+ transport="stdio",
576
+ **kwargs
577
+ )
578
+
579
+
580
+ def create_perplexity_mcp_server(
581
+ api_key: str,
582
+ *,
583
+ name: str = "perplexity",
584
+ timeout_ms: int = 600000,
585
+ **kwargs
586
+ ) -> MCPServerConfig:
587
+ """Create configuration for Perplexity MCP server.
588
+
589
+ The Perplexity MCP server provides 4 tools:
590
+ - perplexity_search: Direct web search via Search API
591
+ - perplexity_ask: Conversational AI with sonar-pro model
592
+ - perplexity_research: Deep research with sonar-deep-research
593
+ - perplexity_reason: Advanced reasoning with sonar-reasoning-pro
594
+
595
+ Args:
596
+ api_key: Perplexity API key (get from perplexity.ai/account/api)
597
+ name: Server name for tool prefixing
598
+ timeout_ms: Request timeout (default 600000ms for deep research)
599
+ **kwargs: Additional MCPServerConfig parameters
600
+
601
+ Returns:
602
+ MCPServerConfig configured for Perplexity
603
+
604
+ Example:
605
+ >>> config = create_perplexity_mcp_server(
606
+ ... api_key=os.environ["PERPLEXITY_API_KEY"]
607
+ ... )
608
+ >>> await agent.add_mcp_server(config)
609
+ """
610
+ return MCPServerConfig(
611
+ name=name,
612
+ transport="stdio",
613
+ command="npx",
614
+ args=["-y", "@perplexity-ai/mcp-server"],
615
+ env={
616
+ "PERPLEXITY_API_KEY": api_key or os.environ.get("PERPLEXITY_API_KEY"),
617
+ "PERPLEXITY_TIMEOUT_MS": str(timeout_ms),
618
+ },
619
+ startup_delay=3.0, # npx needs time to fetch/start
620
+ **kwargs
621
+ )
622
+
623
+ def create_quic_mcp_server(
624
+ name: str,
625
+ host: str,
626
+ port: int,
627
+ cert_path: Optional[str] = None,
628
+ serialization: str = "msgpack",
629
+ **kwargs
630
+ ) -> MCPServerConfig:
631
+ """Create configuration for QUIC MCP server.
632
+
633
+ Args:
634
+ name: Server name
635
+ host: Server hostname
636
+ port: Server port
637
+ cert_path: Path to TLS certificate (optional for client if trusted)
638
+ serialization: Serialization format ("msgpack" or "json")
639
+ **kwargs: Additional MCPServerConfig parameters
640
+
641
+ Returns:
642
+ MCPServerConfig configured for QUIC transport
643
+ """
644
+ quic_fmt = SerializationFormat.MSGPACK
645
+ if serialization.lower() == "json":
646
+ quic_fmt = SerializationFormat.JSON
647
+
648
+ quic_conf = QuicMCPConfig(
649
+ host=host,
650
+ port=port,
651
+ cert_path=cert_path,
652
+ serialization=quic_fmt,
653
+ # Default efficient settings
654
+ enable_0rtt=True,
655
+ enable_webtransport=True
656
+ )
657
+
658
+ return MCPServerConfig(
659
+ name=name,
660
+ transport="quic",
661
+ quic_config=quic_conf,
662
+ **kwargs
663
+ )
664
+
665
+ # Extension for BaseAgent
666
+ class MCPEnabledMixin:
667
+ """Mixin to add complete MCP capabilities to agents."""
668
+
669
+ def __init__(self, *args, **kwargs):
670
+ super().__init__(*args, **kwargs)
671
+ self.mcp_manager = MCPToolManager(self.tool_manager)
672
+
673
+ async def add_mcp_server(self, config: MCPServerConfig) -> List[str]:
674
+ """Add an MCP server with full feature support."""
675
+ return await self.mcp_manager.add_mcp_server(config)
676
+
677
+ async def add_local_mcp_server(
678
+ self,
679
+ name: str,
680
+ script_path: Union[str, Path],
681
+ interpreter: str = "python",
682
+ **kwargs
683
+ ) -> List[str]:
684
+ """Add a local stdio MCP server."""
685
+ config = create_local_mcp_server(name, script_path, interpreter, **kwargs)
686
+ return await self.add_mcp_server(config)
687
+
688
+ async def add_http_mcp_server(
689
+ self,
690
+ name: str,
691
+ url: str,
692
+ auth_type: Optional[str] = None,
693
+ auth_config: Optional[Dict[str, Any]] = None,
694
+ headers: Optional[Dict[str, str]] = None,
695
+ **kwargs
696
+ ) -> List[str]:
697
+ """Add an HTTP MCP server."""
698
+ config = create_http_mcp_server(name, url, auth_type, auth_config, headers, **kwargs)
699
+ return await self.add_mcp_server(config)
700
+
701
+ async def add_perplexity_mcp_server(
702
+ self,
703
+ api_key: str,
704
+ name: str = "perplexity",
705
+ **kwargs
706
+ ) -> List[str]:
707
+ """Add a Perplexity MCP server capability."""
708
+ config = create_perplexity_mcp_server(api_key, name=name, **kwargs)
709
+ return await self.add_mcp_server(config)
710
+
711
+ async def add_fireflies_mcp_server(
712
+ self,
713
+ api_key: str,
714
+ **kwargs
715
+ ) -> List[str]:
716
+ """Add Fireflies.ai MCP server capability.
717
+
718
+ Args:
719
+ api_key: Fireflies API key from Settings > Developer Settings
720
+ **kwargs: Additional MCPServerConfig parameters
721
+
722
+ Returns:
723
+ List of registered tool names
724
+
725
+ Example:
726
+ >>> tools = await agent.add_fireflies_mcp_server(
727
+ ... api_key="your-fireflies-api-key"
728
+ ... )
729
+ """
730
+ config = create_fireflies_mcp_server(api_key=api_key, **kwargs)
731
+ return await self.add_mcp_server(config)
732
+
733
+ async def add_quic_mcp_server(
734
+ self,
735
+ name: str,
736
+ host: str,
737
+ port: int,
738
+ cert_path: Optional[str] = None,
739
+ **kwargs
740
+ ) -> List[str]:
741
+ """Add a QUIC/HTTP3 MCP server connection."""
742
+ config = create_quic_mcp_server(name, host, port, cert_path, **kwargs)
743
+ return await self.add_mcp_server(config)
744
+
745
+ async def add_websocket_mcp_server(
746
+ self,
747
+ name: str,
748
+ url: str,
749
+ auth_type: Optional[str] = None,
750
+ auth_config: Optional[Dict[str, Any]] = None,
751
+ headers: Optional[Dict[str, str]] = None,
752
+ **kwargs
753
+ ) -> List[str]:
754
+ """Add a WebSocket MCP server connection.
755
+
756
+ Args:
757
+ name: Server name
758
+ url: WebSocket URL (ws:// or wss://)
759
+ auth_type: Authentication type ("bearer", "api_key", "oauth")
760
+ auth_config: Authentication configuration
761
+ headers: Additional headers for WebSocket upgrade
762
+ **kwargs: Additional MCPServerConfig parameters
763
+
764
+ Returns:
765
+ List of registered tool names
766
+
767
+ Example:
768
+ >>> await agent.add_websocket_mcp_server(
769
+ ... "my-ws-server",
770
+ ... "ws://localhost:8766/mcp/ws",
771
+ ... auth_type="bearer",
772
+ ... auth_config={"token": "my-token"}
773
+ ... )
774
+ """
775
+ config = create_websocket_mcp_server(
776
+ name, url, auth_type, auth_config, headers, **kwargs
777
+ )
778
+ return await self.add_mcp_server(config)
779
+
780
+ async def remove_mcp_server(self, server_name: str):
781
+ await self.mcp_manager.remove_mcp_server(server_name)
782
+
783
+ async def reconfigure_mcp_server(self, config: MCPServerConfig) -> List[str]:
784
+ """Reconfigure an existing MCP server with new configuration.
785
+
786
+ Args:
787
+ config: New MCPServerConfig with updated parameters
788
+
789
+ Returns:
790
+ List of registered tool names
791
+ """
792
+ return await self.mcp_manager.reconfigure_mcp_server(config)
793
+
794
+ async def reconfigure_fireflies_mcp_server(self, api_key: str, **kwargs) -> List[str]:
795
+ """Reconfigure Fireflies MCP server with a new API key.
796
+
797
+ This is useful in multi-user scenarios where each user provides their own
798
+ Fireflies API key. The method will disconnect the existing connection and
799
+ reconnect with the new credentials.
800
+
801
+ Args:
802
+ api_key: New Fireflies API key
803
+ **kwargs: Additional MCPServerConfig parameters
804
+
805
+ Returns:
806
+ List of registered tool names
807
+
808
+ Example:
809
+ >>> # Initial setup with user 1's API key
810
+ >>> await agent.add_fireflies_mcp_server(api_key="user1-api-key")
811
+
812
+ >>> # Later, reconfigure with user 2's API key
813
+ >>> await agent.reconfigure_fireflies_mcp_server(api_key="user2-api-key")
814
+ """
815
+ config = create_fireflies_mcp_server(api_key=api_key, **kwargs)
816
+ return await self.reconfigure_mcp_server(config)
817
+
818
+ async def reconfigure_perplexity_mcp_server(self, api_key: str, name: str = "perplexity", **kwargs) -> List[str]:
819
+ """Reconfigure Perplexity MCP server with a new API key.
820
+
821
+ Useful for updating the API key without restarting the agent.
822
+
823
+ Args:
824
+ api_key: New Perplexity API key
825
+ name: Server name (default: "perplexity")
826
+ **kwargs: Additional MCPServerConfig parameters
827
+
828
+ Returns:
829
+ List of registered tool names
830
+ """
831
+ config = create_perplexity_mcp_server(api_key, name=name, **kwargs)
832
+ return await self.reconfigure_mcp_server(config)
833
+
834
+ def list_mcp_servers(self) -> List[str]:
835
+ return self.mcp_manager.list_mcp_servers()
836
+
837
+ async def shutdown(self, **kwargs):
838
+ if hasattr(self, 'mcp_manager'):
839
+ await self.mcp_manager.disconnect_all()
840
+
841
+ if hasattr(super(), 'shutdown'):
842
+ await super().shutdown(**kwargs)