letta-client 0.1.233__py3-none-any.whl → 0.1.234__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of letta-client might be problematic. Click here for more details.

Files changed (438) hide show
  1. letta_client/__init__.py +2 -0
  2. letta_client/agents/__init__.py +2 -0
  3. letta_client/agents/blocks/__init__.py +2 -0
  4. letta_client/agents/blocks/client.py +72 -313
  5. letta_client/agents/blocks/raw_client.py +654 -0
  6. letta_client/agents/client.py +329 -869
  7. letta_client/agents/context/__init__.py +2 -0
  8. letta_client/agents/context/client.py +31 -66
  9. letta_client/agents/context/raw_client.py +122 -0
  10. letta_client/agents/core_memory/__init__.py +2 -0
  11. letta_client/agents/core_memory/client.py +31 -66
  12. letta_client/agents/core_memory/raw_client.py +124 -0
  13. letta_client/agents/files/__init__.py +2 -0
  14. letta_client/agents/files/client.py +39 -178
  15. letta_client/agents/files/raw_client.py +349 -0
  16. letta_client/agents/folders/__init__.py +2 -0
  17. letta_client/agents/folders/client.py +39 -178
  18. letta_client/agents/folders/raw_client.py +327 -0
  19. letta_client/agents/groups/__init__.py +2 -0
  20. letta_client/agents/groups/client.py +31 -72
  21. letta_client/agents/groups/raw_client.py +142 -0
  22. letta_client/agents/memory_variables/__init__.py +2 -0
  23. letta_client/agents/memory_variables/client.py +31 -65
  24. letta_client/agents/memory_variables/raw_client.py +125 -0
  25. letta_client/agents/memory_variables/types/__init__.py +2 -0
  26. letta_client/agents/memory_variables/types/memory_variables_list_response.py +3 -2
  27. letta_client/agents/messages/__init__.py +2 -0
  28. letta_client/agents/messages/client.py +150 -589
  29. letta_client/agents/messages/raw_client.py +1384 -0
  30. letta_client/agents/messages/types/__init__.py +2 -0
  31. letta_client/agents/messages/types/letta_streaming_response.py +6 -5
  32. letta_client/agents/messages/types/messages_modify_request.py +3 -2
  33. letta_client/agents/messages/types/messages_modify_response.py +5 -4
  34. letta_client/agents/messages/types/messages_preview_raw_payload_request.py +1 -0
  35. letta_client/agents/passages/__init__.py +2 -0
  36. letta_client/agents/passages/client.py +89 -301
  37. letta_client/agents/passages/raw_client.py +678 -0
  38. letta_client/agents/raw_client.py +2068 -0
  39. letta_client/agents/sources/__init__.py +2 -0
  40. letta_client/agents/sources/client.py +39 -178
  41. letta_client/agents/sources/raw_client.py +327 -0
  42. letta_client/agents/templates/__init__.py +2 -0
  43. letta_client/agents/templates/client.py +57 -276
  44. letta_client/agents/templates/raw_client.py +505 -0
  45. letta_client/agents/templates/types/__init__.py +2 -0
  46. letta_client/agents/templates/types/templates_create_response.py +5 -4
  47. letta_client/agents/templates/types/templates_migrate_response.py +3 -2
  48. letta_client/agents/tools/__init__.py +2 -0
  49. letta_client/agents/tools/client.py +40 -179
  50. letta_client/agents/tools/raw_client.py +327 -0
  51. letta_client/agents/types/__init__.py +2 -0
  52. letta_client/agents/types/agents_search_request_search_item.py +4 -3
  53. letta_client/agents/types/agents_search_request_search_item_field.py +4 -3
  54. letta_client/agents/types/agents_search_request_search_item_one.py +4 -3
  55. letta_client/agents/types/agents_search_request_search_item_three.py +3 -2
  56. letta_client/agents/types/agents_search_request_search_item_two.py +3 -2
  57. letta_client/agents/types/agents_search_request_search_item_zero.py +3 -2
  58. letta_client/agents/types/agents_search_response.py +5 -4
  59. letta_client/agents/types/create_agent_request_response_format.py +1 -0
  60. letta_client/agents/types/create_agent_request_tool_rules_item.py +4 -3
  61. letta_client/agents/types/update_agent_response_format.py +1 -0
  62. letta_client/agents/types/update_agent_tool_rules_item.py +4 -3
  63. letta_client/base_client.py +41 -49
  64. letta_client/batches/__init__.py +2 -0
  65. letta_client/batches/client.py +45 -253
  66. letta_client/batches/raw_client.py +457 -0
  67. letta_client/blocks/__init__.py +2 -0
  68. letta_client/blocks/agents/__init__.py +2 -0
  69. letta_client/blocks/agents/client.py +33 -70
  70. letta_client/blocks/agents/raw_client.py +144 -0
  71. letta_client/blocks/client.py +126 -424
  72. letta_client/blocks/raw_client.py +973 -0
  73. letta_client/client_side_access_tokens/__init__.py +2 -0
  74. letta_client/client_side_access_tokens/client.py +45 -216
  75. letta_client/client_side_access_tokens/raw_client.py +435 -0
  76. letta_client/client_side_access_tokens/types/__init__.py +2 -0
  77. letta_client/client_side_access_tokens/types/client_side_access_tokens_create_request_policy_item.py +4 -3
  78. letta_client/client_side_access_tokens/types/client_side_access_tokens_create_response.py +6 -5
  79. letta_client/client_side_access_tokens/types/client_side_access_tokens_create_response_policy.py +4 -3
  80. letta_client/client_side_access_tokens/types/client_side_access_tokens_create_response_policy_data_item.py +4 -3
  81. letta_client/client_side_access_tokens/types/client_side_access_tokens_list_client_side_access_tokens_response.py +6 -5
  82. letta_client/client_side_access_tokens/types/client_side_access_tokens_list_client_side_access_tokens_response_tokens_item.py +6 -5
  83. letta_client/client_side_access_tokens/types/client_side_access_tokens_list_client_side_access_tokens_response_tokens_item_policy.py +4 -3
  84. letta_client/client_side_access_tokens/types/client_side_access_tokens_list_client_side_access_tokens_response_tokens_item_policy_data_item.py +4 -3
  85. letta_client/core/__init__.py +5 -0
  86. letta_client/core/api_error.py +13 -5
  87. letta_client/core/client_wrapper.py +14 -5
  88. letta_client/core/force_multipart.py +16 -0
  89. letta_client/core/http_client.py +70 -26
  90. letta_client/core/http_response.py +55 -0
  91. letta_client/core/jsonable_encoder.py +0 -1
  92. letta_client/core/pydantic_utilities.py +70 -111
  93. letta_client/core/serialization.py +7 -3
  94. letta_client/core/unchecked_base_model.py +40 -4
  95. letta_client/embedding_models/__init__.py +2 -0
  96. letta_client/embedding_models/client.py +31 -65
  97. letta_client/embedding_models/raw_client.py +117 -0
  98. letta_client/errors/__init__.py +2 -0
  99. letta_client/errors/bad_request_error.py +4 -3
  100. letta_client/errors/conflict_error.py +4 -2
  101. letta_client/errors/internal_server_error.py +4 -3
  102. letta_client/errors/not_found_error.py +4 -3
  103. letta_client/errors/payment_required_error.py +4 -2
  104. letta_client/errors/unprocessable_entity_error.py +4 -2
  105. letta_client/folders/__init__.py +2 -0
  106. letta_client/folders/client.py +100 -564
  107. letta_client/folders/files/__init__.py +2 -0
  108. letta_client/folders/files/client.py +44 -189
  109. letta_client/folders/files/raw_client.py +391 -0
  110. letta_client/folders/passages/__init__.py +2 -0
  111. letta_client/folders/passages/client.py +33 -74
  112. letta_client/folders/passages/raw_client.py +162 -0
  113. letta_client/folders/raw_client.py +1084 -0
  114. letta_client/groups/__init__.py +2 -0
  115. letta_client/groups/client.py +87 -406
  116. letta_client/groups/messages/__init__.py +2 -0
  117. letta_client/groups/messages/client.py +110 -371
  118. letta_client/groups/messages/raw_client.py +881 -0
  119. letta_client/groups/messages/types/__init__.py +2 -0
  120. letta_client/groups/messages/types/letta_streaming_response.py +5 -4
  121. letta_client/groups/messages/types/messages_modify_request.py +3 -2
  122. letta_client/groups/messages/types/messages_modify_response.py +5 -4
  123. letta_client/groups/raw_client.py +807 -0
  124. letta_client/groups/types/__init__.py +2 -0
  125. letta_client/groups/types/group_create_manager_config.py +1 -0
  126. letta_client/groups/types/group_update_manager_config.py +1 -0
  127. letta_client/health/__init__.py +2 -0
  128. letta_client/health/client.py +31 -43
  129. letta_client/health/raw_client.py +85 -0
  130. letta_client/identities/__init__.py +2 -0
  131. letta_client/identities/client.py +115 -498
  132. letta_client/identities/properties/__init__.py +2 -0
  133. letta_client/identities/properties/client.py +32 -76
  134. letta_client/identities/properties/raw_client.py +152 -0
  135. letta_client/identities/raw_client.py +1010 -0
  136. letta_client/jobs/__init__.py +2 -0
  137. letta_client/jobs/client.py +67 -310
  138. letta_client/jobs/raw_client.py +624 -0
  139. letta_client/messages/__init__.py +2 -0
  140. letta_client/messages/client.py +41 -74
  141. letta_client/messages/raw_client.py +186 -0
  142. letta_client/models/__init__.py +2 -0
  143. letta_client/models/client.py +39 -73
  144. letta_client/models/raw_client.py +151 -0
  145. letta_client/projects/__init__.py +2 -0
  146. letta_client/projects/client.py +31 -53
  147. letta_client/projects/raw_client.py +125 -0
  148. letta_client/projects/types/__init__.py +2 -0
  149. letta_client/projects/types/projects_list_response.py +5 -4
  150. letta_client/projects/types/projects_list_response_projects_item.py +3 -2
  151. letta_client/providers/__init__.py +2 -0
  152. letta_client/providers/client.py +62 -335
  153. letta_client/providers/raw_client.py +664 -0
  154. letta_client/runs/__init__.py +2 -0
  155. letta_client/runs/client.py +56 -258
  156. letta_client/runs/messages/__init__.py +2 -0
  157. letta_client/runs/messages/client.py +34 -79
  158. letta_client/runs/messages/raw_client.py +209 -0
  159. letta_client/runs/raw_client.py +440 -0
  160. letta_client/runs/steps/__init__.py +2 -0
  161. letta_client/runs/steps/client.py +33 -76
  162. letta_client/runs/steps/raw_client.py +192 -0
  163. letta_client/runs/usage/__init__.py +2 -0
  164. letta_client/runs/usage/client.py +31 -66
  165. letta_client/runs/usage/raw_client.py +122 -0
  166. letta_client/sources/__init__.py +2 -0
  167. letta_client/sources/client.py +107 -625
  168. letta_client/sources/files/__init__.py +2 -0
  169. letta_client/sources/files/client.py +44 -189
  170. letta_client/sources/files/raw_client.py +391 -0
  171. letta_client/sources/passages/__init__.py +2 -0
  172. letta_client/sources/passages/client.py +33 -74
  173. letta_client/sources/passages/raw_client.py +162 -0
  174. letta_client/sources/raw_client.py +1209 -0
  175. letta_client/steps/__init__.py +2 -0
  176. letta_client/steps/client.py +65 -153
  177. letta_client/steps/feedback/__init__.py +2 -0
  178. letta_client/steps/feedback/client.py +32 -73
  179. letta_client/steps/feedback/raw_client.py +141 -0
  180. letta_client/steps/raw_client.py +355 -0
  181. letta_client/steps/types/__init__.py +2 -0
  182. letta_client/tags/__init__.py +2 -0
  183. letta_client/tags/client.py +33 -73
  184. letta_client/tags/raw_client.py +148 -0
  185. letta_client/telemetry/__init__.py +2 -0
  186. letta_client/telemetry/client.py +31 -66
  187. letta_client/telemetry/raw_client.py +118 -0
  188. letta_client/templates/__init__.py +2 -0
  189. letta_client/templates/agents/__init__.py +2 -0
  190. letta_client/templates/agents/client.py +48 -96
  191. letta_client/templates/agents/raw_client.py +227 -0
  192. letta_client/templates/agents/types/__init__.py +2 -0
  193. letta_client/templates/agents/types/agents_create_request_initial_message_sequence_item.py +4 -3
  194. letta_client/templates/agents/types/agents_create_response.py +4 -3
  195. letta_client/templates/client.py +36 -57
  196. letta_client/templates/raw_client.py +133 -0
  197. letta_client/templates/types/__init__.py +2 -0
  198. letta_client/templates/types/templates_list_response.py +5 -4
  199. letta_client/templates/types/templates_list_response_templates_item.py +3 -2
  200. letta_client/tools/__init__.py +2 -0
  201. letta_client/tools/client.py +195 -1322
  202. letta_client/tools/raw_client.py +2565 -0
  203. letta_client/tools/types/__init__.py +2 -0
  204. letta_client/tools/types/add_mcp_server_request.py +2 -1
  205. letta_client/tools/types/add_mcp_server_response_item.py +2 -1
  206. letta_client/tools/types/connect_mcp_server_request.py +2 -1
  207. letta_client/tools/types/delete_mcp_server_response_item.py +2 -1
  208. letta_client/tools/types/list_mcp_servers_response_value.py +1 -0
  209. letta_client/tools/types/streaming_response.py +5 -4
  210. letta_client/tools/types/test_mcp_server_request.py +2 -1
  211. letta_client/tools/types/update_mcp_server_request.py +2 -1
  212. letta_client/tools/types/update_mcp_server_response.py +2 -1
  213. letta_client/types/__init__.py +2 -0
  214. letta_client/types/action_model.py +6 -5
  215. letta_client/types/action_parameters_model.py +3 -2
  216. letta_client/types/action_response_model.py +3 -2
  217. letta_client/types/agent_environment_variable.py +3 -2
  218. letta_client/types/agent_schema.py +7 -6
  219. letta_client/types/agent_schema_tool_rules_item.py +2 -1
  220. letta_client/types/agent_state.py +9 -8
  221. letta_client/types/agent_state_response_format.py +1 -0
  222. letta_client/types/agent_state_tool_rules_item.py +4 -3
  223. letta_client/types/app_auth_scheme.py +4 -3
  224. letta_client/types/app_model.py +5 -4
  225. letta_client/types/assistant_message.py +3 -2
  226. letta_client/types/assistant_message_content.py +1 -0
  227. letta_client/types/audio.py +3 -2
  228. letta_client/types/auth_request.py +2 -1
  229. letta_client/types/auth_response.py +5 -4
  230. letta_client/types/auth_scheme_field.py +3 -2
  231. letta_client/types/bad_request_error_body.py +3 -2
  232. letta_client/types/base_64_image.py +2 -1
  233. letta_client/types/base_tool_rule_schema.py +3 -2
  234. letta_client/types/batch_job.py +4 -3
  235. letta_client/types/block.py +3 -2
  236. letta_client/types/block_update.py +2 -1
  237. letta_client/types/chat_completion_assistant_message_param.py +5 -4
  238. letta_client/types/chat_completion_assistant_message_param_content.py +1 -0
  239. letta_client/types/chat_completion_assistant_message_param_content_item.py +2 -1
  240. letta_client/types/chat_completion_audio_param.py +4 -3
  241. letta_client/types/chat_completion_content_part_image_param.py +4 -3
  242. letta_client/types/chat_completion_content_part_input_audio_param.py +4 -3
  243. letta_client/types/chat_completion_content_part_refusal_param.py +3 -2
  244. letta_client/types/chat_completion_content_part_text_param.py +3 -2
  245. letta_client/types/chat_completion_developer_message_param.py +4 -3
  246. letta_client/types/chat_completion_developer_message_param_content.py +1 -0
  247. letta_client/types/chat_completion_function_call_option_param.py +3 -2
  248. letta_client/types/chat_completion_function_message_param.py +3 -2
  249. letta_client/types/chat_completion_message_tool_call.py +4 -3
  250. letta_client/types/chat_completion_message_tool_call_param.py +4 -3
  251. letta_client/types/chat_completion_named_tool_choice_param.py +4 -3
  252. letta_client/types/chat_completion_prediction_content_param.py +4 -3
  253. letta_client/types/chat_completion_prediction_content_param_content.py +1 -0
  254. letta_client/types/chat_completion_stream_options_param.py +3 -2
  255. letta_client/types/chat_completion_system_message_param.py +4 -3
  256. letta_client/types/chat_completion_system_message_param_content.py +1 -0
  257. letta_client/types/chat_completion_tool_message_param.py +4 -3
  258. letta_client/types/chat_completion_tool_message_param_content.py +1 -0
  259. letta_client/types/chat_completion_tool_param.py +4 -3
  260. letta_client/types/chat_completion_user_message_param.py +4 -3
  261. letta_client/types/chat_completion_user_message_param_content.py +1 -0
  262. letta_client/types/chat_completion_user_message_param_content_item.py +2 -1
  263. letta_client/types/child_tool_rule.py +3 -2
  264. letta_client/types/child_tool_rule_schema.py +3 -2
  265. letta_client/types/code_input.py +3 -2
  266. letta_client/types/completion_create_params_non_streaming.py +10 -9
  267. letta_client/types/completion_create_params_non_streaming_function_call.py +1 -0
  268. letta_client/types/completion_create_params_non_streaming_messages_item.py +4 -3
  269. letta_client/types/completion_create_params_non_streaming_response_format.py +3 -2
  270. letta_client/types/completion_create_params_non_streaming_tool_choice.py +1 -0
  271. letta_client/types/completion_create_params_streaming.py +10 -9
  272. letta_client/types/completion_create_params_streaming_function_call.py +1 -0
  273. letta_client/types/completion_create_params_streaming_messages_item.py +4 -3
  274. letta_client/types/completion_create_params_streaming_response_format.py +3 -2
  275. letta_client/types/completion_create_params_streaming_tool_choice.py +1 -0
  276. letta_client/types/conditional_tool_rule.py +3 -2
  277. letta_client/types/conditional_tool_rule_schema.py +3 -2
  278. letta_client/types/conflict_error_body.py +3 -2
  279. letta_client/types/context_window_overview.py +4 -3
  280. letta_client/types/continue_tool_rule.py +3 -2
  281. letta_client/types/core_memory_block_schema.py +4 -3
  282. letta_client/types/create_block.py +3 -2
  283. letta_client/types/dynamic_manager.py +2 -1
  284. letta_client/types/dynamic_manager_update.py +2 -1
  285. letta_client/types/e_2_b_sandbox_config.py +2 -1
  286. letta_client/types/embedding_config.py +4 -3
  287. letta_client/types/file.py +4 -3
  288. letta_client/types/file_block.py +4 -3
  289. letta_client/types/file_file.py +3 -2
  290. letta_client/types/file_metadata.py +5 -4
  291. letta_client/types/file_stats.py +3 -2
  292. letta_client/types/folder.py +5 -4
  293. letta_client/types/function_call.py +3 -2
  294. letta_client/types/function_definition_input.py +3 -2
  295. letta_client/types/function_definition_output.py +3 -2
  296. letta_client/types/function_output.py +3 -2
  297. letta_client/types/function_tool.py +4 -3
  298. letta_client/types/generate_tool_input.py +3 -2
  299. letta_client/types/generate_tool_output.py +4 -3
  300. letta_client/types/group.py +4 -3
  301. letta_client/types/health.py +3 -2
  302. letta_client/types/hidden_reasoning_message.py +4 -3
  303. letta_client/types/http_validation_error.py +4 -3
  304. letta_client/types/identity.py +4 -3
  305. letta_client/types/identity_property.py +5 -4
  306. letta_client/types/image_content.py +3 -2
  307. letta_client/types/image_content_source.py +1 -0
  308. letta_client/types/image_url.py +4 -3
  309. letta_client/types/init_tool_rule.py +3 -2
  310. letta_client/types/input_audio.py +4 -3
  311. letta_client/types/internal_server_error_body.py +3 -2
  312. letta_client/types/job.py +4 -3
  313. letta_client/types/json_object_response_format.py +3 -2
  314. letta_client/types/json_schema.py +4 -3
  315. letta_client/types/json_schema_response_format.py +2 -1
  316. letta_client/types/letta_batch_messages.py +4 -3
  317. letta_client/types/letta_batch_request.py +4 -3
  318. letta_client/types/letta_image.py +2 -1
  319. letta_client/types/letta_message_content_union.py +4 -3
  320. letta_client/types/letta_message_union.py +5 -4
  321. letta_client/types/letta_ping.py +2 -1
  322. letta_client/types/letta_request.py +4 -3
  323. letta_client/types/letta_request_config.py +3 -2
  324. letta_client/types/letta_response.py +4 -3
  325. letta_client/types/letta_stop_reason.py +3 -2
  326. letta_client/types/letta_streaming_request.py +9 -3
  327. letta_client/types/letta_usage_statistics.py +3 -2
  328. letta_client/types/letta_user_message_content_union.py +2 -1
  329. letta_client/types/llm_config.py +6 -5
  330. letta_client/types/local_sandbox_config.py +3 -2
  331. letta_client/types/max_count_per_step_tool_rule.py +3 -2
  332. letta_client/types/max_count_per_step_tool_rule_schema.py +3 -2
  333. letta_client/types/mcp_tool.py +4 -3
  334. letta_client/types/memory.py +4 -3
  335. letta_client/types/message.py +6 -5
  336. letta_client/types/message_content_item.py +1 -0
  337. letta_client/types/message_create.py +5 -4
  338. letta_client/types/message_create_content.py +1 -0
  339. letta_client/types/message_schema.py +4 -3
  340. letta_client/types/modal_sandbox_config.py +2 -1
  341. letta_client/types/not_found_error_body.py +3 -2
  342. letta_client/types/omitted_reasoning_content.py +3 -2
  343. letta_client/types/openai_types_chat_chat_completion_message_tool_call_param_function.py +3 -2
  344. letta_client/types/openai_types_chat_chat_completion_named_tool_choice_param_function.py +3 -2
  345. letta_client/types/openai_types_chat_completion_create_params_function.py +3 -2
  346. letta_client/types/organization.py +3 -2
  347. letta_client/types/organization_create.py +2 -1
  348. letta_client/types/organization_sources_stats.py +3 -2
  349. letta_client/types/organization_update.py +2 -1
  350. letta_client/types/parameter_properties.py +3 -2
  351. letta_client/types/parameters_schema.py +4 -3
  352. letta_client/types/parent_tool_rule.py +3 -2
  353. letta_client/types/passage.py +4 -3
  354. letta_client/types/payment_required_error_body.py +3 -2
  355. letta_client/types/pip_requirement.py +3 -2
  356. letta_client/types/provider.py +5 -4
  357. letta_client/types/provider_check.py +4 -3
  358. letta_client/types/provider_trace.py +3 -2
  359. letta_client/types/reasoning_content.py +2 -1
  360. letta_client/types/reasoning_message.py +4 -3
  361. letta_client/types/redacted_reasoning_content.py +2 -1
  362. letta_client/types/required_before_exit_tool_rule.py +3 -2
  363. letta_client/types/response_format_json_object.py +3 -2
  364. letta_client/types/response_format_json_schema.py +4 -3
  365. letta_client/types/response_format_text.py +3 -2
  366. letta_client/types/round_robin_manager.py +2 -1
  367. letta_client/types/round_robin_manager_update.py +2 -1
  368. letta_client/types/run.py +4 -3
  369. letta_client/types/sandbox_config.py +4 -3
  370. letta_client/types/sandbox_config_create.py +4 -3
  371. letta_client/types/sandbox_config_create_config.py +2 -1
  372. letta_client/types/sandbox_config_update.py +3 -2
  373. letta_client/types/sandbox_config_update_config.py +2 -1
  374. letta_client/types/sandbox_environment_variable.py +3 -2
  375. letta_client/types/sandbox_environment_variable_create.py +3 -2
  376. letta_client/types/sandbox_environment_variable_update.py +2 -1
  377. letta_client/types/sleeptime_manager.py +2 -1
  378. letta_client/types/sleeptime_manager_update.py +2 -1
  379. letta_client/types/source.py +5 -4
  380. letta_client/types/source_create.py +4 -3
  381. letta_client/types/source_stats.py +4 -3
  382. letta_client/types/source_update.py +3 -2
  383. letta_client/types/sse_server_config.py +4 -3
  384. letta_client/types/stdio_server_config.py +4 -3
  385. letta_client/types/step.py +5 -4
  386. letta_client/types/streamable_http_server_config.py +4 -3
  387. letta_client/types/supervisor_manager.py +2 -1
  388. letta_client/types/supervisor_manager_update.py +2 -1
  389. letta_client/types/system_message.py +2 -1
  390. letta_client/types/tag_schema.py +3 -2
  391. letta_client/types/terminal_tool_rule.py +3 -2
  392. letta_client/types/text_content.py +2 -1
  393. letta_client/types/text_response_format.py +3 -2
  394. letta_client/types/tool.py +5 -4
  395. letta_client/types/tool_annotations.py +4 -3
  396. letta_client/types/tool_call.py +3 -2
  397. letta_client/types/tool_call_content.py +2 -1
  398. letta_client/types/tool_call_delta.py +3 -2
  399. letta_client/types/tool_call_message.py +4 -3
  400. letta_client/types/tool_call_message_tool_call.py +1 -0
  401. letta_client/types/tool_create.py +3 -2
  402. letta_client/types/tool_env_var_schema.py +3 -2
  403. letta_client/types/tool_json_schema.py +4 -3
  404. letta_client/types/tool_return.py +4 -3
  405. letta_client/types/tool_return_content.py +2 -1
  406. letta_client/types/tool_return_message.py +4 -3
  407. letta_client/types/tool_schema.py +5 -4
  408. letta_client/types/update_assistant_message.py +3 -2
  409. letta_client/types/update_assistant_message_content.py +1 -0
  410. letta_client/types/update_reasoning_message.py +3 -2
  411. letta_client/types/update_ssemcp_server.py +2 -1
  412. letta_client/types/update_stdio_mcp_server.py +3 -2
  413. letta_client/types/update_streamable_httpmcp_server.py +2 -1
  414. letta_client/types/update_system_message.py +2 -1
  415. letta_client/types/update_user_message.py +3 -2
  416. letta_client/types/update_user_message_content.py +1 -0
  417. letta_client/types/url_image.py +2 -1
  418. letta_client/types/usage_statistics.py +5 -4
  419. letta_client/types/usage_statistics_completion_token_details.py +3 -2
  420. letta_client/types/usage_statistics_prompt_token_details.py +3 -2
  421. letta_client/types/user.py +3 -2
  422. letta_client/types/user_create.py +3 -2
  423. letta_client/types/user_message.py +3 -2
  424. letta_client/types/user_message_content.py +1 -0
  425. letta_client/types/user_update.py +3 -2
  426. letta_client/types/validation_error.py +4 -3
  427. letta_client/types/voice_sleeptime_manager.py +2 -1
  428. letta_client/types/voice_sleeptime_manager_update.py +2 -1
  429. letta_client/types/web_search_options.py +4 -3
  430. letta_client/types/web_search_options_user_location.py +4 -3
  431. letta_client/types/web_search_options_user_location_approximate.py +3 -2
  432. letta_client/voice/__init__.py +2 -0
  433. letta_client/voice/client.py +33 -74
  434. letta_client/voice/raw_client.py +154 -0
  435. {letta_client-0.1.233.dist-info → letta_client-0.1.234.dist-info}/METADATA +24 -3
  436. letta_client-0.1.234.dist-info/RECORD +503 -0
  437. letta_client-0.1.233.dist-info/RECORD +0 -455
  438. {letta_client-0.1.233.dist-info → letta_client-0.1.234.dist-info}/WHEEL +0 -0
