agno 0.1.2__py3-none-any.whl → 2.3.13__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (723) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +44 -5
  3. agno/agent/agent.py +10531 -2975
  4. agno/api/agent.py +14 -53
  5. agno/api/api.py +7 -46
  6. agno/api/evals.py +22 -0
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -25
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +6 -9
  11. agno/api/schemas/evals.py +16 -0
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +10 -10
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +16 -0
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +22 -26
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/compression/__init__.py +3 -0
  25. agno/compression/manager.py +247 -0
  26. agno/culture/__init__.py +3 -0
  27. agno/culture/manager.py +956 -0
  28. agno/db/__init__.py +24 -0
  29. agno/db/async_postgres/__init__.py +3 -0
  30. agno/db/base.py +946 -0
  31. agno/db/dynamo/__init__.py +3 -0
  32. agno/db/dynamo/dynamo.py +2781 -0
  33. agno/db/dynamo/schemas.py +442 -0
  34. agno/db/dynamo/utils.py +743 -0
  35. agno/db/firestore/__init__.py +3 -0
  36. agno/db/firestore/firestore.py +2379 -0
  37. agno/db/firestore/schemas.py +181 -0
  38. agno/db/firestore/utils.py +376 -0
  39. agno/db/gcs_json/__init__.py +3 -0
  40. agno/db/gcs_json/gcs_json_db.py +1791 -0
  41. agno/db/gcs_json/utils.py +228 -0
  42. agno/db/in_memory/__init__.py +3 -0
  43. agno/db/in_memory/in_memory_db.py +1312 -0
  44. agno/db/in_memory/utils.py +230 -0
  45. agno/db/json/__init__.py +3 -0
  46. agno/db/json/json_db.py +1777 -0
  47. agno/db/json/utils.py +230 -0
  48. agno/db/migrations/manager.py +199 -0
  49. agno/db/migrations/v1_to_v2.py +635 -0
  50. agno/db/migrations/versions/v2_3_0.py +938 -0
  51. agno/db/mongo/__init__.py +17 -0
  52. agno/db/mongo/async_mongo.py +2760 -0
  53. agno/db/mongo/mongo.py +2597 -0
  54. agno/db/mongo/schemas.py +119 -0
  55. agno/db/mongo/utils.py +276 -0
  56. agno/db/mysql/__init__.py +4 -0
  57. agno/db/mysql/async_mysql.py +2912 -0
  58. agno/db/mysql/mysql.py +2923 -0
  59. agno/db/mysql/schemas.py +186 -0
  60. agno/db/mysql/utils.py +488 -0
  61. agno/db/postgres/__init__.py +4 -0
  62. agno/db/postgres/async_postgres.py +2579 -0
  63. agno/db/postgres/postgres.py +2870 -0
  64. agno/db/postgres/schemas.py +187 -0
  65. agno/db/postgres/utils.py +442 -0
  66. agno/db/redis/__init__.py +3 -0
  67. agno/db/redis/redis.py +2141 -0
  68. agno/db/redis/schemas.py +159 -0
  69. agno/db/redis/utils.py +346 -0
  70. agno/db/schemas/__init__.py +4 -0
  71. agno/db/schemas/culture.py +120 -0
  72. agno/db/schemas/evals.py +34 -0
  73. agno/db/schemas/knowledge.py +40 -0
  74. agno/db/schemas/memory.py +61 -0
  75. agno/db/singlestore/__init__.py +3 -0
  76. agno/db/singlestore/schemas.py +179 -0
  77. agno/db/singlestore/singlestore.py +2877 -0
  78. agno/db/singlestore/utils.py +384 -0
  79. agno/db/sqlite/__init__.py +4 -0
  80. agno/db/sqlite/async_sqlite.py +2911 -0
  81. agno/db/sqlite/schemas.py +181 -0
  82. agno/db/sqlite/sqlite.py +2908 -0
  83. agno/db/sqlite/utils.py +429 -0
  84. agno/db/surrealdb/__init__.py +3 -0
  85. agno/db/surrealdb/metrics.py +292 -0
  86. agno/db/surrealdb/models.py +334 -0
  87. agno/db/surrealdb/queries.py +71 -0
  88. agno/db/surrealdb/surrealdb.py +1908 -0
  89. agno/db/surrealdb/utils.py +147 -0
  90. agno/db/utils.py +118 -0
  91. agno/eval/__init__.py +24 -0
  92. agno/eval/accuracy.py +666 -276
  93. agno/eval/agent_as_judge.py +861 -0
  94. agno/eval/base.py +29 -0
  95. agno/eval/performance.py +779 -0
  96. agno/eval/reliability.py +241 -62
  97. agno/eval/utils.py +120 -0
  98. agno/exceptions.py +143 -1
  99. agno/filters.py +354 -0
  100. agno/guardrails/__init__.py +6 -0
  101. agno/guardrails/base.py +19 -0
  102. agno/guardrails/openai.py +144 -0
  103. agno/guardrails/pii.py +94 -0
  104. agno/guardrails/prompt_injection.py +52 -0
  105. agno/hooks/__init__.py +3 -0
  106. agno/hooks/decorator.py +164 -0
  107. agno/integrations/discord/__init__.py +3 -0
  108. agno/integrations/discord/client.py +203 -0
  109. agno/knowledge/__init__.py +5 -1
  110. agno/{document → knowledge}/chunking/agentic.py +22 -14
  111. agno/{document → knowledge}/chunking/document.py +2 -2
  112. agno/{document → knowledge}/chunking/fixed.py +7 -6
  113. agno/knowledge/chunking/markdown.py +151 -0
  114. agno/{document → knowledge}/chunking/recursive.py +15 -3
  115. agno/knowledge/chunking/row.py +39 -0
  116. agno/knowledge/chunking/semantic.py +91 -0
  117. agno/knowledge/chunking/strategy.py +165 -0
  118. agno/knowledge/content.py +74 -0
  119. agno/knowledge/document/__init__.py +5 -0
  120. agno/{document → knowledge/document}/base.py +12 -2
  121. agno/knowledge/embedder/__init__.py +5 -0
  122. agno/knowledge/embedder/aws_bedrock.py +343 -0
  123. agno/knowledge/embedder/azure_openai.py +210 -0
  124. agno/{embedder → knowledge/embedder}/base.py +8 -0
  125. agno/knowledge/embedder/cohere.py +323 -0
  126. agno/knowledge/embedder/fastembed.py +62 -0
  127. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  128. agno/knowledge/embedder/google.py +258 -0
  129. agno/knowledge/embedder/huggingface.py +94 -0
  130. agno/knowledge/embedder/jina.py +182 -0
  131. agno/knowledge/embedder/langdb.py +22 -0
  132. agno/knowledge/embedder/mistral.py +206 -0
  133. agno/knowledge/embedder/nebius.py +13 -0
  134. agno/knowledge/embedder/ollama.py +154 -0
  135. agno/knowledge/embedder/openai.py +195 -0
  136. agno/knowledge/embedder/sentence_transformer.py +63 -0
  137. agno/{embedder → knowledge/embedder}/together.py +1 -1
  138. agno/knowledge/embedder/vllm.py +262 -0
  139. agno/knowledge/embedder/voyageai.py +165 -0
  140. agno/knowledge/knowledge.py +3006 -0
  141. agno/knowledge/reader/__init__.py +7 -0
  142. agno/knowledge/reader/arxiv_reader.py +81 -0
  143. agno/knowledge/reader/base.py +95 -0
  144. agno/knowledge/reader/csv_reader.py +164 -0
  145. agno/knowledge/reader/docx_reader.py +82 -0
  146. agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
  147. agno/knowledge/reader/firecrawl_reader.py +201 -0
  148. agno/knowledge/reader/json_reader.py +88 -0
  149. agno/knowledge/reader/markdown_reader.py +137 -0
  150. agno/knowledge/reader/pdf_reader.py +431 -0
  151. agno/knowledge/reader/pptx_reader.py +101 -0
  152. agno/knowledge/reader/reader_factory.py +313 -0
  153. agno/knowledge/reader/s3_reader.py +89 -0
  154. agno/knowledge/reader/tavily_reader.py +193 -0
  155. agno/knowledge/reader/text_reader.py +127 -0
  156. agno/knowledge/reader/web_search_reader.py +325 -0
  157. agno/knowledge/reader/website_reader.py +455 -0
  158. agno/knowledge/reader/wikipedia_reader.py +91 -0
  159. agno/knowledge/reader/youtube_reader.py +78 -0
  160. agno/knowledge/remote_content/remote_content.py +88 -0
  161. agno/knowledge/reranker/__init__.py +3 -0
  162. agno/{reranker → knowledge/reranker}/base.py +1 -1
  163. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  164. agno/knowledge/reranker/infinity.py +195 -0
  165. agno/knowledge/reranker/sentence_transformer.py +54 -0
  166. agno/knowledge/types.py +39 -0
  167. agno/knowledge/utils.py +234 -0
  168. agno/media.py +439 -95
  169. agno/memory/__init__.py +16 -3
  170. agno/memory/manager.py +1474 -123
  171. agno/memory/strategies/__init__.py +15 -0
  172. agno/memory/strategies/base.py +66 -0
  173. agno/memory/strategies/summarize.py +196 -0
  174. agno/memory/strategies/types.py +37 -0
  175. agno/models/aimlapi/__init__.py +5 -0
  176. agno/models/aimlapi/aimlapi.py +62 -0
  177. agno/models/anthropic/__init__.py +4 -0
  178. agno/models/anthropic/claude.py +960 -496
  179. agno/models/aws/__init__.py +15 -0
  180. agno/models/aws/bedrock.py +686 -451
  181. agno/models/aws/claude.py +190 -183
  182. agno/models/azure/__init__.py +18 -1
  183. agno/models/azure/ai_foundry.py +489 -0
  184. agno/models/azure/openai_chat.py +89 -40
  185. agno/models/base.py +2477 -550
  186. agno/models/cerebras/__init__.py +12 -0
  187. agno/models/cerebras/cerebras.py +565 -0
  188. agno/models/cerebras/cerebras_openai.py +131 -0
  189. agno/models/cohere/__init__.py +4 -0
  190. agno/models/cohere/chat.py +306 -492
  191. agno/models/cometapi/__init__.py +5 -0
  192. agno/models/cometapi/cometapi.py +74 -0
  193. agno/models/dashscope/__init__.py +5 -0
  194. agno/models/dashscope/dashscope.py +90 -0
  195. agno/models/deepinfra/__init__.py +5 -0
  196. agno/models/deepinfra/deepinfra.py +45 -0
  197. agno/models/deepseek/__init__.py +4 -0
  198. agno/models/deepseek/deepseek.py +110 -9
  199. agno/models/fireworks/__init__.py +4 -0
  200. agno/models/fireworks/fireworks.py +19 -22
  201. agno/models/google/__init__.py +3 -7
  202. agno/models/google/gemini.py +1717 -662
  203. agno/models/google/utils.py +22 -0
  204. agno/models/groq/__init__.py +4 -0
  205. agno/models/groq/groq.py +391 -666
  206. agno/models/huggingface/__init__.py +4 -0
  207. agno/models/huggingface/huggingface.py +266 -538
  208. agno/models/ibm/__init__.py +5 -0
  209. agno/models/ibm/watsonx.py +432 -0
  210. agno/models/internlm/__init__.py +3 -0
  211. agno/models/internlm/internlm.py +20 -3
  212. agno/models/langdb/__init__.py +1 -0
  213. agno/models/langdb/langdb.py +60 -0
  214. agno/models/litellm/__init__.py +14 -0
  215. agno/models/litellm/chat.py +503 -0
  216. agno/models/litellm/litellm_openai.py +42 -0
  217. agno/models/llama_cpp/__init__.py +5 -0
  218. agno/models/llama_cpp/llama_cpp.py +22 -0
  219. agno/models/lmstudio/__init__.py +5 -0
  220. agno/models/lmstudio/lmstudio.py +25 -0
  221. agno/models/message.py +361 -39
  222. agno/models/meta/__init__.py +12 -0
  223. agno/models/meta/llama.py +502 -0
  224. agno/models/meta/llama_openai.py +79 -0
  225. agno/models/metrics.py +120 -0
  226. agno/models/mistral/__init__.py +4 -0
  227. agno/models/mistral/mistral.py +293 -393
  228. agno/models/nebius/__init__.py +3 -0
  229. agno/models/nebius/nebius.py +53 -0
  230. agno/models/nexus/__init__.py +3 -0
  231. agno/models/nexus/nexus.py +22 -0
  232. agno/models/nvidia/__init__.py +4 -0
  233. agno/models/nvidia/nvidia.py +22 -3
  234. agno/models/ollama/__init__.py +4 -2
  235. agno/models/ollama/chat.py +257 -492
  236. agno/models/openai/__init__.py +7 -0
  237. agno/models/openai/chat.py +725 -770
  238. agno/models/openai/like.py +16 -2
  239. agno/models/openai/responses.py +1121 -0
  240. agno/models/openrouter/__init__.py +4 -0
  241. agno/models/openrouter/openrouter.py +62 -5
  242. agno/models/perplexity/__init__.py +5 -0
  243. agno/models/perplexity/perplexity.py +203 -0
  244. agno/models/portkey/__init__.py +3 -0
  245. agno/models/portkey/portkey.py +82 -0
  246. agno/models/requesty/__init__.py +5 -0
  247. agno/models/requesty/requesty.py +69 -0
  248. agno/models/response.py +177 -7
  249. agno/models/sambanova/__init__.py +4 -0
  250. agno/models/sambanova/sambanova.py +23 -4
  251. agno/models/siliconflow/__init__.py +5 -0
  252. agno/models/siliconflow/siliconflow.py +42 -0
  253. agno/models/together/__init__.py +4 -0
  254. agno/models/together/together.py +21 -164
  255. agno/models/utils.py +266 -0
  256. agno/models/vercel/__init__.py +3 -0
  257. agno/models/vercel/v0.py +43 -0
  258. agno/models/vertexai/__init__.py +0 -1
  259. agno/models/vertexai/claude.py +190 -0
  260. agno/models/vllm/__init__.py +3 -0
  261. agno/models/vllm/vllm.py +83 -0
  262. agno/models/xai/__init__.py +2 -0
  263. agno/models/xai/xai.py +111 -7
  264. agno/os/__init__.py +3 -0
  265. agno/os/app.py +1027 -0
  266. agno/os/auth.py +244 -0
  267. agno/os/config.py +126 -0
  268. agno/os/interfaces/__init__.py +1 -0
  269. agno/os/interfaces/a2a/__init__.py +3 -0
  270. agno/os/interfaces/a2a/a2a.py +42 -0
  271. agno/os/interfaces/a2a/router.py +249 -0
  272. agno/os/interfaces/a2a/utils.py +924 -0
  273. agno/os/interfaces/agui/__init__.py +3 -0
  274. agno/os/interfaces/agui/agui.py +47 -0
  275. agno/os/interfaces/agui/router.py +147 -0
  276. agno/os/interfaces/agui/utils.py +574 -0
  277. agno/os/interfaces/base.py +25 -0
  278. agno/os/interfaces/slack/__init__.py +3 -0
  279. agno/os/interfaces/slack/router.py +148 -0
  280. agno/os/interfaces/slack/security.py +30 -0
  281. agno/os/interfaces/slack/slack.py +47 -0
  282. agno/os/interfaces/whatsapp/__init__.py +3 -0
  283. agno/os/interfaces/whatsapp/router.py +210 -0
  284. agno/os/interfaces/whatsapp/security.py +55 -0
  285. agno/os/interfaces/whatsapp/whatsapp.py +36 -0
  286. agno/os/mcp.py +293 -0
  287. agno/os/middleware/__init__.py +9 -0
  288. agno/os/middleware/jwt.py +797 -0
  289. agno/os/router.py +258 -0
  290. agno/os/routers/__init__.py +3 -0
  291. agno/os/routers/agents/__init__.py +3 -0
  292. agno/os/routers/agents/router.py +599 -0
  293. agno/os/routers/agents/schema.py +261 -0
  294. agno/os/routers/evals/__init__.py +3 -0
  295. agno/os/routers/evals/evals.py +450 -0
  296. agno/os/routers/evals/schemas.py +174 -0
  297. agno/os/routers/evals/utils.py +231 -0
  298. agno/os/routers/health.py +31 -0
  299. agno/os/routers/home.py +52 -0
  300. agno/os/routers/knowledge/__init__.py +3 -0
  301. agno/os/routers/knowledge/knowledge.py +1008 -0
  302. agno/os/routers/knowledge/schemas.py +178 -0
  303. agno/os/routers/memory/__init__.py +3 -0
  304. agno/os/routers/memory/memory.py +661 -0
  305. agno/os/routers/memory/schemas.py +88 -0
  306. agno/os/routers/metrics/__init__.py +3 -0
  307. agno/os/routers/metrics/metrics.py +190 -0
  308. agno/os/routers/metrics/schemas.py +47 -0
  309. agno/os/routers/session/__init__.py +3 -0
  310. agno/os/routers/session/session.py +997 -0
  311. agno/os/routers/teams/__init__.py +3 -0
  312. agno/os/routers/teams/router.py +512 -0
  313. agno/os/routers/teams/schema.py +257 -0
  314. agno/os/routers/traces/__init__.py +3 -0
  315. agno/os/routers/traces/schemas.py +414 -0
  316. agno/os/routers/traces/traces.py +499 -0
  317. agno/os/routers/workflows/__init__.py +3 -0
  318. agno/os/routers/workflows/router.py +624 -0
  319. agno/os/routers/workflows/schema.py +75 -0
  320. agno/os/schema.py +534 -0
  321. agno/os/scopes.py +469 -0
  322. agno/{playground → os}/settings.py +7 -15
  323. agno/os/utils.py +973 -0
  324. agno/reasoning/anthropic.py +80 -0
  325. agno/reasoning/azure_ai_foundry.py +67 -0
  326. agno/reasoning/deepseek.py +63 -0
  327. agno/reasoning/default.py +97 -0
  328. agno/reasoning/gemini.py +73 -0
  329. agno/reasoning/groq.py +71 -0
  330. agno/reasoning/helpers.py +24 -1
  331. agno/reasoning/ollama.py +67 -0
  332. agno/reasoning/openai.py +86 -0
  333. agno/reasoning/step.py +2 -1
  334. agno/reasoning/vertexai.py +76 -0
  335. agno/run/__init__.py +6 -0
  336. agno/run/agent.py +822 -0
  337. agno/run/base.py +247 -0
  338. agno/run/cancel.py +81 -0
  339. agno/run/requirement.py +181 -0
  340. agno/run/team.py +767 -0
  341. agno/run/workflow.py +708 -0
  342. agno/session/__init__.py +10 -0
  343. agno/session/agent.py +260 -0
  344. agno/session/summary.py +265 -0
  345. agno/session/team.py +342 -0
  346. agno/session/workflow.py +501 -0
  347. agno/table.py +10 -0
  348. agno/team/__init__.py +37 -0
  349. agno/team/team.py +9536 -0
  350. agno/tools/__init__.py +7 -0
  351. agno/tools/agentql.py +120 -0
  352. agno/tools/airflow.py +22 -12
  353. agno/tools/api.py +122 -0
  354. agno/tools/apify.py +276 -83
  355. agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
  356. agno/tools/aws_lambda.py +28 -7
  357. agno/tools/aws_ses.py +66 -0
  358. agno/tools/baidusearch.py +11 -4
  359. agno/tools/bitbucket.py +292 -0
  360. agno/tools/brandfetch.py +213 -0
  361. agno/tools/bravesearch.py +106 -0
  362. agno/tools/brightdata.py +367 -0
  363. agno/tools/browserbase.py +209 -0
  364. agno/tools/calcom.py +32 -23
  365. agno/tools/calculator.py +24 -37
  366. agno/tools/cartesia.py +187 -0
  367. agno/tools/{clickup_tool.py → clickup.py} +17 -28
  368. agno/tools/confluence.py +91 -26
  369. agno/tools/crawl4ai.py +139 -43
  370. agno/tools/csv_toolkit.py +28 -22
  371. agno/tools/dalle.py +36 -22
  372. agno/tools/daytona.py +475 -0
  373. agno/tools/decorator.py +169 -14
  374. agno/tools/desi_vocal.py +23 -11
  375. agno/tools/discord.py +32 -29
  376. agno/tools/docker.py +716 -0
  377. agno/tools/duckdb.py +76 -81
  378. agno/tools/duckduckgo.py +43 -40
  379. agno/tools/e2b.py +703 -0
  380. agno/tools/eleven_labs.py +65 -54
  381. agno/tools/email.py +13 -5
  382. agno/tools/evm.py +129 -0
  383. agno/tools/exa.py +324 -42
  384. agno/tools/fal.py +39 -35
  385. agno/tools/file.py +196 -30
  386. agno/tools/file_generation.py +356 -0
  387. agno/tools/financial_datasets.py +288 -0
  388. agno/tools/firecrawl.py +108 -33
  389. agno/tools/function.py +960 -122
  390. agno/tools/giphy.py +34 -12
  391. agno/tools/github.py +1294 -97
  392. agno/tools/gmail.py +922 -0
  393. agno/tools/google_bigquery.py +117 -0
  394. agno/tools/google_drive.py +271 -0
  395. agno/tools/google_maps.py +253 -0
  396. agno/tools/googlecalendar.py +607 -107
  397. agno/tools/googlesheets.py +377 -0
  398. agno/tools/hackernews.py +20 -12
  399. agno/tools/jina.py +24 -14
  400. agno/tools/jira.py +48 -19
  401. agno/tools/knowledge.py +218 -0
  402. agno/tools/linear.py +82 -43
  403. agno/tools/linkup.py +58 -0
  404. agno/tools/local_file_system.py +15 -7
  405. agno/tools/lumalab.py +41 -26
  406. agno/tools/mcp/__init__.py +10 -0
  407. agno/tools/mcp/mcp.py +331 -0
  408. agno/tools/mcp/multi_mcp.py +347 -0
  409. agno/tools/mcp/params.py +24 -0
  410. agno/tools/mcp_toolbox.py +284 -0
  411. agno/tools/mem0.py +193 -0
  412. agno/tools/memory.py +419 -0
  413. agno/tools/mlx_transcribe.py +11 -9
  414. agno/tools/models/azure_openai.py +190 -0
  415. agno/tools/models/gemini.py +203 -0
  416. agno/tools/models/groq.py +158 -0
  417. agno/tools/models/morph.py +186 -0
  418. agno/tools/models/nebius.py +124 -0
  419. agno/tools/models_labs.py +163 -82
  420. agno/tools/moviepy_video.py +18 -13
  421. agno/tools/nano_banana.py +151 -0
  422. agno/tools/neo4j.py +134 -0
  423. agno/tools/newspaper.py +15 -4
  424. agno/tools/newspaper4k.py +19 -6
  425. agno/tools/notion.py +204 -0
  426. agno/tools/openai.py +181 -17
  427. agno/tools/openbb.py +27 -20
  428. agno/tools/opencv.py +321 -0
  429. agno/tools/openweather.py +233 -0
  430. agno/tools/oxylabs.py +385 -0
  431. agno/tools/pandas.py +25 -15
  432. agno/tools/parallel.py +314 -0
  433. agno/tools/postgres.py +238 -185
  434. agno/tools/pubmed.py +125 -13
  435. agno/tools/python.py +48 -35
  436. agno/tools/reasoning.py +283 -0
  437. agno/tools/reddit.py +207 -29
  438. agno/tools/redshift.py +406 -0
  439. agno/tools/replicate.py +69 -26
  440. agno/tools/resend.py +11 -6
  441. agno/tools/scrapegraph.py +179 -19
  442. agno/tools/searxng.py +23 -31
  443. agno/tools/serpapi.py +15 -10
  444. agno/tools/serper.py +255 -0
  445. agno/tools/shell.py +23 -12
  446. agno/tools/shopify.py +1519 -0
  447. agno/tools/slack.py +56 -14
  448. agno/tools/sleep.py +8 -6
  449. agno/tools/spider.py +35 -11
  450. agno/tools/spotify.py +919 -0
  451. agno/tools/sql.py +34 -19
  452. agno/tools/tavily.py +158 -8
  453. agno/tools/telegram.py +18 -8
  454. agno/tools/todoist.py +218 -0
  455. agno/tools/toolkit.py +134 -9
  456. agno/tools/trafilatura.py +388 -0
  457. agno/tools/trello.py +25 -28
  458. agno/tools/twilio.py +18 -9
  459. agno/tools/user_control_flow.py +78 -0
  460. agno/tools/valyu.py +228 -0
  461. agno/tools/visualization.py +467 -0
  462. agno/tools/webbrowser.py +28 -0
  463. agno/tools/webex.py +76 -0
  464. agno/tools/website.py +23 -19
  465. agno/tools/webtools.py +45 -0
  466. agno/tools/whatsapp.py +286 -0
  467. agno/tools/wikipedia.py +28 -19
  468. agno/tools/workflow.py +285 -0
  469. agno/tools/{twitter.py → x.py} +142 -46
  470. agno/tools/yfinance.py +41 -39
  471. agno/tools/youtube.py +34 -17
  472. agno/tools/zendesk.py +15 -5
  473. agno/tools/zep.py +454 -0
  474. agno/tools/zoom.py +86 -37
  475. agno/tracing/__init__.py +12 -0
  476. agno/tracing/exporter.py +157 -0
  477. agno/tracing/schemas.py +276 -0
  478. agno/tracing/setup.py +111 -0
  479. agno/utils/agent.py +938 -0
  480. agno/utils/audio.py +37 -1
  481. agno/utils/certs.py +27 -0
  482. agno/utils/code_execution.py +11 -0
  483. agno/utils/common.py +103 -20
  484. agno/utils/cryptography.py +22 -0
  485. agno/utils/dttm.py +33 -0
  486. agno/utils/events.py +700 -0
  487. agno/utils/functions.py +107 -37
  488. agno/utils/gemini.py +426 -0
  489. agno/utils/hooks.py +171 -0
  490. agno/utils/http.py +185 -0
  491. agno/utils/json_schema.py +159 -37
  492. agno/utils/knowledge.py +36 -0
  493. agno/utils/location.py +19 -0
  494. agno/utils/log.py +221 -8
  495. agno/utils/mcp.py +214 -0
  496. agno/utils/media.py +335 -14
  497. agno/utils/merge_dict.py +22 -1
  498. agno/utils/message.py +77 -2
  499. agno/utils/models/ai_foundry.py +50 -0
  500. agno/utils/models/claude.py +373 -0
  501. agno/utils/models/cohere.py +94 -0
  502. agno/utils/models/llama.py +85 -0
  503. agno/utils/models/mistral.py +100 -0
  504. agno/utils/models/openai_responses.py +140 -0
  505. agno/utils/models/schema_utils.py +153 -0
  506. agno/utils/models/watsonx.py +41 -0
  507. agno/utils/openai.py +257 -0
  508. agno/utils/pickle.py +1 -1
  509. agno/utils/pprint.py +124 -8
  510. agno/utils/print_response/agent.py +930 -0
  511. agno/utils/print_response/team.py +1914 -0
  512. agno/utils/print_response/workflow.py +1668 -0
  513. agno/utils/prompts.py +111 -0
  514. agno/utils/reasoning.py +108 -0
  515. agno/utils/response.py +163 -0
  516. agno/utils/serialize.py +32 -0
  517. agno/utils/shell.py +4 -4
  518. agno/utils/streamlit.py +487 -0
  519. agno/utils/string.py +204 -51
  520. agno/utils/team.py +139 -0
  521. agno/utils/timer.py +9 -2
  522. agno/utils/tokens.py +657 -0
  523. agno/utils/tools.py +19 -1
  524. agno/utils/whatsapp.py +305 -0
  525. agno/utils/yaml_io.py +3 -3
  526. agno/vectordb/__init__.py +2 -0
  527. agno/vectordb/base.py +87 -9
  528. agno/vectordb/cassandra/__init__.py +5 -1
  529. agno/vectordb/cassandra/cassandra.py +383 -27
  530. agno/vectordb/chroma/__init__.py +4 -0
  531. agno/vectordb/chroma/chromadb.py +748 -83
  532. agno/vectordb/clickhouse/__init__.py +7 -1
  533. agno/vectordb/clickhouse/clickhousedb.py +554 -53
  534. agno/vectordb/couchbase/__init__.py +3 -0
  535. agno/vectordb/couchbase/couchbase.py +1446 -0
  536. agno/vectordb/lancedb/__init__.py +5 -0
  537. agno/vectordb/lancedb/lance_db.py +730 -98
  538. agno/vectordb/langchaindb/__init__.py +5 -0
  539. agno/vectordb/langchaindb/langchaindb.py +163 -0
  540. agno/vectordb/lightrag/__init__.py +5 -0
  541. agno/vectordb/lightrag/lightrag.py +388 -0
  542. agno/vectordb/llamaindex/__init__.py +3 -0
  543. agno/vectordb/llamaindex/llamaindexdb.py +166 -0
  544. agno/vectordb/milvus/__init__.py +3 -0
  545. agno/vectordb/milvus/milvus.py +966 -78
  546. agno/vectordb/mongodb/__init__.py +9 -1
  547. agno/vectordb/mongodb/mongodb.py +1175 -172
  548. agno/vectordb/pgvector/__init__.py +8 -0
  549. agno/vectordb/pgvector/pgvector.py +599 -115
  550. agno/vectordb/pineconedb/__init__.py +5 -1
  551. agno/vectordb/pineconedb/pineconedb.py +406 -43
  552. agno/vectordb/qdrant/__init__.py +4 -0
  553. agno/vectordb/qdrant/qdrant.py +914 -61
  554. agno/vectordb/redis/__init__.py +9 -0
  555. agno/vectordb/redis/redisdb.py +682 -0
  556. agno/vectordb/singlestore/__init__.py +8 -1
  557. agno/vectordb/singlestore/singlestore.py +771 -0
  558. agno/vectordb/surrealdb/__init__.py +3 -0
  559. agno/vectordb/surrealdb/surrealdb.py +663 -0
  560. agno/vectordb/upstashdb/__init__.py +5 -0
  561. agno/vectordb/upstashdb/upstashdb.py +718 -0
  562. agno/vectordb/weaviate/__init__.py +8 -0
  563. agno/vectordb/weaviate/index.py +15 -0
  564. agno/vectordb/weaviate/weaviate.py +1009 -0
  565. agno/workflow/__init__.py +23 -1
  566. agno/workflow/agent.py +299 -0
  567. agno/workflow/condition.py +759 -0
  568. agno/workflow/loop.py +756 -0
  569. agno/workflow/parallel.py +853 -0
  570. agno/workflow/router.py +723 -0
  571. agno/workflow/step.py +1564 -0
  572. agno/workflow/steps.py +613 -0
  573. agno/workflow/types.py +556 -0
  574. agno/workflow/workflow.py +4327 -514
  575. agno-2.3.13.dist-info/METADATA +639 -0
  576. agno-2.3.13.dist-info/RECORD +613 -0
  577. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
  578. agno-2.3.13.dist-info/licenses/LICENSE +201 -0
  579. agno/api/playground.py +0 -91
  580. agno/api/schemas/playground.py +0 -22
  581. agno/api/schemas/user.py +0 -22
  582. agno/api/schemas/workspace.py +0 -46
  583. agno/api/user.py +0 -160
  584. agno/api/workspace.py +0 -151
  585. agno/cli/auth_server.py +0 -118
  586. agno/cli/config.py +0 -275
  587. agno/cli/console.py +0 -88
  588. agno/cli/credentials.py +0 -23
  589. agno/cli/entrypoint.py +0 -571
  590. agno/cli/operator.py +0 -355
  591. agno/cli/settings.py +0 -85
  592. agno/cli/ws/ws_cli.py +0 -817
  593. agno/constants.py +0 -13
  594. agno/document/__init__.py +0 -1
  595. agno/document/chunking/semantic.py +0 -47
  596. agno/document/chunking/strategy.py +0 -31
  597. agno/document/reader/__init__.py +0 -1
  598. agno/document/reader/arxiv_reader.py +0 -41
  599. agno/document/reader/base.py +0 -22
  600. agno/document/reader/csv_reader.py +0 -84
  601. agno/document/reader/docx_reader.py +0 -46
  602. agno/document/reader/firecrawl_reader.py +0 -99
  603. agno/document/reader/json_reader.py +0 -43
  604. agno/document/reader/pdf_reader.py +0 -219
  605. agno/document/reader/s3/pdf_reader.py +0 -46
  606. agno/document/reader/s3/text_reader.py +0 -51
  607. agno/document/reader/text_reader.py +0 -41
  608. agno/document/reader/website_reader.py +0 -175
  609. agno/document/reader/youtube_reader.py +0 -50
  610. agno/embedder/__init__.py +0 -1
  611. agno/embedder/azure_openai.py +0 -86
  612. agno/embedder/cohere.py +0 -72
  613. agno/embedder/fastembed.py +0 -37
  614. agno/embedder/google.py +0 -73
  615. agno/embedder/huggingface.py +0 -54
  616. agno/embedder/mistral.py +0 -80
  617. agno/embedder/ollama.py +0 -57
  618. agno/embedder/openai.py +0 -74
  619. agno/embedder/sentence_transformer.py +0 -38
  620. agno/embedder/voyageai.py +0 -64
  621. agno/eval/perf.py +0 -201
  622. agno/file/__init__.py +0 -1
  623. agno/file/file.py +0 -16
  624. agno/file/local/csv.py +0 -32
  625. agno/file/local/txt.py +0 -19
  626. agno/infra/app.py +0 -240
  627. agno/infra/base.py +0 -144
  628. agno/infra/context.py +0 -20
  629. agno/infra/db_app.py +0 -52
  630. agno/infra/resource.py +0 -205
  631. agno/infra/resources.py +0 -55
  632. agno/knowledge/agent.py +0 -230
  633. agno/knowledge/arxiv.py +0 -22
  634. agno/knowledge/combined.py +0 -22
  635. agno/knowledge/csv.py +0 -28
  636. agno/knowledge/csv_url.py +0 -19
  637. agno/knowledge/document.py +0 -20
  638. agno/knowledge/docx.py +0 -30
  639. agno/knowledge/json.py +0 -28
  640. agno/knowledge/langchain.py +0 -71
  641. agno/knowledge/llamaindex.py +0 -66
  642. agno/knowledge/pdf.py +0 -28
  643. agno/knowledge/pdf_url.py +0 -26
  644. agno/knowledge/s3/base.py +0 -60
  645. agno/knowledge/s3/pdf.py +0 -21
  646. agno/knowledge/s3/text.py +0 -23
  647. agno/knowledge/text.py +0 -30
  648. agno/knowledge/website.py +0 -88
  649. agno/knowledge/wikipedia.py +0 -31
  650. agno/knowledge/youtube.py +0 -22
  651. agno/memory/agent.py +0 -392
  652. agno/memory/classifier.py +0 -104
  653. agno/memory/db/__init__.py +0 -1
  654. agno/memory/db/base.py +0 -42
  655. agno/memory/db/mongodb.py +0 -189
  656. agno/memory/db/postgres.py +0 -203
  657. agno/memory/db/sqlite.py +0 -193
  658. agno/memory/memory.py +0 -15
  659. agno/memory/row.py +0 -36
  660. agno/memory/summarizer.py +0 -192
  661. agno/memory/summary.py +0 -19
  662. agno/memory/workflow.py +0 -38
  663. agno/models/google/gemini_openai.py +0 -26
  664. agno/models/ollama/hermes.py +0 -221
  665. agno/models/ollama/tools.py +0 -362
  666. agno/models/vertexai/gemini.py +0 -595
  667. agno/playground/__init__.py +0 -3
  668. agno/playground/async_router.py +0 -421
  669. agno/playground/deploy.py +0 -249
  670. agno/playground/operator.py +0 -92
  671. agno/playground/playground.py +0 -91
  672. agno/playground/schemas.py +0 -76
  673. agno/playground/serve.py +0 -55
  674. agno/playground/sync_router.py +0 -405
  675. agno/reasoning/agent.py +0 -68
  676. agno/run/response.py +0 -112
  677. agno/storage/agent/__init__.py +0 -0
  678. agno/storage/agent/base.py +0 -38
  679. agno/storage/agent/dynamodb.py +0 -350
  680. agno/storage/agent/json.py +0 -92
  681. agno/storage/agent/mongodb.py +0 -228
  682. agno/storage/agent/postgres.py +0 -367
  683. agno/storage/agent/session.py +0 -79
  684. agno/storage/agent/singlestore.py +0 -303
  685. agno/storage/agent/sqlite.py +0 -357
  686. agno/storage/agent/yaml.py +0 -93
  687. agno/storage/workflow/__init__.py +0 -0
  688. agno/storage/workflow/base.py +0 -40
  689. agno/storage/workflow/mongodb.py +0 -233
  690. agno/storage/workflow/postgres.py +0 -366
  691. agno/storage/workflow/session.py +0 -60
  692. agno/storage/workflow/sqlite.py +0 -359
  693. agno/tools/googlesearch.py +0 -88
  694. agno/utils/defaults.py +0 -57
  695. agno/utils/filesystem.py +0 -39
  696. agno/utils/git.py +0 -52
  697. agno/utils/json_io.py +0 -30
  698. agno/utils/load_env.py +0 -19
  699. agno/utils/py_io.py +0 -19
  700. agno/utils/pyproject.py +0 -18
  701. agno/utils/resource_filter.py +0 -31
  702. agno/vectordb/singlestore/s2vectordb.py +0 -390
  703. agno/vectordb/singlestore/s2vectordb2.py +0 -355
  704. agno/workspace/__init__.py +0 -0
  705. agno/workspace/config.py +0 -325
  706. agno/workspace/enums.py +0 -6
  707. agno/workspace/helpers.py +0 -48
  708. agno/workspace/operator.py +0 -758
  709. agno/workspace/settings.py +0 -63
  710. agno-0.1.2.dist-info/LICENSE +0 -375
  711. agno-0.1.2.dist-info/METADATA +0 -502
  712. agno-0.1.2.dist-info/RECORD +0 -352
  713. agno-0.1.2.dist-info/entry_points.txt +0 -3
  714. /agno/{cli → db/migrations}/__init__.py +0 -0
  715. /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
  716. /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
  717. /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
  718. /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
  719. /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
  720. /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
  721. /agno/{reranker → utils/models}/__init__.py +0 -0
  722. /agno/{storage → utils/print_response}/__init__.py +0 -0
  723. {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/tools/lumalab.py CHANGED
@@ -1,12 +1,13 @@
1
1
  import time
2
2
  import uuid
3
3
  from os import getenv
4
- from typing import Any, Dict, Literal, Optional, TypedDict
4
+ from typing import Any, Dict, List, Literal, Optional, TypedDict
5
5
 
6
6
  from agno.agent import Agent
7
- from agno.media import VideoArtifact
7
+ from agno.media import Video
8
8
  from agno.tools import Toolkit
9
- from agno.utils.log import logger
9
+ from agno.tools.function import ToolResult
10
+ from agno.utils.log import log_info, logger
10
11
 
11
12
  try:
12
13
  from lumaai import LumaAI # type: ignore
@@ -30,9 +31,11 @@ class LumaLabTools(Toolkit):
30
31
  wait_for_completion: bool = True,
31
32
  poll_interval: int = 3,
32
33
  max_wait_time: int = 300, # 5 minutes
34
+ enable_generate_video: bool = True,
35
+ enable_image_to_video: bool = True,
36
+ all: bool = False,
37
+ **kwargs,
33
38
  ):
34
- super().__init__(name="luma_lab")
35
-
36
39
  self.wait_for_completion = wait_for_completion
37
40
  self.poll_interval = poll_interval
38
41
  self.max_wait_time = max_wait_time
@@ -42,8 +45,14 @@ class LumaLabTools(Toolkit):
42
45
  logger.error("LUMAAI_API_KEY not set. Please set the LUMAAI_API_KEY environment variable.")
43
46
 
44
47
  self.client = LumaAI(auth_token=self.api_key)
45
- self.register(self.generate_video)
46
- self.register(self.image_to_video)
48
+
49
+ tools: List[Any] = []
50
+ if all or enable_generate_video:
51
+ tools.append(self.generate_video)
52
+ if all or enable_image_to_video:
53
+ tools.append(self.image_to_video)
54
+
55
+ super().__init__(name="luma_lab", tools=tools, **kwargs)
47
56
 
48
57
  def image_to_video(
49
58
  self,
@@ -53,7 +62,7 @@ class LumaLabTools(Toolkit):
53
62
  end_image_url: Optional[str] = None,
54
63
  loop: bool = False,
55
64
  aspect_ratio: Literal["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21"] = "16:9",
56
- ) -> str:
65
+ ) -> ToolResult:
57
66
  """Generate a video from one or two images with a prompt.
58
67
 
59
68
  Args:
@@ -65,7 +74,7 @@ class LumaLabTools(Toolkit):
65
74
  aspect_ratio: Aspect ratio of the output video
66
75
 
67
76
  Returns:
68
- str: Status message or error
77
+ ToolResult: A ToolResult containing the generated video or error message.
69
78
  """