@@ -0,0 +1,2565 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ import contextlib
4
+ import json
5
+ import typing
6
+ from json.decoder import JSONDecodeError
7
+
8
+ import httpx_sse
9
+ from ..core.api_error import ApiError
10
+ from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
11
+ from ..core.http_response import AsyncHttpResponse, HttpResponse
12
+ from ..core.jsonable_encoder import jsonable_encoder
13
+ from ..core.request_options import RequestOptions
14
+ from ..core.serialization import convert_and_respect_annotation_metadata
15
+ from ..core.unchecked_base_model import construct_type
16
+ from ..errors.unprocessable_entity_error import UnprocessableEntityError
17
+ from ..types.action_model import ActionModel
18
+ from ..types.app_model import AppModel
19
+ from ..types.http_validation_error import HttpValidationError
20
+ from ..types.mcp_tool import McpTool
21
+ from ..types.pip_requirement import PipRequirement
22
+ from ..types.tool import Tool
23
+ from ..types.tool_return_message import ToolReturnMessage
24
+ from .types.add_mcp_server_request import AddMcpServerRequest
25
+ from .types.add_mcp_server_response_item import AddMcpServerResponseItem
26
+ from .types.connect_mcp_server_request import ConnectMcpServerRequest
27
+ from .types.delete_mcp_server_response_item import DeleteMcpServerResponseItem
28
+ from .types.list_mcp_servers_response_value import ListMcpServersResponseValue
29
+ from .types.streaming_response import StreamingResponse
30
+ from .types.test_mcp_server_request import TestMcpServerRequest
31
+ from .types.update_mcp_server_request import UpdateMcpServerRequest
32
+ from .types.update_mcp_server_response import UpdateMcpServerResponse
33
+
34
+ # this is used as the default value for optional parameters
35
+ OMIT = typing.cast(typing.Any, ...)
36
+
37
+
38
+ class RawToolsClient:
39
+ def __init__(self, *, client_wrapper: SyncClientWrapper):
40
+ self._client_wrapper = client_wrapper
41
+
42
+ def retrieve(self, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None) -> HttpResponse[Tool]:
43
+ """
44
+ Get a tool by ID
45
+
46
+ Parameters
47
+ ----------
48
+ tool_id : str
49
+
50
+ request_options : typing.Optional[RequestOptions]
51
+ Request-specific configuration.
52
+
53
+ Returns
54
+ -------
55
+ HttpResponse[Tool]
56
+ Successful Response
57
+ """
58
+ _response = self._client_wrapper.httpx_client.request(
59
+ f"v1/tools/{jsonable_encoder(tool_id)}",
60
+ method="GET",
61
+ request_options=request_options,
62
+ )
63
+ try:
64
+ if 200 <= _response.status_code < 300:
65
+ _data = typing.cast(
66
+ Tool,
67
+ construct_type(
68
+ type_=Tool, # type: ignore
69
+ object_=_response.json(),
70
+ ),
71
+ )
72
+ return HttpResponse(response=_response, data=_data)
73
+ if _response.status_code == 422:
74
+ raise UnprocessableEntityError(
75
+ headers=dict(_response.headers),
76
+ body=typing.cast(
77
+ HttpValidationError,
78
+ construct_type(
79
+ type_=HttpValidationError, # type: ignore
80
+ object_=_response.json(),
81
+ ),
82
+ ),
83
+ )
84
+ _response_json = _response.json()
85
+ except JSONDecodeError:
86
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
87
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
88
+
89
+ def delete(
90
+ self, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None
91
+ ) -> HttpResponse[typing.Optional[typing.Any]]:
92
+ """
93
+ Delete a tool by name
94
+
95
+ Parameters
96
+ ----------
97
+ tool_id : str
98
+
99
+ request_options : typing.Optional[RequestOptions]
100
+ Request-specific configuration.
101
+
102
+ Returns
103
+ -------
104
+ HttpResponse[typing.Optional[typing.Any]]
105
+ Successful Response
106
+ """
107
+ _response = self._client_wrapper.httpx_client.request(
108
+ f"v1/tools/{jsonable_encoder(tool_id)}",
109
+ method="DELETE",
110
+ request_options=request_options,
111
+ )
112
+ try:
113
+ if _response is None or not _response.text.strip():
114
+ return HttpResponse(response=_response, data=None)
115
+ if 200 <= _response.status_code < 300:
116
+ _data = typing.cast(
117
+ typing.Optional[typing.Any],
118
+ construct_type(
119
+ type_=typing.Optional[typing.Any], # type: ignore
120
+ object_=_response.json(),
121
+ ),
122
+ )
123
+ return HttpResponse(response=_response, data=_data)
124
+ if _response.status_code == 422:
125
+ raise UnprocessableEntityError(
126
+ headers=dict(_response.headers),
127
+ body=typing.cast(
128
+ HttpValidationError,
129
+ construct_type(
130
+ type_=HttpValidationError, # type: ignore
131
+ object_=_response.json(),
132
+ ),
133
+ ),
134
+ )
135
+ _response_json = _response.json()
136
+ except JSONDecodeError:
137
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
138
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
139
+
140
+ def modify(
141
+ self,
142
+ tool_id: str,
143
+ *,
144
+ description: typing.Optional[str] = OMIT,
145
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
146
+ source_code: typing.Optional[str] = OMIT,
147
+ source_type: typing.Optional[str] = OMIT,
148
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
149
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
150
+ return_char_limit: typing.Optional[int] = OMIT,
151
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
152
+ request_options: typing.Optional[RequestOptions] = None,
153
+ ) -> HttpResponse[Tool]:
154
+ """
155
+ Update an existing tool
156
+
157
+ Parameters
158
+ ----------
159
+ tool_id : str
160
+
161
+ description : typing.Optional[str]
162
+ The description of the tool.
163
+
164
+ tags : typing.Optional[typing.Sequence[str]]
165
+ Metadata tags.
166
+
167
+ source_code : typing.Optional[str]
168
+ The source code of the function.
169
+
170
+ source_type : typing.Optional[str]
171
+ The type of the source code.
172
+
173
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
174
+ The JSON schema of the function (auto-generated from source_code if not provided)
175
+
176
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
177
+ The args JSON schema of the function.
178
+
179
+ return_char_limit : typing.Optional[int]
180
+ The maximum number of characters in the response.
181
+
182
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
183
+ Optional list of pip packages required by this tool.
184
+
185
+ request_options : typing.Optional[RequestOptions]
186
+ Request-specific configuration.
187
+
188
+ Returns
189
+ -------
190
+ HttpResponse[Tool]
191
+ Successful Response
192
+ """
193
+ _response = self._client_wrapper.httpx_client.request(
194
+ f"v1/tools/{jsonable_encoder(tool_id)}",
195
+ method="PATCH",
196
+ json={
197
+ "description": description,
198
+ "tags": tags,
199
+ "source_code": source_code,
200
+ "source_type": source_type,
201
+ "json_schema": json_schema,
202
+ "args_json_schema": args_json_schema,
203
+ "return_char_limit": return_char_limit,
204
+ "pip_requirements": convert_and_respect_annotation_metadata(
205
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
206
+ ),
207
+ },
208
+ headers={
209
+ "content-type": "application/json",
210
+ },
211
+ request_options=request_options,
212
+ omit=OMIT,
213
+ )
214
+ try:
215
+ if 200 <= _response.status_code < 300:
216
+ _data = typing.cast(
217
+ Tool,
218
+ construct_type(
219
+ type_=Tool, # type: ignore
220
+ object_=_response.json(),
221
+ ),
222
+ )
223
+ return HttpResponse(response=_response, data=_data)
224
+ if _response.status_code == 422:
225
+ raise UnprocessableEntityError(
226
+ headers=dict(_response.headers),
227
+ body=typing.cast(
228
+ HttpValidationError,
229
+ construct_type(
230
+ type_=HttpValidationError, # type: ignore
231
+ object_=_response.json(),
232
+ ),
233
+ ),
234
+ )
235
+ _response_json = _response.json()
236
+ except JSONDecodeError:
237
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
238
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
239
+
240
+ def count(
241
+ self,
242
+ *,
243
+ include_base_tools: typing.Optional[bool] = None,
244
+ request_options: typing.Optional[RequestOptions] = None,
245
+ ) -> HttpResponse[int]:
246
+ """
247
+ Get a count of all tools available to agents belonging to the org of the user.
248
+
249
+ Parameters
250
+ ----------
251
+ include_base_tools : typing.Optional[bool]
252
+ Include built-in Letta tools in the count
253
+
254
+ request_options : typing.Optional[RequestOptions]
255
+ Request-specific configuration.
256
+
257
+ Returns
258
+ -------
259
+ HttpResponse[int]
260
+ Successful Response
261
+ """
262
+ _response = self._client_wrapper.httpx_client.request(
263
+ "v1/tools/count",
264
+ method="GET",
265
+ params={
266
+ "include_base_tools": include_base_tools,
267
+ },
268
+ request_options=request_options,
269
+ )
270
+ try:
271
+ if 200 <= _response.status_code < 300:
272
+ _data = typing.cast(
273
+ int,
274
+ construct_type(
275
+ type_=int, # type: ignore
276
+ object_=_response.json(),
277
+ ),
278
+ )
279
+ return HttpResponse(response=_response, data=_data)
280
+ if _response.status_code == 422:
281
+ raise UnprocessableEntityError(
282
+ headers=dict(_response.headers),
283
+ body=typing.cast(
284
+ HttpValidationError,
285
+ construct_type(
286
+ type_=HttpValidationError, # type: ignore
287
+ object_=_response.json(),
288
+ ),
289
+ ),
290
+ )
291
+ _response_json = _response.json()
292
+ except JSONDecodeError:
293
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
294
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
295
+
296
+ def list(
297
+ self,
298
+ *,
299
+ after: typing.Optional[str] = None,
300
+ limit: typing.Optional[int] = None,
301
+ name: typing.Optional[str] = None,
302
+ request_options: typing.Optional[RequestOptions] = None,
303
+ ) -> HttpResponse[typing.List[Tool]]:
304
+ """
305
+ Get a list of all tools available to agents belonging to the org of the user
306
+
307
+ Parameters
308
+ ----------
309
+ after : typing.Optional[str]
310
+
311
+ limit : typing.Optional[int]
312
+
313
+ name : typing.Optional[str]
314
+
315
+ request_options : typing.Optional[RequestOptions]
316
+ Request-specific configuration.
317
+
318
+ Returns
319
+ -------
320
+ HttpResponse[typing.List[Tool]]
321
+ Successful Response
322
+ """
323
+ _response = self._client_wrapper.httpx_client.request(
324
+ "v1/tools/",
325
+ method="GET",
326
+ params={
327
+ "after": after,
328
+ "limit": limit,
329
+ "name": name,
330
+ },
331
+ request_options=request_options,
332
+ )
333
+ try:
334
+ if 200 <= _response.status_code < 300:
335
+ _data = typing.cast(
336
+ typing.List[Tool],
337
+ construct_type(
338
+ type_=typing.List[Tool], # type: ignore
339
+ object_=_response.json(),
340
+ ),
341
+ )
342
+ return HttpResponse(response=_response, data=_data)
343
+ if _response.status_code == 422:
344
+ raise UnprocessableEntityError(
345
+ headers=dict(_response.headers),
346
+ body=typing.cast(
347
+ HttpValidationError,
348
+ construct_type(
349
+ type_=HttpValidationError, # type: ignore
350
+ object_=_response.json(),
351
+ ),
352
+ ),
353
+ )
354
+ _response_json = _response.json()
355
+ except JSONDecodeError:
356
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
357
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
358
+
359
+ def create(
360
+ self,
361
+ *,
362
+ source_code: str,
363
+ description: typing.Optional[str] = OMIT,
364
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
365
+ source_type: typing.Optional[str] = OMIT,
366
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
367
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
368
+ return_char_limit: typing.Optional[int] = OMIT,
369
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
370
+ request_options: typing.Optional[RequestOptions] = None,
371
+ ) -> HttpResponse[Tool]:
372
+ """
373
+ Create a new tool
374
+
375
+ Parameters
376
+ ----------
377
+ source_code : str
378
+ The source code of the function.
379
+
380
+ description : typing.Optional[str]
381
+ The description of the tool.
382
+
383
+ tags : typing.Optional[typing.Sequence[str]]
384
+ Metadata tags.
385
+
386
+ source_type : typing.Optional[str]
387
+ The source type of the function.
388
+
389
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
390
+ The JSON schema of the function (auto-generated from source_code if not provided)
391
+
392
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
393
+ The args JSON schema of the function.
394
+
395
+ return_char_limit : typing.Optional[int]
396
+ The maximum number of characters in the response.
397
+
398
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
399
+ Optional list of pip packages required by this tool.
400
+
401
+ request_options : typing.Optional[RequestOptions]
402
+ Request-specific configuration.
403
+
404
+ Returns
405
+ -------
406
+ HttpResponse[Tool]
407
+ Successful Response
408
+ """
409
+ _response = self._client_wrapper.httpx_client.request(
410
+ "v1/tools/",
411
+ method="POST",
412
+ json={
413
+ "description": description,
414
+ "tags": tags,
415
+ "source_code": source_code,
416
+ "source_type": source_type,
417
+ "json_schema": json_schema,
418
+ "args_json_schema": args_json_schema,
419
+ "return_char_limit": return_char_limit,
420
+ "pip_requirements": convert_and_respect_annotation_metadata(
421
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
422
+ ),
423
+ },
424
+ headers={
425
+ "content-type": "application/json",
426
+ },
427
+ request_options=request_options,
428
+ omit=OMIT,
429
+ )
430
+ try:
431
+ if 200 <= _response.status_code < 300:
432
+ _data = typing.cast(
433
+ Tool,
434
+ construct_type(
435
+ type_=Tool, # type: ignore
436
+ object_=_response.json(),
437
+ ),
438
+ )
439
+ return HttpResponse(response=_response, data=_data)
440
+ if _response.status_code == 422:
441
+ raise UnprocessableEntityError(
442
+ headers=dict(_response.headers),
443
+ body=typing.cast(
444
+ HttpValidationError,
445
+ construct_type(
446
+ type_=HttpValidationError, # type: ignore
447
+ object_=_response.json(),
448
+ ),
449
+ ),
450
+ )
451
+ _response_json = _response.json()
452
+ except JSONDecodeError:
453
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
454
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
455
+
456
+ def upsert(
457
+ self,
458
+ *,
459
+ source_code: str,
460
+ description: typing.Optional[str] = OMIT,
461
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
462
+ source_type: typing.Optional[str] = OMIT,
463
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
464
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
465
+ return_char_limit: typing.Optional[int] = OMIT,
466
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
467
+ request_options: typing.Optional[RequestOptions] = None,
468
+ ) -> HttpResponse[Tool]:
469
+ """
470
+ Create or update a tool
471
+
472
+ Parameters
473
+ ----------
474
+ source_code : str
475
+ The source code of the function.
476
+
477
+ description : typing.Optional[str]
478
+ The description of the tool.
479
+
480
+ tags : typing.Optional[typing.Sequence[str]]
481
+ Metadata tags.
482
+
483
+ source_type : typing.Optional[str]
484
+ The source type of the function.
485
+
486
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
487
+ The JSON schema of the function (auto-generated from source_code if not provided)
488
+
489
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
490
+ The args JSON schema of the function.
491
+
492
+ return_char_limit : typing.Optional[int]
493
+ The maximum number of characters in the response.
494
+
495
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
496
+ Optional list of pip packages required by this tool.
497
+
498
+ request_options : typing.Optional[RequestOptions]
499
+ Request-specific configuration.
500
+
501
+ Returns
502
+ -------
503
+ HttpResponse[Tool]
504
+ Successful Response
505
+ """
506
+ _response = self._client_wrapper.httpx_client.request(
507
+ "v1/tools/",
508
+ method="PUT",
509
+ json={
510
+ "description": description,
511
+ "tags": tags,
512
+ "source_code": source_code,
513
+ "source_type": source_type,
514
+ "json_schema": json_schema,
515
+ "args_json_schema": args_json_schema,
516
+ "return_char_limit": return_char_limit,
517
+ "pip_requirements": convert_and_respect_annotation_metadata(
518
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
519
+ ),
520
+ },
521
+ headers={
522
+ "content-type": "application/json",
523
+ },
524
+ request_options=request_options,
525
+ omit=OMIT,
526
+ )
527
+ try:
528
+ if 200 <= _response.status_code < 300:
529
+ _data = typing.cast(
530
+ Tool,
531
+ construct_type(
532
+ type_=Tool, # type: ignore
533
+ object_=_response.json(),
534
+ ),
535
+ )
536
+ return HttpResponse(response=_response, data=_data)
537
+ if _response.status_code == 422:
538
+ raise UnprocessableEntityError(
539
+ headers=dict(_response.headers),
540
+ body=typing.cast(
541
+ HttpValidationError,
542
+ construct_type(
543
+ type_=HttpValidationError, # type: ignore
544
+ object_=_response.json(),
545
+ ),
546
+ ),
547
+ )
548
+ _response_json = _response.json()
549
+ except JSONDecodeError:
550
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
551
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
552
+
553
+ def upsert_base_tools(
554
+ self, *, request_options: typing.Optional[RequestOptions] = None
555
+ ) -> HttpResponse[typing.List[Tool]]:
556
+ """
557
+ Upsert base tools
558
+
559
+ Parameters
560
+ ----------
561
+ request_options : typing.Optional[RequestOptions]
562
+ Request-specific configuration.
563
+
564
+ Returns
565
+ -------
566
+ HttpResponse[typing.List[Tool]]
567
+ Successful Response
568
+ """
569
+ _response = self._client_wrapper.httpx_client.request(
570
+ "v1/tools/add-base-tools",
571
+ method="POST",
572
+ request_options=request_options,
573
+ )
574
+ try:
575
+ if 200 <= _response.status_code < 300:
576
+ _data = typing.cast(
577
+ typing.List[Tool],
578
+ construct_type(
579
+ type_=typing.List[Tool], # type: ignore
580
+ object_=_response.json(),
581
+ ),
582
+ )
583
+ return HttpResponse(response=_response, data=_data)
584
+ if _response.status_code == 422:
585
+ raise UnprocessableEntityError(
586
+ headers=dict(_response.headers),
587
+ body=typing.cast(
588
+ HttpValidationError,
589
+ construct_type(
590
+ type_=HttpValidationError, # type: ignore
591
+ object_=_response.json(),
592
+ ),
593
+ ),
594
+ )
595
+ _response_json = _response.json()
596
+ except JSONDecodeError:
597
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
598
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
599
+
600
+ def run_tool_from_source(
601
+ self,
602
+ *,
603
+ source_code: str,
604
+ args: typing.Dict[str, typing.Optional[typing.Any]],
605
+ env_vars: typing.Optional[typing.Dict[str, str]] = OMIT,
606
+ name: typing.Optional[str] = OMIT,
607
+ source_type: typing.Optional[str] = OMIT,
608
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
609
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
610
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
611
+ request_options: typing.Optional[RequestOptions] = None,
612
+ ) -> HttpResponse[ToolReturnMessage]:
613
+ """
614
+ Attempt to build a tool from source, then run it on the provided arguments
615
+
616
+ Parameters
617
+ ----------
618
+ source_code : str
619
+ The source code of the function.
620
+
621
+ args : typing.Dict[str, typing.Optional[typing.Any]]
622
+ The arguments to pass to the tool.
623
+
624
+ env_vars : typing.Optional[typing.Dict[str, str]]
625
+ The environment variables to pass to the tool.
626
+
627
+ name : typing.Optional[str]
628
+ The name of the tool to run.
629
+
630
+ source_type : typing.Optional[str]
631
+ The type of the source code.
632
+
633
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
634
+ The args JSON schema of the function.
635
+
636
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
637
+ The JSON schema of the function (auto-generated from source_code if not provided)
638
+
639
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
640
+ Optional list of pip packages required by this tool.
641
+
642
+ request_options : typing.Optional[RequestOptions]
643
+ Request-specific configuration.
644
+
645
+ Returns
646
+ -------
647
+ HttpResponse[ToolReturnMessage]
648
+ Successful Response
649
+ """
650
+ _response = self._client_wrapper.httpx_client.request(
651
+ "v1/tools/run",
652
+ method="POST",
653
+ json={
654
+ "source_code": source_code,
655
+ "args": args,
656
+ "env_vars": env_vars,
657
+ "name": name,
658
+ "source_type": source_type,
659
+ "args_json_schema": args_json_schema,
660
+ "json_schema": json_schema,
661
+ "pip_requirements": convert_and_respect_annotation_metadata(
662
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
663
+ ),
664
+ },
665
+ headers={
666
+ "content-type": "application/json",
667
+ },
668
+ request_options=request_options,
669
+ omit=OMIT,
670
+ )
671
+ try:
672
+ if 200 <= _response.status_code < 300:
673
+ _data = typing.cast(
674
+ ToolReturnMessage,
675
+ construct_type(
676
+ type_=ToolReturnMessage, # type: ignore
677
+ object_=_response.json(),
678
+ ),
679
+ )
680
+ return HttpResponse(response=_response, data=_data)
681
+ if _response.status_code == 422:
682
+ raise UnprocessableEntityError(
683
+ headers=dict(_response.headers),
684
+ body=typing.cast(
685
+ HttpValidationError,
686
+ construct_type(
687
+ type_=HttpValidationError, # type: ignore
688
+ object_=_response.json(),
689
+ ),
690
+ ),
691
+ )
692
+ _response_json = _response.json()
693
+ except JSONDecodeError:
694
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
695
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
696
+
697
+ def list_composio_apps(
698
+ self, *, user_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
699
+ ) -> HttpResponse[typing.List[AppModel]]:
700
+ """
701
+ Get a list of all Composio apps
702
+
703
+ Parameters
704
+ ----------
705
+ user_id : typing.Optional[str]
706
+
707
+ request_options : typing.Optional[RequestOptions]
708
+ Request-specific configuration.
709
+
710
+ Returns
711
+ -------
712
+ HttpResponse[typing.List[AppModel]]
713
+ Successful Response
714
+ """
715
+ _response = self._client_wrapper.httpx_client.request(
716
+ "v1/tools/composio/apps",
717
+ method="GET",
718
+ headers={
719
+ "user-id": str(user_id) if user_id is not None else None,
720
+ },
721
+ request_options=request_options,
722
+ )
723
+ try:
724
+ if 200 <= _response.status_code < 300:
725
+ _data = typing.cast(
726
+ typing.List[AppModel],
727
+ construct_type(
728
+ type_=typing.List[AppModel], # type: ignore
729
+ object_=_response.json(),
730
+ ),
731
+ )
732
+ return HttpResponse(response=_response, data=_data)
733
+ if _response.status_code == 422:
734
+ raise UnprocessableEntityError(
735
+ headers=dict(_response.headers),
736
+ body=typing.cast(
737
+ HttpValidationError,
738
+ construct_type(
739
+ type_=HttpValidationError, # type: ignore
740
+ object_=_response.json(),
741
+ ),
742
+ ),
743
+ )
744
+ _response_json = _response.json()
745
+ except JSONDecodeError:
746
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
747
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
748
+
749
+ def list_composio_actions_by_app(
750
+ self, composio_app_name: str, *, request_options: typing.Optional[RequestOptions] = None
751
+ ) -> HttpResponse[typing.List[ActionModel]]:
752
+ """
753
+ Get a list of all Composio actions for a specific app
754
+
755
+ Parameters
756
+ ----------
757
+ composio_app_name : str
758
+
759
+ request_options : typing.Optional[RequestOptions]
760
+ Request-specific configuration.
761
+
762
+ Returns
763
+ -------
764
+ HttpResponse[typing.List[ActionModel]]
765
+ Successful Response
766
+ """
767
+ _response = self._client_wrapper.httpx_client.request(
768
+ f"v1/tools/composio/apps/{jsonable_encoder(composio_app_name)}/actions",
769
+ method="GET",
770
+ request_options=request_options,
771
+ )
772
+ try:
773
+ if 200 <= _response.status_code < 300:
774
+ _data = typing.cast(
775
+ typing.List[ActionModel],
776
+ construct_type(
777
+ type_=typing.List[ActionModel], # type: ignore
778
+ object_=_response.json(),
779
+ ),
780
+ )
781
+ return HttpResponse(response=_response, data=_data)
782
+ if _response.status_code == 422:
783
+ raise UnprocessableEntityError(
784
+ headers=dict(_response.headers),
785
+ body=typing.cast(
786
+ HttpValidationError,
787
+ construct_type(
788
+ type_=HttpValidationError, # type: ignore
789
+ object_=_response.json(),
790
+ ),
791
+ ),
792
+ )
793
+ _response_json = _response.json()
794
+ except JSONDecodeError:
795
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
796
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
797
+
798
+ def add_composio_tool(
799
+ self, composio_action_name: str, *, request_options: typing.Optional[RequestOptions] = None
800
+ ) -> HttpResponse[Tool]:
801
+ """
802
+ Add a new Composio tool by action name (Composio refers to each tool as an `Action`)
803
+
804
+ Parameters
805
+ ----------
806
+ composio_action_name : str
807
+
808
+ request_options : typing.Optional[RequestOptions]
809
+ Request-specific configuration.
810
+
811
+ Returns
812
+ -------
813
+ HttpResponse[Tool]
814
+ Successful Response
815
+ """
816
+ _response = self._client_wrapper.httpx_client.request(
817
+ f"v1/tools/composio/{jsonable_encoder(composio_action_name)}",
818
+ method="POST",
819
+ request_options=request_options,
820
+ )
821
+ try:
822
+ if 200 <= _response.status_code < 300:
823
+ _data = typing.cast(
824
+ Tool,
825
+ construct_type(
826
+ type_=Tool, # type: ignore
827
+ object_=_response.json(),
828
+ ),
829
+ )
830
+ return HttpResponse(response=_response, data=_data)
831
+ if _response.status_code == 422:
832
+ raise UnprocessableEntityError(
833
+ headers=dict(_response.headers),
834
+ body=typing.cast(
835
+ HttpValidationError,
836
+ construct_type(
837
+ type_=HttpValidationError, # type: ignore
838
+ object_=_response.json(),
839
+ ),
840
+ ),
841
+ )
842
+ _response_json = _response.json()
843
+ except JSONDecodeError:
844
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
845
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
846
+
847
+ def list_mcp_servers(
848
+ self, *, user_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
849
+ ) -> HttpResponse[typing.Dict[str, ListMcpServersResponseValue]]:
850
+ """
851
+ Get a list of all configured MCP servers
852
+
853
+ Parameters
854
+ ----------
855
+ user_id : typing.Optional[str]
856
+
857
+ request_options : typing.Optional[RequestOptions]
858
+ Request-specific configuration.
859
+
860
+ Returns
861
+ -------
862
+ HttpResponse[typing.Dict[str, ListMcpServersResponseValue]]
863
+ Successful Response
864
+ """
865
+ _response = self._client_wrapper.httpx_client.request(
866
+ "v1/tools/mcp/servers",
867
+ method="GET",
868
+ headers={
869
+ "user-id": str(user_id) if user_id is not None else None,
870
+ },
871
+ request_options=request_options,
872
+ )
873
+ try:
874
+ if 200 <= _response.status_code < 300:
875
+ _data = typing.cast(
876
+ typing.Dict[str, ListMcpServersResponseValue],
877
+ construct_type(
878
+ type_=typing.Dict[str, ListMcpServersResponseValue], # type: ignore
879
+ object_=_response.json(),
880
+ ),
881
+ )
882
+ return HttpResponse(response=_response, data=_data)
883
+ if _response.status_code == 422:
884
+ raise UnprocessableEntityError(
885
+ headers=dict(_response.headers),
886
+ body=typing.cast(
887
+ HttpValidationError,
888
+ construct_type(
889
+ type_=HttpValidationError, # type: ignore
890
+ object_=_response.json(),
891
+ ),
892
+ ),
893
+ )
894
+ _response_json = _response.json()
895
+ except JSONDecodeError:
896
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
897
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
898
+
899
+ def add_mcp_server(
900
+ self, *, request: AddMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
901
+ ) -> HttpResponse[typing.List[AddMcpServerResponseItem]]:
902
+ """
903
+ Add a new MCP server to the Letta MCP server config
904
+
905
+ Parameters
906
+ ----------
907
+ request : AddMcpServerRequest
908
+
909
+ request_options : typing.Optional[RequestOptions]
910
+ Request-specific configuration.
911
+
912
+ Returns
913
+ -------
914
+ HttpResponse[typing.List[AddMcpServerResponseItem]]
915
+ Successful Response
916
+ """
917
+ _response = self._client_wrapper.httpx_client.request(
918
+ "v1/tools/mcp/servers",
919
+ method="PUT",
920
+ json=convert_and_respect_annotation_metadata(
921
+ object_=request, annotation=AddMcpServerRequest, direction="write"
922
+ ),
923
+ headers={
924
+ "content-type": "application/json",
925
+ },
926
+ request_options=request_options,
927
+ omit=OMIT,
928
+ )
929
+ try:
930
+ if 200 <= _response.status_code < 300:
931
+ _data = typing.cast(
932
+ typing.List[AddMcpServerResponseItem],
933
+ construct_type(
934
+ type_=typing.List[AddMcpServerResponseItem], # type: ignore
935
+ object_=_response.json(),
936
+ ),
937
+ )
938
+ return HttpResponse(response=_response, data=_data)
939
+ if _response.status_code == 422:
940
+ raise UnprocessableEntityError(
941
+ headers=dict(_response.headers),
942
+ body=typing.cast(
943
+ HttpValidationError,
944
+ construct_type(
945
+ type_=HttpValidationError, # type: ignore
946
+ object_=_response.json(),
947
+ ),
948
+ ),
949
+ )
950
+ _response_json = _response.json()
951
+ except JSONDecodeError:
952
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
953
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
954
+
955
+ def list_mcp_tools_by_server(
956
+ self, mcp_server_name: str, *, request_options: typing.Optional[RequestOptions] = None
957
+ ) -> HttpResponse[typing.List[McpTool]]:
958
+ """
959
+ Get a list of all tools for a specific MCP server
960
+
961
+ Parameters
962
+ ----------
963
+ mcp_server_name : str
964
+
965
+ request_options : typing.Optional[RequestOptions]
966
+ Request-specific configuration.
967
+
968
+ Returns
969
+ -------
970
+ HttpResponse[typing.List[McpTool]]
971
+ Successful Response
972
+ """
973
+ _response = self._client_wrapper.httpx_client.request(
974
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}/tools",
975
+ method="GET",
976
+ request_options=request_options,
977
+ )
978
+ try:
979
+ if 200 <= _response.status_code < 300:
980
+ _data = typing.cast(
981
+ typing.List[McpTool],
982
+ construct_type(
983
+ type_=typing.List[McpTool], # type: ignore
984
+ object_=_response.json(),
985
+ ),
986
+ )
987
+ return HttpResponse(response=_response, data=_data)
988
+ if _response.status_code == 422:
989
+ raise UnprocessableEntityError(
990
+ headers=dict(_response.headers),
991
+ body=typing.cast(
992
+ HttpValidationError,
993
+ construct_type(
994
+ type_=HttpValidationError, # type: ignore
995
+ object_=_response.json(),
996
+ ),
997
+ ),
998
+ )
999
+ _response_json = _response.json()
1000
+ except JSONDecodeError:
1001
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1002
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1003
+
1004
+ def add_mcp_tool(
1005
+ self, mcp_server_name: str, mcp_tool_name: str, *, request_options: typing.Optional[RequestOptions] = None
1006
+ ) -> HttpResponse[Tool]:
1007
+ """
1008
+ Register a new MCP tool as a Letta server by MCP server + tool name
1009
+
1010
+ Parameters
1011
+ ----------
1012
+ mcp_server_name : str
1013
+
1014
+ mcp_tool_name : str
1015
+
1016
+ request_options : typing.Optional[RequestOptions]
1017
+ Request-specific configuration.
1018
+
1019
+ Returns
1020
+ -------
1021
+ HttpResponse[Tool]
1022
+ Successful Response
1023
+ """
1024
+ _response = self._client_wrapper.httpx_client.request(
1025
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}/{jsonable_encoder(mcp_tool_name)}",
1026
+ method="POST",
1027
+ request_options=request_options,
1028
+ )
1029
+ try:
1030
+ if 200 <= _response.status_code < 300:
1031
+ _data = typing.cast(
1032
+ Tool,
1033
+ construct_type(
1034
+ type_=Tool, # type: ignore
1035
+ object_=_response.json(),
1036
+ ),
1037
+ )
1038
+ return HttpResponse(response=_response, data=_data)
1039
+ if _response.status_code == 422:
1040
+ raise UnprocessableEntityError(
1041
+ headers=dict(_response.headers),
1042
+ body=typing.cast(
1043
+ HttpValidationError,
1044
+ construct_type(
1045
+ type_=HttpValidationError, # type: ignore
1046
+ object_=_response.json(),
1047
+ ),
1048
+ ),
1049
+ )
1050
+ _response_json = _response.json()
1051
+ except JSONDecodeError:
1052
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1053
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1054
+
1055
+ def delete_mcp_server(
1056
+ self, mcp_server_name: str, *, request_options: typing.Optional[RequestOptions] = None
1057
+ ) -> HttpResponse[typing.List[DeleteMcpServerResponseItem]]:
1058
+ """
1059
+ Add a new MCP server to the Letta MCP server config
1060
+
1061
+ Parameters
1062
+ ----------
1063
+ mcp_server_name : str
1064
+
1065
+ request_options : typing.Optional[RequestOptions]
1066
+ Request-specific configuration.
1067
+
1068
+ Returns
1069
+ -------
1070
+ HttpResponse[typing.List[DeleteMcpServerResponseItem]]
1071
+ Successful Response
1072
+ """
1073
+ _response = self._client_wrapper.httpx_client.request(
1074
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}",
1075
+ method="DELETE",
1076
+ request_options=request_options,
1077
+ )
1078
+ try:
1079
+ if 200 <= _response.status_code < 300:
1080
+ _data = typing.cast(
1081
+ typing.List[DeleteMcpServerResponseItem],
1082
+ construct_type(
1083
+ type_=typing.List[DeleteMcpServerResponseItem], # type: ignore
1084
+ object_=_response.json(),
1085
+ ),
1086
+ )
1087
+ return HttpResponse(response=_response, data=_data)
1088
+ if _response.status_code == 422:
1089
+ raise UnprocessableEntityError(
1090
+ headers=dict(_response.headers),
1091
+ body=typing.cast(
1092
+ HttpValidationError,
1093
+ construct_type(
1094
+ type_=HttpValidationError, # type: ignore
1095
+ object_=_response.json(),
1096
+ ),
1097
+ ),
1098
+ )
1099
+ _response_json = _response.json()
1100
+ except JSONDecodeError:
1101
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1102
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1103
+
1104
+ def update_mcp_server(
1105
+ self,
1106
+ mcp_server_name: str,
1107
+ *,
1108
+ request: UpdateMcpServerRequest,
1109
+ request_options: typing.Optional[RequestOptions] = None,
1110
+ ) -> HttpResponse[UpdateMcpServerResponse]:
1111
+ """
1112
+ Update an existing MCP server configuration
1113
+
1114
+ Parameters
1115
+ ----------
1116
+ mcp_server_name : str
1117
+
1118
+ request : UpdateMcpServerRequest
1119
+
1120
+ request_options : typing.Optional[RequestOptions]
1121
+ Request-specific configuration.
1122
+
1123
+ Returns
1124
+ -------
1125
+ HttpResponse[UpdateMcpServerResponse]
1126
+ Successful Response
1127
+ """
1128
+ _response = self._client_wrapper.httpx_client.request(
1129
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}",
1130
+ method="PATCH",
1131
+ json=convert_and_respect_annotation_metadata(
1132
+ object_=request, annotation=UpdateMcpServerRequest, direction="write"
1133
+ ),
1134
+ headers={
1135
+ "content-type": "application/json",
1136
+ },
1137
+ request_options=request_options,
1138
+ omit=OMIT,
1139
+ )
1140
+ try:
1141
+ if 200 <= _response.status_code < 300:
1142
+ _data = typing.cast(
1143
+ UpdateMcpServerResponse,
1144
+ construct_type(
1145
+ type_=UpdateMcpServerResponse, # type: ignore
1146
+ object_=_response.json(),
1147
+ ),
1148
+ )
1149
+ return HttpResponse(response=_response, data=_data)
1150
+ if _response.status_code == 422:
1151
+ raise UnprocessableEntityError(
1152
+ headers=dict(_response.headers),
1153
+ body=typing.cast(
1154
+ HttpValidationError,
1155
+ construct_type(
1156
+ type_=HttpValidationError, # type: ignore
1157
+ object_=_response.json(),
1158
+ ),
1159
+ ),
1160
+ )
1161
+ _response_json = _response.json()
1162
+ except JSONDecodeError:
1163
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1164
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1165
+
1166
+ def test_mcp_server(
1167
+ self, *, request: TestMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
1168
+ ) -> HttpResponse[typing.Optional[typing.Any]]:
1169
+ """
1170
+ Test connection to an MCP server without adding it.
1171
+ Returns the list of available tools if successful.
1172
+
1173
+ Parameters
1174
+ ----------
1175
+ request : TestMcpServerRequest
1176
+
1177
+ request_options : typing.Optional[RequestOptions]
1178
+ Request-specific configuration.
1179
+
1180
+ Returns
1181
+ -------
1182
+ HttpResponse[typing.Optional[typing.Any]]
1183
+ Successful Response
1184
+ """
1185
+ _response = self._client_wrapper.httpx_client.request(
1186
+ "v1/tools/mcp/servers/test",
1187
+ method="POST",
1188
+ json=convert_and_respect_annotation_metadata(
1189
+ object_=request, annotation=TestMcpServerRequest, direction="write"
1190
+ ),
1191
+ headers={
1192
+ "content-type": "application/json",
1193
+ },
1194
+ request_options=request_options,
1195
+ omit=OMIT,
1196
+ )
1197
+ try:
1198
+ if _response is None or not _response.text.strip():
1199
+ return HttpResponse(response=_response, data=None)
1200
+ if 200 <= _response.status_code < 300:
1201
+ _data = typing.cast(
1202
+ typing.Optional[typing.Any],
1203
+ construct_type(
1204
+ type_=typing.Optional[typing.Any], # type: ignore
1205
+ object_=_response.json(),
1206
+ ),
1207
+ )
1208
+ return HttpResponse(response=_response, data=_data)
1209
+ if _response.status_code == 422:
1210
+ raise UnprocessableEntityError(
1211
+ headers=dict(_response.headers),
1212
+ body=typing.cast(
1213
+ HttpValidationError,
1214
+ construct_type(
1215
+ type_=HttpValidationError, # type: ignore
1216
+ object_=_response.json(),
1217
+ ),
1218
+ ),
1219
+ )
1220
+ _response_json = _response.json()
1221
+ except JSONDecodeError:
1222
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1223
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1224
+
1225
+ @contextlib.contextmanager
1226
+ def connect_mcp_server(
1227
+ self, *, request: ConnectMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
1228
+ ) -> typing.Iterator[HttpResponse[typing.Iterator[StreamingResponse]]]:
1229
+ """
1230
+ Connect to an MCP server with support for OAuth via SSE.
1231
+ Returns a stream of events handling authorization state and exchange if OAuth is required.
1232
+
1233
+ Parameters
1234
+ ----------
1235
+ request : ConnectMcpServerRequest
1236
+
1237
+ request_options : typing.Optional[RequestOptions]
1238
+ Request-specific configuration.
1239
+
1240
+ Yields
1241
+ ------
1242
+ typing.Iterator[HttpResponse[typing.Iterator[StreamingResponse]]]
1243
+ Successful response
1244
+ """
1245
+ with self._client_wrapper.httpx_client.stream(
1246
+ "v1/tools/mcp/servers/connect",
1247
+ method="POST",
1248
+ json=convert_and_respect_annotation_metadata(
1249
+ object_=request, annotation=ConnectMcpServerRequest, direction="write"
1250
+ ),
1251
+ headers={
1252
+ "content-type": "application/json",
1253
+ },
1254
+ request_options=request_options,
1255
+ omit=OMIT,
1256
+ ) as _response:
1257
+
1258
+ def _stream() -> HttpResponse[typing.Iterator[StreamingResponse]]:
1259
+ try:
1260
+ if 200 <= _response.status_code < 300:
1261
+
1262
+ def _iter():
1263
+ _event_source = httpx_sse.EventSource(_response)
1264
+ for _sse in _event_source.iter_sse():
1265
+ if _sse.data == None:
1266
+ return
1267
+ try:
1268
+ yield typing.cast(
1269
+ StreamingResponse,
1270
+ construct_type(
1271
+ type_=StreamingResponse, # type: ignore
1272
+ object_=json.loads(_sse.data),
1273
+ ),
1274
+ )
1275
+ except Exception:
1276
+ pass
1277
+ return
1278
+
1279
+ return HttpResponse(response=_response, data=_iter())
1280
+ _response.read()
1281
+ if _response.status_code == 422:
1282
+ raise UnprocessableEntityError(
1283
+ headers=dict(_response.headers),
1284
+ body=typing.cast(
1285
+ HttpValidationError,
1286
+ construct_type(
1287
+ type_=HttpValidationError, # type: ignore
1288
+ object_=_response.json(),
1289
+ ),
1290
+ ),
1291
+ )
1292
+ _response_json = _response.json()
1293
+ except JSONDecodeError:
1294
+ raise ApiError(
1295
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
1296
+ )
1297
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1298
+
1299
+ yield _stream()
1300
+
1301
+
1302
+ class AsyncRawToolsClient:
1303
+ def __init__(self, *, client_wrapper: AsyncClientWrapper):
1304
+ self._client_wrapper = client_wrapper
1305
+
1306
+ async def retrieve(
1307
+ self, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None
1308
+ ) -> AsyncHttpResponse[Tool]:
1309
+ """
1310
+ Get a tool by ID
1311
+
1312
+ Parameters
1313
+ ----------
1314
+ tool_id : str
1315
+
1316
+ request_options : typing.Optional[RequestOptions]
1317
+ Request-specific configuration.
1318
+
1319
+ Returns
1320
+ -------
1321
+ AsyncHttpResponse[Tool]
1322
+ Successful Response
1323
+ """
1324
+ _response = await self._client_wrapper.httpx_client.request(
1325
+ f"v1/tools/{jsonable_encoder(tool_id)}",
1326
+ method="GET",
1327
+ request_options=request_options,
1328
+ )
1329
+ try:
1330
+ if 200 <= _response.status_code < 300:
1331
+ _data = typing.cast(
1332
+ Tool,
1333
+ construct_type(
1334
+ type_=Tool, # type: ignore
1335
+ object_=_response.json(),
1336
+ ),
1337
+ )
1338
+ return AsyncHttpResponse(response=_response, data=_data)
1339
+ if _response.status_code == 422:
1340
+ raise UnprocessableEntityError(
1341
+ headers=dict(_response.headers),
1342
+ body=typing.cast(
1343
+ HttpValidationError,
1344
+ construct_type(
1345
+ type_=HttpValidationError, # type: ignore
1346
+ object_=_response.json(),
1347
+ ),
1348
+ ),
1349
+ )
1350
+ _response_json = _response.json()
1351
+ except JSONDecodeError:
1352
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1353
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1354
+
1355
+ async def delete(
1356
+ self, tool_id: str, *, request_options: typing.Optional[RequestOptions] = None
1357
+ ) -> AsyncHttpResponse[typing.Optional[typing.Any]]:
1358
+ """
1359
+ Delete a tool by name
1360
+
1361
+ Parameters
1362
+ ----------
1363
+ tool_id : str
1364
+
1365
+ request_options : typing.Optional[RequestOptions]
1366
+ Request-specific configuration.
1367
+
1368
+ Returns
1369
+ -------
1370
+ AsyncHttpResponse[typing.Optional[typing.Any]]
1371
+ Successful Response
1372
+ """
1373
+ _response = await self._client_wrapper.httpx_client.request(
1374
+ f"v1/tools/{jsonable_encoder(tool_id)}",
1375
+ method="DELETE",
1376
+ request_options=request_options,
1377
+ )
1378
+ try:
1379
+ if _response is None or not _response.text.strip():
1380
+ return AsyncHttpResponse(response=_response, data=None)
1381
+ if 200 <= _response.status_code < 300:
1382
+ _data = typing.cast(
1383
+ typing.Optional[typing.Any],
1384
+ construct_type(
1385
+ type_=typing.Optional[typing.Any], # type: ignore
1386
+ object_=_response.json(),
1387
+ ),
1388
+ )
1389
+ return AsyncHttpResponse(response=_response, data=_data)
1390
+ if _response.status_code == 422:
1391
+ raise UnprocessableEntityError(
1392
+ headers=dict(_response.headers),
1393
+ body=typing.cast(
1394
+ HttpValidationError,
1395
+ construct_type(
1396
+ type_=HttpValidationError, # type: ignore
1397
+ object_=_response.json(),
1398
+ ),
1399
+ ),
1400
+ )
1401
+ _response_json = _response.json()
1402
+ except JSONDecodeError:
1403
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1404
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1405
+
1406
+ async def modify(
1407
+ self,
1408
+ tool_id: str,
1409
+ *,
1410
+ description: typing.Optional[str] = OMIT,
1411
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
1412
+ source_code: typing.Optional[str] = OMIT,
1413
+ source_type: typing.Optional[str] = OMIT,
1414
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1415
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1416
+ return_char_limit: typing.Optional[int] = OMIT,
1417
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
1418
+ request_options: typing.Optional[RequestOptions] = None,
1419
+ ) -> AsyncHttpResponse[Tool]:
1420
+ """
1421
+ Update an existing tool
1422
+
1423
+ Parameters
1424
+ ----------
1425
+ tool_id : str
1426
+
1427
+ description : typing.Optional[str]
1428
+ The description of the tool.
1429
+
1430
+ tags : typing.Optional[typing.Sequence[str]]
1431
+ Metadata tags.
1432
+
1433
+ source_code : typing.Optional[str]
1434
+ The source code of the function.
1435
+
1436
+ source_type : typing.Optional[str]
1437
+ The type of the source code.
1438
+
1439
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1440
+ The JSON schema of the function (auto-generated from source_code if not provided)
1441
+
1442
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1443
+ The args JSON schema of the function.
1444
+
1445
+ return_char_limit : typing.Optional[int]
1446
+ The maximum number of characters in the response.
1447
+
1448
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
1449
+ Optional list of pip packages required by this tool.
1450
+
1451
+ request_options : typing.Optional[RequestOptions]
1452
+ Request-specific configuration.
1453
+
1454
+ Returns
1455
+ -------
1456
+ AsyncHttpResponse[Tool]
1457
+ Successful Response
1458
+ """
1459
+ _response = await self._client_wrapper.httpx_client.request(
1460
+ f"v1/tools/{jsonable_encoder(tool_id)}",
1461
+ method="PATCH",
1462
+ json={
1463
+ "description": description,
1464
+ "tags": tags,
1465
+ "source_code": source_code,
1466
+ "source_type": source_type,
1467
+ "json_schema": json_schema,
1468
+ "args_json_schema": args_json_schema,
1469
+ "return_char_limit": return_char_limit,
1470
+ "pip_requirements": convert_and_respect_annotation_metadata(
1471
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
1472
+ ),
1473
+ },
1474
+ headers={
1475
+ "content-type": "application/json",
1476
+ },
1477
+ request_options=request_options,
1478
+ omit=OMIT,
1479
+ )
1480
+ try:
1481
+ if 200 <= _response.status_code < 300:
1482
+ _data = typing.cast(
1483
+ Tool,
1484
+ construct_type(
1485
+ type_=Tool, # type: ignore
1486
+ object_=_response.json(),
1487
+ ),
1488
+ )
1489
+ return AsyncHttpResponse(response=_response, data=_data)
1490
+ if _response.status_code == 422:
1491
+ raise UnprocessableEntityError(
1492
+ headers=dict(_response.headers),
1493
+ body=typing.cast(
1494
+ HttpValidationError,
1495
+ construct_type(
1496
+ type_=HttpValidationError, # type: ignore
1497
+ object_=_response.json(),
1498
+ ),
1499
+ ),
1500
+ )
1501
+ _response_json = _response.json()
1502
+ except JSONDecodeError:
1503
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1504
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1505
+
1506
+ async def count(
1507
+ self,
1508
+ *,
1509
+ include_base_tools: typing.Optional[bool] = None,
1510
+ request_options: typing.Optional[RequestOptions] = None,
1511
+ ) -> AsyncHttpResponse[int]:
1512
+ """
1513
+ Get a count of all tools available to agents belonging to the org of the user.
1514
+
1515
+ Parameters
1516
+ ----------
1517
+ include_base_tools : typing.Optional[bool]
1518
+ Include built-in Letta tools in the count
1519
+
1520
+ request_options : typing.Optional[RequestOptions]
1521
+ Request-specific configuration.
1522
+
1523
+ Returns
1524
+ -------
1525
+ AsyncHttpResponse[int]
1526
+ Successful Response
1527
+ """
1528
+ _response = await self._client_wrapper.httpx_client.request(
1529
+ "v1/tools/count",
1530
+ method="GET",
1531
+ params={
1532
+ "include_base_tools": include_base_tools,
1533
+ },
1534
+ request_options=request_options,
1535
+ )
1536
+ try:
1537
+ if 200 <= _response.status_code < 300:
1538
+ _data = typing.cast(
1539
+ int,
1540
+ construct_type(
1541
+ type_=int, # type: ignore
1542
+ object_=_response.json(),
1543
+ ),
1544
+ )
1545
+ return AsyncHttpResponse(response=_response, data=_data)
1546
+ if _response.status_code == 422:
1547
+ raise UnprocessableEntityError(
1548
+ headers=dict(_response.headers),
1549
+ body=typing.cast(
1550
+ HttpValidationError,
1551
+ construct_type(
1552
+ type_=HttpValidationError, # type: ignore
1553
+ object_=_response.json(),
1554
+ ),
1555
+ ),
1556
+ )
1557
+ _response_json = _response.json()
1558
+ except JSONDecodeError:
1559
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1560
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1561
+
1562
+ async def list(
1563
+ self,
1564
+ *,
1565
+ after: typing.Optional[str] = None,
1566
+ limit: typing.Optional[int] = None,
1567
+ name: typing.Optional[str] = None,
1568
+ request_options: typing.Optional[RequestOptions] = None,
1569
+ ) -> AsyncHttpResponse[typing.List[Tool]]:
1570
+ """
1571
+ Get a list of all tools available to agents belonging to the org of the user
1572
+
1573
+ Parameters
1574
+ ----------
1575
+ after : typing.Optional[str]
1576
+
1577
+ limit : typing.Optional[int]
1578
+
1579
+ name : typing.Optional[str]
1580
+
1581
+ request_options : typing.Optional[RequestOptions]
1582
+ Request-specific configuration.
1583
+
1584
+ Returns
1585
+ -------
1586
+ AsyncHttpResponse[typing.List[Tool]]
1587
+ Successful Response
1588
+ """
1589
+ _response = await self._client_wrapper.httpx_client.request(
1590
+ "v1/tools/",
1591
+ method="GET",
1592
+ params={
1593
+ "after": after,
1594
+ "limit": limit,
1595
+ "name": name,
1596
+ },
1597
+ request_options=request_options,
1598
+ )
1599
+ try:
1600
+ if 200 <= _response.status_code < 300:
1601
+ _data = typing.cast(
1602
+ typing.List[Tool],
1603
+ construct_type(
1604
+ type_=typing.List[Tool], # type: ignore
1605
+ object_=_response.json(),
1606
+ ),
1607
+ )
1608
+ return AsyncHttpResponse(response=_response, data=_data)
1609
+ if _response.status_code == 422:
1610
+ raise UnprocessableEntityError(
1611
+ headers=dict(_response.headers),
1612
+ body=typing.cast(
1613
+ HttpValidationError,
1614
+ construct_type(
1615
+ type_=HttpValidationError, # type: ignore
1616
+ object_=_response.json(),
1617
+ ),
1618
+ ),
1619
+ )
1620
+ _response_json = _response.json()
1621
+ except JSONDecodeError:
1622
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1623
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1624
+
1625
+ async def create(
1626
+ self,
1627
+ *,
1628
+ source_code: str,
1629
+ description: typing.Optional[str] = OMIT,
1630
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
1631
+ source_type: typing.Optional[str] = OMIT,
1632
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1633
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1634
+ return_char_limit: typing.Optional[int] = OMIT,
1635
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
1636
+ request_options: typing.Optional[RequestOptions] = None,
1637
+ ) -> AsyncHttpResponse[Tool]:
1638
+ """
1639
+ Create a new tool
1640
+
1641
+ Parameters
1642
+ ----------
1643
+ source_code : str
1644
+ The source code of the function.
1645
+
1646
+ description : typing.Optional[str]
1647
+ The description of the tool.
1648
+
1649
+ tags : typing.Optional[typing.Sequence[str]]
1650
+ Metadata tags.
1651
+
1652
+ source_type : typing.Optional[str]
1653
+ The source type of the function.
1654
+
1655
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1656
+ The JSON schema of the function (auto-generated from source_code if not provided)
1657
+
1658
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1659
+ The args JSON schema of the function.
1660
+
1661
+ return_char_limit : typing.Optional[int]
1662
+ The maximum number of characters in the response.
1663
+
1664
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
1665
+ Optional list of pip packages required by this tool.
1666
+
1667
+ request_options : typing.Optional[RequestOptions]
1668
+ Request-specific configuration.
1669
+
1670
+ Returns
1671
+ -------
1672
+ AsyncHttpResponse[Tool]
1673
+ Successful Response
1674
+ """
1675
+ _response = await self._client_wrapper.httpx_client.request(
1676
+ "v1/tools/",
1677
+ method="POST",
1678
+ json={
1679
+ "description": description,
1680
+ "tags": tags,
1681
+ "source_code": source_code,
1682
+ "source_type": source_type,
1683
+ "json_schema": json_schema,
1684
+ "args_json_schema": args_json_schema,
1685
+ "return_char_limit": return_char_limit,
1686
+ "pip_requirements": convert_and_respect_annotation_metadata(
1687
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
1688
+ ),
1689
+ },
1690
+ headers={
1691
+ "content-type": "application/json",
1692
+ },
1693
+ request_options=request_options,
1694
+ omit=OMIT,
1695
+ )
1696
+ try:
1697
+ if 200 <= _response.status_code < 300:
1698
+ _data = typing.cast(
1699
+ Tool,
1700
+ construct_type(
1701
+ type_=Tool, # type: ignore
1702
+ object_=_response.json(),
1703
+ ),
1704
+ )
1705
+ return AsyncHttpResponse(response=_response, data=_data)
1706
+ if _response.status_code == 422:
1707
+ raise UnprocessableEntityError(
1708
+ headers=dict(_response.headers),
1709
+ body=typing.cast(
1710
+ HttpValidationError,
1711
+ construct_type(
1712
+ type_=HttpValidationError, # type: ignore
1713
+ object_=_response.json(),
1714
+ ),
1715
+ ),
1716
+ )
1717
+ _response_json = _response.json()
1718
+ except JSONDecodeError:
1719
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1720
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1721
+
1722
+ async def upsert(
1723
+ self,
1724
+ *,
1725
+ source_code: str,
1726
+ description: typing.Optional[str] = OMIT,
1727
+ tags: typing.Optional[typing.Sequence[str]] = OMIT,
1728
+ source_type: typing.Optional[str] = OMIT,
1729
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1730
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1731
+ return_char_limit: typing.Optional[int] = OMIT,
1732
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
1733
+ request_options: typing.Optional[RequestOptions] = None,
1734
+ ) -> AsyncHttpResponse[Tool]:
1735
+ """
1736
+ Create or update a tool
1737
+
1738
+ Parameters
1739
+ ----------
1740
+ source_code : str
1741
+ The source code of the function.
1742
+
1743
+ description : typing.Optional[str]
1744
+ The description of the tool.
1745
+
1746
+ tags : typing.Optional[typing.Sequence[str]]
1747
+ Metadata tags.
1748
+
1749
+ source_type : typing.Optional[str]
1750
+ The source type of the function.
1751
+
1752
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1753
+ The JSON schema of the function (auto-generated from source_code if not provided)
1754
+
1755
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1756
+ The args JSON schema of the function.
1757
+
1758
+ return_char_limit : typing.Optional[int]
1759
+ The maximum number of characters in the response.
1760
+
1761
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
1762
+ Optional list of pip packages required by this tool.
1763
+
1764
+ request_options : typing.Optional[RequestOptions]
1765
+ Request-specific configuration.
1766
+
1767
+ Returns
1768
+ -------
1769
+ AsyncHttpResponse[Tool]
1770
+ Successful Response
1771
+ """
1772
+ _response = await self._client_wrapper.httpx_client.request(
1773
+ "v1/tools/",
1774
+ method="PUT",
1775
+ json={
1776
+ "description": description,
1777
+ "tags": tags,
1778
+ "source_code": source_code,
1779
+ "source_type": source_type,
1780
+ "json_schema": json_schema,
1781
+ "args_json_schema": args_json_schema,
1782
+ "return_char_limit": return_char_limit,
1783
+ "pip_requirements": convert_and_respect_annotation_metadata(
1784
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
1785
+ ),
1786
+ },
1787
+ headers={
1788
+ "content-type": "application/json",
1789
+ },
1790
+ request_options=request_options,
1791
+ omit=OMIT,
1792
+ )
1793
+ try:
1794
+ if 200 <= _response.status_code < 300:
1795
+ _data = typing.cast(
1796
+ Tool,
1797
+ construct_type(
1798
+ type_=Tool, # type: ignore
1799
+ object_=_response.json(),
1800
+ ),
1801
+ )
1802
+ return AsyncHttpResponse(response=_response, data=_data)
1803
+ if _response.status_code == 422:
1804
+ raise UnprocessableEntityError(
1805
+ headers=dict(_response.headers),
1806
+ body=typing.cast(
1807
+ HttpValidationError,
1808
+ construct_type(
1809
+ type_=HttpValidationError, # type: ignore
1810
+ object_=_response.json(),
1811
+ ),
1812
+ ),
1813
+ )
1814
+ _response_json = _response.json()
1815
+ except JSONDecodeError:
1816
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1817
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1818
+
1819
+ async def upsert_base_tools(
1820
+ self, *, request_options: typing.Optional[RequestOptions] = None
1821
+ ) -> AsyncHttpResponse[typing.List[Tool]]:
1822
+ """
1823
+ Upsert base tools
1824
+
1825
+ Parameters
1826
+ ----------
1827
+ request_options : typing.Optional[RequestOptions]
1828
+ Request-specific configuration.
1829
+
1830
+ Returns
1831
+ -------
1832
+ AsyncHttpResponse[typing.List[Tool]]
1833
+ Successful Response
1834
+ """
1835
+ _response = await self._client_wrapper.httpx_client.request(
1836
+ "v1/tools/add-base-tools",
1837
+ method="POST",
1838
+ request_options=request_options,
1839
+ )
1840
+ try:
1841
+ if 200 <= _response.status_code < 300:
1842
+ _data = typing.cast(
1843
+ typing.List[Tool],
1844
+ construct_type(
1845
+ type_=typing.List[Tool], # type: ignore
1846
+ object_=_response.json(),
1847
+ ),
1848
+ )
1849
+ return AsyncHttpResponse(response=_response, data=_data)
1850
+ if _response.status_code == 422:
1851
+ raise UnprocessableEntityError(
1852
+ headers=dict(_response.headers),
1853
+ body=typing.cast(
1854
+ HttpValidationError,
1855
+ construct_type(
1856
+ type_=HttpValidationError, # type: ignore
1857
+ object_=_response.json(),
1858
+ ),
1859
+ ),
1860
+ )
1861
+ _response_json = _response.json()
1862
+ except JSONDecodeError:
1863
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1864
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1865
+
1866
+ async def run_tool_from_source(
1867
+ self,
1868
+ *,
1869
+ source_code: str,
1870
+ args: typing.Dict[str, typing.Optional[typing.Any]],
1871
+ env_vars: typing.Optional[typing.Dict[str, str]] = OMIT,
1872
+ name: typing.Optional[str] = OMIT,
1873
+ source_type: typing.Optional[str] = OMIT,
1874
+ args_json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1875
+ json_schema: typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]] = OMIT,
1876
+ pip_requirements: typing.Optional[typing.Sequence[PipRequirement]] = OMIT,
1877
+ request_options: typing.Optional[RequestOptions] = None,
1878
+ ) -> AsyncHttpResponse[ToolReturnMessage]:
1879
+ """
1880
+ Attempt to build a tool from source, then run it on the provided arguments
1881
+
1882
+ Parameters
1883
+ ----------
1884
+ source_code : str
1885
+ The source code of the function.
1886
+
1887
+ args : typing.Dict[str, typing.Optional[typing.Any]]
1888
+ The arguments to pass to the tool.
1889
+
1890
+ env_vars : typing.Optional[typing.Dict[str, str]]
1891
+ The environment variables to pass to the tool.
1892
+
1893
+ name : typing.Optional[str]
1894
+ The name of the tool to run.
1895
+
1896
+ source_type : typing.Optional[str]
1897
+ The type of the source code.
1898
+
1899
+ args_json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1900
+ The args JSON schema of the function.
1901
+
1902
+ json_schema : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
1903
+ The JSON schema of the function (auto-generated from source_code if not provided)
1904
+
1905
+ pip_requirements : typing.Optional[typing.Sequence[PipRequirement]]
1906
+ Optional list of pip packages required by this tool.
1907
+
1908
+ request_options : typing.Optional[RequestOptions]
1909
+ Request-specific configuration.
1910
+
1911
+ Returns
1912
+ -------
1913
+ AsyncHttpResponse[ToolReturnMessage]
1914
+ Successful Response
1915
+ """
1916
+ _response = await self._client_wrapper.httpx_client.request(
1917
+ "v1/tools/run",
1918
+ method="POST",
1919
+ json={
1920
+ "source_code": source_code,
1921
+ "args": args,
1922
+ "env_vars": env_vars,
1923
+ "name": name,
1924
+ "source_type": source_type,
1925
+ "args_json_schema": args_json_schema,
1926
+ "json_schema": json_schema,
1927
+ "pip_requirements": convert_and_respect_annotation_metadata(
1928
+ object_=pip_requirements, annotation=typing.Sequence[PipRequirement], direction="write"
1929
+ ),
1930
+ },
1931
+ headers={
1932
+ "content-type": "application/json",
1933
+ },
1934
+ request_options=request_options,
1935
+ omit=OMIT,
1936
+ )
1937
+ try:
1938
+ if 200 <= _response.status_code < 300:
1939
+ _data = typing.cast(
1940
+ ToolReturnMessage,
1941
+ construct_type(
1942
+ type_=ToolReturnMessage, # type: ignore
1943
+ object_=_response.json(),
1944
+ ),
1945
+ )
1946
+ return AsyncHttpResponse(response=_response, data=_data)
1947
+ if _response.status_code == 422:
1948
+ raise UnprocessableEntityError(
1949
+ headers=dict(_response.headers),
1950
+ body=typing.cast(
1951
+ HttpValidationError,
1952
+ construct_type(
1953
+ type_=HttpValidationError, # type: ignore
1954
+ object_=_response.json(),
1955
+ ),
1956
+ ),
1957
+ )
1958
+ _response_json = _response.json()
1959
+ except JSONDecodeError:
1960
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1961
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1962
+
1963
+ async def list_composio_apps(
1964
+ self, *, user_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
1965
+ ) -> AsyncHttpResponse[typing.List[AppModel]]:
1966
+ """
1967
+ Get a list of all Composio apps
1968
+
1969
+ Parameters
1970
+ ----------
1971
+ user_id : typing.Optional[str]
1972
+
1973
+ request_options : typing.Optional[RequestOptions]
1974
+ Request-specific configuration.
1975
+
1976
+ Returns
1977
+ -------
1978
+ AsyncHttpResponse[typing.List[AppModel]]
1979
+ Successful Response
1980
+ """
1981
+ _response = await self._client_wrapper.httpx_client.request(
1982
+ "v1/tools/composio/apps",
1983
+ method="GET",
1984
+ headers={
1985
+ "user-id": str(user_id) if user_id is not None else None,
1986
+ },
1987
+ request_options=request_options,
1988
+ )
1989
+ try:
1990
+ if 200 <= _response.status_code < 300:
1991
+ _data = typing.cast(
1992
+ typing.List[AppModel],
1993
+ construct_type(
1994
+ type_=typing.List[AppModel], # type: ignore
1995
+ object_=_response.json(),
1996
+ ),
1997
+ )
1998
+ return AsyncHttpResponse(response=_response, data=_data)
1999
+ if _response.status_code == 422:
2000
+ raise UnprocessableEntityError(
2001
+ headers=dict(_response.headers),
2002
+ body=typing.cast(
2003
+ HttpValidationError,
2004
+ construct_type(
2005
+ type_=HttpValidationError, # type: ignore
2006
+ object_=_response.json(),
2007
+ ),
2008
+ ),
2009
+ )
2010
+ _response_json = _response.json()
2011
+ except JSONDecodeError:
2012
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2013
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2014
+
2015
+ async def list_composio_actions_by_app(
2016
+ self, composio_app_name: str, *, request_options: typing.Optional[RequestOptions] = None
2017
+ ) -> AsyncHttpResponse[typing.List[ActionModel]]:
2018
+ """
2019
+ Get a list of all Composio actions for a specific app
2020
+
2021
+ Parameters
2022
+ ----------
2023
+ composio_app_name : str
2024
+
2025
+ request_options : typing.Optional[RequestOptions]
2026
+ Request-specific configuration.
2027
+
2028
+ Returns
2029
+ -------
2030
+ AsyncHttpResponse[typing.List[ActionModel]]
2031
+ Successful Response
2032
+ """
2033
+ _response = await self._client_wrapper.httpx_client.request(
2034
+ f"v1/tools/composio/apps/{jsonable_encoder(composio_app_name)}/actions",
2035
+ method="GET",
2036
+ request_options=request_options,
2037
+ )
2038
+ try:
2039
+ if 200 <= _response.status_code < 300:
2040
+ _data = typing.cast(
2041
+ typing.List[ActionModel],
2042
+ construct_type(
2043
+ type_=typing.List[ActionModel], # type: ignore
2044
+ object_=_response.json(),
2045
+ ),
2046
+ )
2047
+ return AsyncHttpResponse(response=_response, data=_data)
2048
+ if _response.status_code == 422:
2049
+ raise UnprocessableEntityError(
2050
+ headers=dict(_response.headers),
2051
+ body=typing.cast(
2052
+ HttpValidationError,
2053
+ construct_type(
2054
+ type_=HttpValidationError, # type: ignore
2055
+ object_=_response.json(),
2056
+ ),
2057
+ ),
2058
+ )
2059
+ _response_json = _response.json()
2060
+ except JSONDecodeError:
2061
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2062
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2063
+
2064
+ async def add_composio_tool(
2065
+ self, composio_action_name: str, *, request_options: typing.Optional[RequestOptions] = None
2066
+ ) -> AsyncHttpResponse[Tool]:
2067
+ """
2068
+ Add a new Composio tool by action name (Composio refers to each tool as an `Action`)
2069
+
2070
+ Parameters
2071
+ ----------
2072
+ composio_action_name : str
2073
+
2074
+ request_options : typing.Optional[RequestOptions]
2075
+ Request-specific configuration.
2076
+
2077
+ Returns
2078
+ -------
2079
+ AsyncHttpResponse[Tool]
2080
+ Successful Response
2081
+ """
2082
+ _response = await self._client_wrapper.httpx_client.request(
2083
+ f"v1/tools/composio/{jsonable_encoder(composio_action_name)}",
2084
+ method="POST",
2085
+ request_options=request_options,
2086
+ )
2087
+ try:
2088
+ if 200 <= _response.status_code < 300:
2089
+ _data = typing.cast(
2090
+ Tool,
2091
+ construct_type(
2092
+ type_=Tool, # type: ignore
2093
+ object_=_response.json(),
2094
+ ),
2095
+ )
2096
+ return AsyncHttpResponse(response=_response, data=_data)
2097
+ if _response.status_code == 422:
2098
+ raise UnprocessableEntityError(
2099
+ headers=dict(_response.headers),
2100
+ body=typing.cast(
2101
+ HttpValidationError,
2102
+ construct_type(
2103
+ type_=HttpValidationError, # type: ignore
2104
+ object_=_response.json(),
2105
+ ),
2106
+ ),
2107
+ )
2108
+ _response_json = _response.json()
2109
+ except JSONDecodeError:
2110
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2111
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2112
+
2113
+ async def list_mcp_servers(
2114
+ self, *, user_id: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
2115
+ ) -> AsyncHttpResponse[typing.Dict[str, ListMcpServersResponseValue]]:
2116
+ """
2117
+ Get a list of all configured MCP servers
2118
+
2119
+ Parameters
2120
+ ----------
2121
+ user_id : typing.Optional[str]
2122
+
2123
+ request_options : typing.Optional[RequestOptions]
2124
+ Request-specific configuration.
2125
+
2126
+ Returns
2127
+ -------
2128
+ AsyncHttpResponse[typing.Dict[str, ListMcpServersResponseValue]]
2129
+ Successful Response
2130
+ """
2131
+ _response = await self._client_wrapper.httpx_client.request(
2132
+ "v1/tools/mcp/servers",
2133
+ method="GET",
2134
+ headers={
2135
+ "user-id": str(user_id) if user_id is not None else None,
2136
+ },
2137
+ request_options=request_options,
2138
+ )
2139
+ try:
2140
+ if 200 <= _response.status_code < 300:
2141
+ _data = typing.cast(
2142
+ typing.Dict[str, ListMcpServersResponseValue],
2143
+ construct_type(
2144
+ type_=typing.Dict[str, ListMcpServersResponseValue], # type: ignore
2145
+ object_=_response.json(),
2146
+ ),
2147
+ )
2148
+ return AsyncHttpResponse(response=_response, data=_data)
2149
+ if _response.status_code == 422:
2150
+ raise UnprocessableEntityError(
2151
+ headers=dict(_response.headers),
2152
+ body=typing.cast(
2153
+ HttpValidationError,
2154
+ construct_type(
2155
+ type_=HttpValidationError, # type: ignore
2156
+ object_=_response.json(),
2157
+ ),
2158
+ ),
2159
+ )
2160
+ _response_json = _response.json()
2161
+ except JSONDecodeError:
2162
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2163
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2164
+
2165
+ async def add_mcp_server(
2166
+ self, *, request: AddMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
2167
+ ) -> AsyncHttpResponse[typing.List[AddMcpServerResponseItem]]:
2168
+ """
2169
+ Add a new MCP server to the Letta MCP server config
2170
+
2171
+ Parameters
2172
+ ----------
2173
+ request : AddMcpServerRequest
2174
+
2175
+ request_options : typing.Optional[RequestOptions]
2176
+ Request-specific configuration.
2177
+
2178
+ Returns
2179
+ -------
2180
+ AsyncHttpResponse[typing.List[AddMcpServerResponseItem]]
2181
+ Successful Response
2182
+ """
2183
+ _response = await self._client_wrapper.httpx_client.request(
2184
+ "v1/tools/mcp/servers",
2185
+ method="PUT",
2186
+ json=convert_and_respect_annotation_metadata(
2187
+ object_=request, annotation=AddMcpServerRequest, direction="write"
2188
+ ),
2189
+ headers={
2190
+ "content-type": "application/json",
2191
+ },
2192
+ request_options=request_options,
2193
+ omit=OMIT,
2194
+ )
2195
+ try:
2196
+ if 200 <= _response.status_code < 300:
2197
+ _data = typing.cast(
2198
+ typing.List[AddMcpServerResponseItem],
2199
+ construct_type(
2200
+ type_=typing.List[AddMcpServerResponseItem], # type: ignore
2201
+ object_=_response.json(),
2202
+ ),
2203
+ )
2204
+ return AsyncHttpResponse(response=_response, data=_data)
2205
+ if _response.status_code == 422:
2206
+ raise UnprocessableEntityError(
2207
+ headers=dict(_response.headers),
2208
+ body=typing.cast(
2209
+ HttpValidationError,
2210
+ construct_type(
2211
+ type_=HttpValidationError, # type: ignore
2212
+ object_=_response.json(),
2213
+ ),
2214
+ ),
2215
+ )
2216
+ _response_json = _response.json()
2217
+ except JSONDecodeError:
2218
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2219
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2220
+
2221
+ async def list_mcp_tools_by_server(
2222
+ self, mcp_server_name: str, *, request_options: typing.Optional[RequestOptions] = None
2223
+ ) -> AsyncHttpResponse[typing.List[McpTool]]:
2224
+ """
2225
+ Get a list of all tools for a specific MCP server
2226
+
2227
+ Parameters
2228
+ ----------
2229
+ mcp_server_name : str
2230
+
2231
+ request_options : typing.Optional[RequestOptions]
2232
+ Request-specific configuration.
2233
+
2234
+ Returns
2235
+ -------
2236
+ AsyncHttpResponse[typing.List[McpTool]]
2237
+ Successful Response
2238
+ """
2239
+ _response = await self._client_wrapper.httpx_client.request(
2240
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}/tools",
2241
+ method="GET",
2242
+ request_options=request_options,
2243
+ )
2244
+ try:
2245
+ if 200 <= _response.status_code < 300:
2246
+ _data = typing.cast(
2247
+ typing.List[McpTool],
2248
+ construct_type(
2249
+ type_=typing.List[McpTool], # type: ignore
2250
+ object_=_response.json(),
2251
+ ),
2252
+ )
2253
+ return AsyncHttpResponse(response=_response, data=_data)
2254
+ if _response.status_code == 422:
2255
+ raise UnprocessableEntityError(
2256
+ headers=dict(_response.headers),
2257
+ body=typing.cast(
2258
+ HttpValidationError,
2259
+ construct_type(
2260
+ type_=HttpValidationError, # type: ignore
2261
+ object_=_response.json(),
2262
+ ),
2263
+ ),
2264
+ )
2265
+ _response_json = _response.json()
2266
+ except JSONDecodeError:
2267
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2268
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2269
+
2270
+ async def add_mcp_tool(
2271
+ self, mcp_server_name: str, mcp_tool_name: str, *, request_options: typing.Optional[RequestOptions] = None
2272
+ ) -> AsyncHttpResponse[Tool]:
2273
+ """
2274
+ Register a new MCP tool as a Letta server by MCP server + tool name
2275
+
2276
+ Parameters
2277
+ ----------
2278
+ mcp_server_name : str
2279
+
2280
+ mcp_tool_name : str
2281
+
2282
+ request_options : typing.Optional[RequestOptions]
2283
+ Request-specific configuration.
2284
+
2285
+ Returns
2286
+ -------
2287
+ AsyncHttpResponse[Tool]
2288
+ Successful Response
2289
+ """
2290
+ _response = await self._client_wrapper.httpx_client.request(
2291
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}/{jsonable_encoder(mcp_tool_name)}",
2292
+ method="POST",
2293
+ request_options=request_options,
2294
+ )
2295
+ try:
2296
+ if 200 <= _response.status_code < 300:
2297
+ _data = typing.cast(
2298
+ Tool,
2299
+ construct_type(
2300
+ type_=Tool, # type: ignore
2301
+ object_=_response.json(),
2302
+ ),
2303
+ )
2304
+ return AsyncHttpResponse(response=_response, data=_data)
2305
+ if _response.status_code == 422:
2306
+ raise UnprocessableEntityError(
2307
+ headers=dict(_response.headers),
2308
+ body=typing.cast(
2309
+ HttpValidationError,
2310
+ construct_type(
2311
+ type_=HttpValidationError, # type: ignore
2312
+ object_=_response.json(),
2313
+ ),
2314
+ ),
2315
+ )
2316
+ _response_json = _response.json()
2317
+ except JSONDecodeError:
2318
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2319
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2320
+
2321
+ async def delete_mcp_server(
2322
+ self, mcp_server_name: str, *, request_options: typing.Optional[RequestOptions] = None
2323
+ ) -> AsyncHttpResponse[typing.List[DeleteMcpServerResponseItem]]:
2324
+ """
2325
+ Add a new MCP server to the Letta MCP server config
2326
+
2327
+ Parameters
2328
+ ----------
2329
+ mcp_server_name : str
2330
+
2331
+ request_options : typing.Optional[RequestOptions]
2332
+ Request-specific configuration.
2333
+
2334
+ Returns
2335
+ -------
2336
+ AsyncHttpResponse[typing.List[DeleteMcpServerResponseItem]]
2337
+ Successful Response
2338
+ """
2339
+ _response = await self._client_wrapper.httpx_client.request(
2340
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}",
2341
+ method="DELETE",
2342
+ request_options=request_options,
2343
+ )
2344
+ try:
2345
+ if 200 <= _response.status_code < 300:
2346
+ _data = typing.cast(
2347
+ typing.List[DeleteMcpServerResponseItem],
2348
+ construct_type(
2349
+ type_=typing.List[DeleteMcpServerResponseItem], # type: ignore
2350
+ object_=_response.json(),
2351
+ ),
2352
+ )
2353
+ return AsyncHttpResponse(response=_response, data=_data)
2354
+ if _response.status_code == 422:
2355
+ raise UnprocessableEntityError(
2356
+ headers=dict(_response.headers),
2357
+ body=typing.cast(
2358
+ HttpValidationError,
2359
+ construct_type(
2360
+ type_=HttpValidationError, # type: ignore
2361
+ object_=_response.json(),
2362
+ ),
2363
+ ),
2364
+ )
2365
+ _response_json = _response.json()
2366
+ except JSONDecodeError:
2367
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2368
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2369
+
2370
+ async def update_mcp_server(
2371
+ self,
2372
+ mcp_server_name: str,
2373
+ *,
2374
+ request: UpdateMcpServerRequest,
2375
+ request_options: typing.Optional[RequestOptions] = None,
2376
+ ) -> AsyncHttpResponse[UpdateMcpServerResponse]:
2377
+ """
2378
+ Update an existing MCP server configuration
2379
+
2380
+ Parameters
2381
+ ----------
2382
+ mcp_server_name : str
2383
+
2384
+ request : UpdateMcpServerRequest
2385
+
2386
+ request_options : typing.Optional[RequestOptions]
2387
+ Request-specific configuration.
2388
+
2389
+ Returns
2390
+ -------
2391
+ AsyncHttpResponse[UpdateMcpServerResponse]
2392
+ Successful Response
2393
+ """
2394
+ _response = await self._client_wrapper.httpx_client.request(
2395
+ f"v1/tools/mcp/servers/{jsonable_encoder(mcp_server_name)}",
2396
+ method="PATCH",
2397
+ json=convert_and_respect_annotation_metadata(
2398
+ object_=request, annotation=UpdateMcpServerRequest, direction="write"
2399
+ ),
2400
+ headers={
2401
+ "content-type": "application/json",
2402
+ },
2403
+ request_options=request_options,
2404
+ omit=OMIT,
2405
+ )
2406
+ try:
2407
+ if 200 <= _response.status_code < 300:
2408
+ _data = typing.cast(
2409
+ UpdateMcpServerResponse,
2410
+ construct_type(
2411
+ type_=UpdateMcpServerResponse, # type: ignore
2412
+ object_=_response.json(),
2413
+ ),
2414
+ )
2415
+ return AsyncHttpResponse(response=_response, data=_data)
2416
+ if _response.status_code == 422:
2417
+ raise UnprocessableEntityError(
2418
+ headers=dict(_response.headers),
2419
+ body=typing.cast(
2420
+ HttpValidationError,
2421
+ construct_type(
2422
+ type_=HttpValidationError, # type: ignore
2423
+ object_=_response.json(),
2424
+ ),
2425
+ ),
2426
+ )
2427
+ _response_json = _response.json()
2428
+ except JSONDecodeError:
2429
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2430
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2431
+
2432
+ async def test_mcp_server(
2433
+ self, *, request: TestMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
2434
+ ) -> AsyncHttpResponse[typing.Optional[typing.Any]]:
2435
+ """
2436
+ Test connection to an MCP server without adding it.
2437
+ Returns the list of available tools if successful.
2438
+
2439
+ Parameters
2440
+ ----------
2441
+ request : TestMcpServerRequest
2442
+
2443
+ request_options : typing.Optional[RequestOptions]
2444
+ Request-specific configuration.
2445
+
2446
+ Returns
2447
+ -------
2448
+ AsyncHttpResponse[typing.Optional[typing.Any]]
2449
+ Successful Response
2450
+ """
2451
+ _response = await self._client_wrapper.httpx_client.request(
2452
+ "v1/tools/mcp/servers/test",
2453
+ method="POST",
2454
+ json=convert_and_respect_annotation_metadata(
2455
+ object_=request, annotation=TestMcpServerRequest, direction="write"
2456
+ ),
2457
+ headers={
2458
+ "content-type": "application/json",
2459
+ },
2460
+ request_options=request_options,
2461
+ omit=OMIT,
2462
+ )
2463
+ try:
2464
+ if _response is None or not _response.text.strip():
2465
+ return AsyncHttpResponse(response=_response, data=None)
2466
+ if 200 <= _response.status_code < 300:
2467
+ _data = typing.cast(
2468
+ typing.Optional[typing.Any],
2469
+ construct_type(
2470
+ type_=typing.Optional[typing.Any], # type: ignore
2471
+ object_=_response.json(),
2472
+ ),
2473
+ )
2474
+ return AsyncHttpResponse(response=_response, data=_data)
2475
+ if _response.status_code == 422:
2476
+ raise UnprocessableEntityError(
2477
+ headers=dict(_response.headers),
2478
+ body=typing.cast(
2479
+ HttpValidationError,
2480
+ construct_type(
2481
+ type_=HttpValidationError, # type: ignore
2482
+ object_=_response.json(),
2483
+ ),
2484
+ ),
2485
+ )
2486
+ _response_json = _response.json()
2487
+ except JSONDecodeError:
2488
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
2489
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2490
+
2491
+ @contextlib.asynccontextmanager
2492
+ async def connect_mcp_server(
2493
+ self, *, request: ConnectMcpServerRequest, request_options: typing.Optional[RequestOptions] = None
2494
+ ) -> typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[StreamingResponse]]]:
2495
+ """
2496
+ Connect to an MCP server with support for OAuth via SSE.
2497
+ Returns a stream of events handling authorization state and exchange if OAuth is required.
2498
+
2499
+ Parameters
2500
+ ----------
2501
+ request : ConnectMcpServerRequest
2502
+
2503
+ request_options : typing.Optional[RequestOptions]
2504
+ Request-specific configuration.
2505
+
2506
+ Yields
2507
+ ------
2508
+ typing.AsyncIterator[AsyncHttpResponse[typing.AsyncIterator[StreamingResponse]]]
2509
+ Successful response
2510
+ """
2511
+ async with self._client_wrapper.httpx_client.stream(
2512
+ "v1/tools/mcp/servers/connect",
2513
+ method="POST",
2514
+ json=convert_and_respect_annotation_metadata(
2515
+ object_=request, annotation=ConnectMcpServerRequest, direction="write"
2516
+ ),
2517
+ headers={
2518
+ "content-type": "application/json",
2519
+ },
2520
+ request_options=request_options,
2521
+ omit=OMIT,
2522
+ ) as _response:
2523
+
2524
+ async def _stream() -> AsyncHttpResponse[typing.AsyncIterator[StreamingResponse]]:
2525
+ try:
2526
+ if 200 <= _response.status_code < 300:
2527
+
2528
+ async def _iter():
2529
+ _event_source = httpx_sse.EventSource(_response)
2530
+ async for _sse in _event_source.aiter_sse():
2531
+ if _sse.data == None:
2532
+ return
2533
+ try:
2534
+ yield typing.cast(
2535
+ StreamingResponse,
2536
+ construct_type(
2537
+ type_=StreamingResponse, # type: ignore
2538
+ object_=json.loads(_sse.data),
2539
+ ),
2540
+ )
2541
+ except Exception:
2542
+ pass
2543
+ return
2544
+
2545
+ return AsyncHttpResponse(response=_response, data=_iter())
2546
+ await _response.aread()
2547
+ if _response.status_code == 422:
2548
+ raise UnprocessableEntityError(
2549
+ headers=dict(_response.headers),
2550
+ body=typing.cast(
2551
+ HttpValidationError,
2552
+ construct_type(
2553
+ type_=HttpValidationError, # type: ignore
2554
+ object_=_response.json(),
2555
+ ),
2556
+ ),
2557
+ )
2558
+ _response_json = _response.json()
2559
+ except JSONDecodeError:
2560
+ raise ApiError(
2561
+ status_code=_response.status_code, headers=dict(_response.headers), body=_response.text
2562
+ )
2563
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
2564
+
2565
+ yield await _stream()