70
79
 
71
80
  try:
@@ -87,33 +96,36 @@ class LumaLabTools(Toolkit):
87
96
  video_id = str(uuid.uuid4())
88
97
 
89
98
  if not self.wait_for_completion:
90
- return "Async generation unsupported"
99
+ return ToolResult(content="Async generation unsupported")
91
100
 
92
101
  # Poll for completion
93
102
  seconds_waited = 0
94
103
  while seconds_waited < self.max_wait_time:
95
104
  if not generation or not generation.id:
96
- return "Failed to get generation ID"
105
+ return ToolResult(content="Failed to get generation ID")
97
106
 
98
107
  generation = self.client.generations.get(generation.id)
99
108
 
100
109
  if generation.state == "completed" and generation.assets:
101
110
  video_url = generation.assets.video
102
111
  if video_url:
103
- agent.add_video(VideoArtifact(id=video_id, url=video_url, eta="completed"))
104
- return f"Video generated successfully: {video_url}"
112
+ video_artifact = Video(id=video_id, url=video_url, eta="completed")
113
+ return ToolResult(
114
+ content=f"Video generated successfully: {video_url}",
115
+ videos=[video_artifact],
116
+ )
105
117
  elif generation.state == "failed":
106
- return f"Generation failed: {generation.failure_reason}"
118
+ return ToolResult(content=f"Generation failed: {generation.failure_reason}")
107
119
 
108
- logger.info(f"Generation in progress... State: {generation.state}")
120
+ log_info(f"Generation in progress... State: {generation.state}")
109
121
  time.sleep(self.poll_interval)
110
122
  seconds_waited += self.poll_interval
111
123
 
112
- return f"Video generation timed out after {self.max_wait_time} seconds"
124
+ return ToolResult(content=f"Video generation timed out after {self.max_wait_time} seconds")
113
125
 
114
126
  except Exception as e:
115
127
  logger.error(f"Failed to generate video: {e}")
116
- return f"Error: {e}"
128
+ return ToolResult(content=f"Error: {e}")
117
129
 
118
130
  def generate_video(
119
131
  self,
@@ -122,7 +134,7 @@ class LumaLabTools(Toolkit):
122
134
  loop: bool = False,
123
135
  aspect_ratio: Literal["1:1", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21"] = "16:9",
124
136
  keyframes: Optional[Dict[str, Dict[str, str]]] = None,
125
- ) -> str:
137
+ ) -> ToolResult:
126
138
  """Use this function to generate a video given a prompt."""
127
139
 
128
140
  try:
@@ -139,30 +151,33 @@ class LumaLabTools(Toolkit):
139
151
 
140
152
  video_id = str(uuid.uuid4())
141
153
  if not self.wait_for_completion:
142
- return "Async generation unsupported"
154
+ return ToolResult(content="Async generation unsupported")
143
155
 
144
156
  # Poll for completion
145
157
  seconds_waited = 0
146
158
  while seconds_waited < self.max_wait_time:
147
159
  if not generation or not generation.id:
148
- return "Failed to get generation ID"
160
+ return ToolResult(content="Failed to get generation ID")
149
161
 
150
162
  generation = self.client.generations.get(generation.id)
151
163
 
152
164
  if generation.state == "completed" and generation.assets:
153
165
  video_url = generation.assets.video
154
166
  if video_url:
155
- agent.add_video(VideoArtifact(id=video_id, url=video_url, state="completed"))
156
- return f"Video generated successfully: {video_url}"
167
+ video_artifact = Video(id=video_id, url=video_url, state="completed")
168
+ return ToolResult(
169
+ content=f"Video generated successfully: {video_url}",
170
+ videos=[video_artifact],
171
+ )
157
172
  elif generation.state == "failed":
158
- return f"Generation failed: {generation.failure_reason}"
173
+ return ToolResult(content=f"Generation failed: {generation.failure_reason}")
159
174
 
160
- logger.info(f"Generation in progress... State: {generation.state}")
175
+ log_info(f"Generation in progress... State: {generation.state}")
161
176
  time.sleep(self.poll_interval)
162
177
  seconds_waited += self.poll_interval
163
178
 
164
- return f"Video generation timed out after {self.max_wait_time} seconds"
179
+ return ToolResult(content=f"Video generation timed out after {self.max_wait_time} seconds")
165
180
 
166
181
  except Exception as e:
167
182
  logger.error(f"Failed to generate video: {e}")
168
- return f"Error: {e}"
183
+ return ToolResult(content=f"Error: {e}")
@@ -0,0 +1,10 @@
1
+ from agno.tools.mcp.mcp import MCPTools
2
+ from agno.tools.mcp.multi_mcp import MultiMCPTools
3
+ from agno.tools.mcp.params import SSEClientParams, StreamableHTTPClientParams
4
+
5
+ __all__ = [
6
+ "MCPTools",
7
+ "MultiMCPTools",
8
+ "StreamableHTTPClientParams",
9
+ "SSEClientParams",
10
+ ]
agno/tools/mcp/mcp.py ADDED
@@ -0,0 +1,331 @@
1
+ import weakref
2
+ from dataclasses import asdict
3
+ from datetime import timedelta
4
+ from typing import Any, Literal, Optional, Union
5
+
6
+ from agno.tools import Toolkit
7
+ from agno.tools.function import Function
8
+ from agno.tools.mcp.params import SSEClientParams, StreamableHTTPClientParams
9
+ from agno.utils.log import log_debug, log_error, log_info
10
+ from agno.utils.mcp import get_entrypoint_for_tool, prepare_command
11
+
12
+ try:
13
+ from mcp import ClientSession, StdioServerParameters
14
+ from mcp.client.sse import sse_client
15
+ from mcp.client.stdio import get_default_environment, stdio_client
16
+ from mcp.client.streamable_http import streamablehttp_client
17
+ except (ImportError, ModuleNotFoundError):
18
+ raise ImportError("`mcp` not installed. Please install using `pip install mcp`")
19
+
20
+
21
+ class MCPTools(Toolkit):
22
+ """
23
+ A toolkit for integrating Model Context Protocol (MCP) servers with Agno agents.
24
+ This allows agents to access tools, resources, and prompts exposed by MCP servers.
25
+
26
+ Can be used in three ways:
27
+ 1. Direct initialization with a ClientSession
28
+ 2. As an async context manager with StdioServerParameters
29
+ 3. As an async context manager with SSE or Streamable HTTP client parameters
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ command: Optional[str] = None,
35
+ *,
36
+ url: Optional[str] = None,
37
+ env: Optional[dict[str, str]] = None,
38
+ transport: Literal["stdio", "sse", "streamable-http"] = "stdio",
39
+ server_params: Optional[Union[StdioServerParameters, SSEClientParams, StreamableHTTPClientParams]] = None,
40
+ session: Optional[ClientSession] = None,
41
+ timeout_seconds: int = 10,
42
+ client=None,
43
+ include_tools: Optional[list[str]] = None,
44
+ exclude_tools: Optional[list[str]] = None,
45
+ refresh_connection: bool = False,
46
+ tool_name_prefix: Optional[str] = None,
47
+ **kwargs,
48
+ ):
49
+ """
50
+ Initialize the MCP toolkit.
51
+
52
+ Args:
53
+ session: An initialized MCP ClientSession connected to an MCP server
54
+ server_params: Parameters for creating a new session
55
+ command: The command to run to start the server. Should be used in conjunction with env.
56
+ url: The URL endpoint for SSE or Streamable HTTP connection when transport is "sse" or "streamable-http".
57
+ env: The environment variables to pass to the server. Should be used in conjunction with command.
58
+ client: The underlying MCP client (optional, used to prevent garbage collection)
59
+ timeout_seconds: Read timeout in seconds for the MCP client
60
+ include_tools: Optional list of tool names to include (if None, includes all)
61
+ exclude_tools: Optional list of tool names to exclude (if None, excludes none)
62
+ transport: The transport protocol to use, either "stdio" or "sse" or "streamable-http"
63
+ refresh_connection: If True, the connection and tools will be refreshed on each run
64
+ """
65
+ super().__init__(name="MCPTools", **kwargs)
66
+
67
+ if transport == "sse":
68
+ log_info("SSE as a standalone transport is deprecated. Please use Streamable HTTP instead.")
69
+
70
+ # Set these after `__init__` to bypass the `_check_tools_filters`
71
+ # because tools are not available until `initialize()` is called.
72
+ self.include_tools = include_tools
73
+ self.exclude_tools = exclude_tools
74
+ self.refresh_connection = refresh_connection
75
+ self.tool_name_prefix = tool_name_prefix
76
+
77
+ if session is None and server_params is None:
78
+ if transport == "sse" and url is None:
79
+ raise ValueError("One of 'url' or 'server_params' parameters must be provided when using SSE transport")
80
+ if transport == "stdio" and command is None:
81
+ raise ValueError(
82
+ "One of 'command' or 'server_params' parameters must be provided when using stdio transport"
83
+ )
84
+ if transport == "streamable-http" and url is None:
85
+ raise ValueError(
86
+ "One of 'url' or 'server_params' parameters must be provided when using Streamable HTTP transport"
87
+ )
88
+
89
+ # Ensure the received server_params are valid for the given transport
90
+ if server_params is not None:
91
+ if transport == "sse":
92
+ if not isinstance(server_params, SSEClientParams):
93
+ raise ValueError(
94
+ "If using the SSE transport, server_params must be an instance of SSEClientParams."
95
+ )
96
+ elif transport == "stdio":
97
+ if not isinstance(server_params, StdioServerParameters):
98
+ raise ValueError(
99
+ "If using the stdio transport, server_params must be an instance of StdioServerParameters."
100
+ )
101
+ elif transport == "streamable-http":
102
+ if not isinstance(server_params, StreamableHTTPClientParams):
103
+ raise ValueError(
104
+ "If using the streamable-http transport, server_params must be an instance of StreamableHTTPClientParams."
105
+ )
106
+
107
+ self.timeout_seconds = timeout_seconds
108
+ self.session: Optional[ClientSession] = session
109
+ self.server_params: Optional[Union[StdioServerParameters, SSEClientParams, StreamableHTTPClientParams]] = (
110
+ server_params
111
+ )
112
+ self.transport = transport
113
+ self.url = url
114
+
115
+ # Merge provided env with system env
116
+ if env is not None:
117
+ env = {
118
+ **get_default_environment(),
119
+ **env,
120
+ }
121
+ else:
122
+ env = get_default_environment()
123
+
124
+ if command is not None and transport not in ["sse", "streamable-http"]:
125
+ parts = prepare_command(command)
126
+ cmd = parts[0]
127
+ arguments = parts[1:] if len(parts) > 1 else []
128
+ self.server_params = StdioServerParameters(command=cmd, args=arguments, env=env)
129
+
130
+ self._client = client
131
+
132
+ self._initialized = False
133
+ self._connection_task = None
134
+ self._active_contexts: list[Any] = []
135
+ self._context = None
136
+ self._session_context = None
137
+
138
+ def cleanup():
139
+ """Cancel active connections"""
140
+ if self._connection_task and not self._connection_task.done():
141
+ self._connection_task.cancel()
142
+
143
+ # Setup cleanup logic before the instance is garbage collected
144
+ self._cleanup_finalizer = weakref.finalize(self, cleanup)
145
+
146
+ @property
147
+ def initialized(self) -> bool:
148
+ return self._initialized
149
+
150
+ async def is_alive(self) -> bool:
151
+ if self.session is None:
152
+ return False
153
+ try:
154
+ await self.session.send_ping()
155
+ return True
156
+ except (RuntimeError, BaseException):
157
+ return False
158
+
159
+ async def connect(self, force: bool = False):
160
+ """Initialize a MCPTools instance and connect to the contextual MCP server"""
161
+
162
+ if force:
163
+ # Clean up the session and context so we force a new connection
164
+ self.session = None
165
+ self._context = None
166
+ self._session_context = None
167
+ self._initialized = False
168
+ self._connection_task = None
169
+ self._active_contexts = []
170
+
171
+ if self._initialized:
172
+ return
173
+
174
+ try:
175
+ await self._connect()
176
+ except (RuntimeError, BaseException) as e:
177
+ log_error(f"Failed to connect to {str(self)}: {e}")
178
+
179
+ async def _connect(self) -> None:
180
+ """Connects to the MCP server and initializes the tools"""
181
+
182
+ if self._initialized:
183
+ return
184
+
185
+ if self.session is not None:
186
+ await self.initialize()
187
+ return
188
+
189
+ # Create a new studio session
190
+ if self.transport == "sse":
191
+ sse_params = asdict(self.server_params) if self.server_params is not None else {} # type: ignore
192
+ if "url" not in sse_params:
193
+ sse_params["url"] = self.url
194
+ self._context = sse_client(**sse_params) # type: ignore
195
+ client_timeout = min(self.timeout_seconds, sse_params.get("timeout", self.timeout_seconds))
196
+
197
+ # Create a new streamable HTTP session
198
+ elif self.transport == "streamable-http":
199
+ streamable_http_params = asdict(self.server_params) if self.server_params is not None else {} # type: ignore
200
+ if "url" not in streamable_http_params:
201
+ streamable_http_params["url"] = self.url
202
+ self._context = streamablehttp_client(**streamable_http_params) # type: ignore
203
+ params_timeout = streamable_http_params.get("timeout", self.timeout_seconds)
204
+ if isinstance(params_timeout, timedelta):
205
+ params_timeout = int(params_timeout.total_seconds())
206
+ client_timeout = min(self.timeout_seconds, params_timeout)
207
+
208
+ else:
209
+ if self.server_params is None:
210
+ raise ValueError("server_params must be provided when using stdio transport.")
211
+ self._context = stdio_client(self.server_params) # type: ignore
212
+ client_timeout = self.timeout_seconds
213
+
214
+ session_params = await self._context.__aenter__() # type: ignore
215
+ self._active_contexts.append(self._context)
216
+ read, write = session_params[0:2]
217
+
218
+ self._session_context = ClientSession(read, write, read_timeout_seconds=timedelta(seconds=client_timeout)) # type: ignore
219
+ self.session = await self._session_context.__aenter__() # type: ignore
220
+ self._active_contexts.append(self._session_context)
221
+
222
+ # Initialize with the new session
223
+ await self.initialize()
224
+
225
+ async def close(self) -> None:
226
+ """Close the MCP connection and clean up resources"""
227
+ if not self._initialized:
228
+ return
229
+
230
+ try:
231
+ if self._session_context is not None:
232
+ await self._session_context.__aexit__(None, None, None)
233
+ self.session = None
234
+ self._session_context = None
235
+
236
+ if self._context is not None:
237
+ await self._context.__aexit__(None, None, None)
238
+ self._context = None
239
+ except (RuntimeError, BaseException) as e:
240
+ log_error(f"Failed to close MCP connection: {e}")
241
+
242
+ self._initialized = False
243
+
244
+ async def __aenter__(self) -> "MCPTools":
245
+ await self._connect()
246
+ return self
247
+
248
+ async def __aexit__(self, _exc_type, _exc_val, _exc_tb):
249
+ """Exit the async context manager."""
250
+ if self._session_context is not None:
251
+ await self._session_context.__aexit__(_exc_type, _exc_val, _exc_tb)
252
+ self.session = None
253
+ self._session_context = None
254
+
255
+ if self._context is not None:
256
+ await self._context.__aexit__(_exc_type, _exc_val, _exc_tb)
257
+ self._context = None
258
+
259
+ self._initialized = False
260
+
261
+ async def build_tools(self) -> None:
262
+ """Build the tools for the MCP toolkit"""
263
+ if self.session is None:
264
+ raise ValueError("Session is not initialized")
265
+
266
+ try:
267
+ # Get the list of tools from the MCP server
268
+ available_tools = await self.session.list_tools() # type: ignore
269
+
270
+ self._check_tools_filters(
271
+ available_tools=[tool.name for tool in available_tools.tools],
272
+ include_tools=self.include_tools,
273
+ exclude_tools=self.exclude_tools,
274
+ )
275
+
276
+ # Filter tools based on include/exclude lists
277
+ filtered_tools = []
278
+ for tool in available_tools.tools:
279
+ if self.exclude_tools and tool.name in self.exclude_tools:
280
+ continue
281
+ if self.include_tools is None or tool.name in self.include_tools:
282
+ filtered_tools.append(tool)
283
+
284
+ # Get tool name prefix if available
285
+ tool_name_prefix = ""
286
+ if self.tool_name_prefix is not None:
287
+ tool_name_prefix = self.tool_name_prefix + "_"
288
+
289
+ # Register the tools with the toolkit
290
+ for tool in filtered_tools:
291
+ try:
292
+ # Get an entrypoint for the tool
293
+ entrypoint = get_entrypoint_for_tool(tool, self.session) # type: ignore
294
+ # Create a Function for the tool
295
+ f = Function(
296
+ name=tool_name_prefix + tool.name,
297
+ description=tool.description,
298
+ parameters=tool.inputSchema,
299
+ entrypoint=entrypoint,
300
+ # Set skip_entrypoint_processing to True to avoid processing the entrypoint
301
+ skip_entrypoint_processing=True,
302
+ )
303
+
304
+ # Register the Function with the toolkit
305
+ self.functions[f.name] = f
306
+ log_debug(f"Function: {f.name} registered with {self.name}")
307
+ except Exception as e:
308
+ log_error(f"Failed to register tool {tool.name}: {e}")
309
+
310
+ except (RuntimeError, BaseException) as e:
311
+ log_error(f"Failed to get tools for {str(self)}: {e}")
312
+ raise
313
+
314
+ async def initialize(self) -> None:
315
+ """Initialize the MCP toolkit by getting available tools from the MCP server"""
316
+ if self._initialized:
317
+ return
318
+
319
+ try:
320
+ if self.session is None:
321
+ raise ValueError("Session is not initialized")
322
+
323
+ # Initialize the session if not already initialized
324
+ await self.session.initialize()
325
+
326
+ await self.build_tools()
327
+
328
+ self._initialized = True
329
+
330
+ except (RuntimeError, BaseException) as e:
331
+ log_error(f"Failed to initialize MCP toolkit: {e}")