sunholo 0.143.3__tar.gz → 0.143.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. {sunholo-0.143.3/src/sunholo.egg-info → sunholo-0.143.9}/PKG-INFO +1 -1
  2. {sunholo-0.143.3 → sunholo-0.143.9}/pyproject.toml +1 -1
  3. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/__init__.py +4 -1
  4. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/vac_routes.py +54 -63
  5. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/__init__.py +11 -2
  6. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/mcp_manager.py +66 -28
  7. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/vac_mcp_server.py +28 -21
  8. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/streaming.py +8 -8
  9. {sunholo-0.143.3 → sunholo-0.143.9/src/sunholo.egg-info}/PKG-INFO +1 -1
  10. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/SOURCES.txt +1 -2
  11. sunholo-0.143.3/tests/test_vac_routes_mcp.py +0 -339
  12. {sunholo-0.143.3 → sunholo-0.143.9}/LICENSE.txt +0 -0
  13. {sunholo-0.143.3 → sunholo-0.143.9}/MANIFEST.in +0 -0
  14. {sunholo-0.143.3 → sunholo-0.143.9}/README.md +0 -0
  15. {sunholo-0.143.3 → sunholo-0.143.9}/setup.cfg +0 -0
  16. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/__init__.py +0 -0
  17. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/agent_card.py +0 -0
  18. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/task_manager.py +0 -0
  19. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
  20. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/__init__.py +0 -0
  21. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/chat_history.py +0 -0
  22. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/dispatch_to_qa.py +0 -0
  23. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/__init__.py +0 -0
  24. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/base.py +0 -0
  25. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
  26. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/__init__.py +0 -0
  27. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/base.py +0 -0
  28. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/langserve.py +0 -0
  29. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/pubsub.py +0 -0
  30. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/route.py +0 -0
  31. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/special_commands.py +0 -0
  32. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/swagger.py +0 -0
  33. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/archive/__init__.py +0 -0
  34. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/archive/archive.py +0 -0
  35. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/__init__.py +0 -0
  36. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/gcloud.py +0 -0
  37. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/refresh.py +0 -0
  38. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/run.py +0 -0
  39. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/__init__.py +0 -0
  40. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/auth.py +0 -0
  41. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/blobs.py +0 -0
  42. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/event_grid.py +0 -0
  43. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/__init__.py +0 -0
  44. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/discord.py +0 -0
  45. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/github_webhook.py +0 -0
  46. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/webapp.py +0 -0
  47. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/__init__.py +0 -0
  48. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/azure.py +0 -0
  49. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/doc_handling.py +0 -0
  50. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/encode_metadata.py +0 -0
  51. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/images.py +0 -0
  52. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/loaders.py +0 -0
  53. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/message_data.py +0 -0
  54. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/pdfs.py +0 -0
  55. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/process_chunker_data.py +0 -0
  56. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/publish.py +0 -0
  57. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/pubsub.py +0 -0
  58. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/splitter.py +0 -0
  59. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/__init__.py +0 -0
  60. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/chat_vac.py +0 -0
  61. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/cli.py +0 -0
  62. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/cli_init.py +0 -0
  63. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/configs.py +0 -0
  64. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/deploy.py +0 -0
  65. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/embedder.py +0 -0
  66. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/merge_texts.py +0 -0
  67. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/run_proxy.py +0 -0
  68. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/sun_rich.py +0 -0
  69. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/swagger.py +0 -0
  70. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/vertex.py +0 -0
  71. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/__init__.py +0 -0
  72. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/llm.py +0 -0
  73. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/retriever.py +0 -0
  74. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/vectorstore.py +0 -0
  75. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/custom_logging.py +0 -0
  76. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/__init__.py +0 -0
  77. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/alloydb.py +0 -0
  78. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/alloydb_client.py +0 -0
  79. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/database.py +0 -0
  80. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/lancedb.py +0 -0
  81. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_function.sql +0 -0
  82. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
  83. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_table.sql +0 -0
  84. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
  85. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
  86. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/setup.sql +0 -0
  87. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/static_dbs.py +0 -0
  88. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/uuid.py +0 -0
  89. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/__init__.py +0 -0
  90. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
  91. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/cli.py +0 -0
  92. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/create_new.py +0 -0
  93. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
  94. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
  95. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/__init__.py +0 -0
  96. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/embed_chunk.py +0 -0
  97. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/embed_metadata.py +0 -0
  98. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/excel/__init__.py +0 -0
  99. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/excel/plugin.py +0 -0
  100. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/__init__.py +0 -0
  101. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/add_file.py +0 -0
  102. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_folder.py +0 -0
  103. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_gcs_text.py +0 -0
  104. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_url.py +0 -0
  105. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/extract_and_sign.py +0 -0
  106. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/metadata.py +0 -0
  107. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/__init__.py +0 -0
  108. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/file_handling.py +0 -0
  109. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/genaiv2.py +0 -0
  110. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/images.py +0 -0
  111. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/init.py +0 -0
  112. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/process_funcs_cls.py +0 -0
  113. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/safety.py +0 -0
  114. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/__init__.py +0 -0
  115. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/async_class.py +0 -0
  116. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/direct_vac_func.py +0 -0
  117. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
  118. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langchain_types.py +0 -0
  119. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/__init__.py +0 -0
  120. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/callback.py +0 -0
  121. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/evals.py +0 -0
  122. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/prompts.py +0 -0
  123. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/__init__.py +0 -0
  124. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/get_files.py +0 -0
  125. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/import_files.py +0 -0
  126. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
  127. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/user_history.py +0 -0
  128. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/lookup/__init__.py +0 -0
  129. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/lookup/model_lookup.yaml +0 -0
  130. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/cli.py +0 -0
  131. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/ollama/__init__.py +0 -0
  132. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/ollama/ollama_images.py +0 -0
  133. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/__init__.py +0 -0
  134. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/process_pubsub.py +0 -0
  135. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/pubsub_manager.py +0 -0
  136. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/__init__.py +0 -0
  137. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/parsers.py +0 -0
  138. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/retry.py +0 -0
  139. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/senses/__init__.py +0 -0
  140. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/senses/stream_voice.py +0 -0
  141. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/__init__.py +0 -0
  142. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/content_buffer.py +0 -0
  143. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/langserve.py +0 -0
  144. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/stream_lookup.py +0 -0
  145. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/summarise/__init__.py +0 -0
  146. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/summarise/summarise.py +0 -0
  147. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/__init__.py +0 -0
  148. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/agent_service.py +0 -0
  149. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/app.py +0 -0
  150. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/my_log.py +0 -0
  151. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/tools/__init__.py +0 -0
  152. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
  153. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/vac_service.py +0 -0
  154. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/__init__.py +0 -0
  155. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/app.py +0 -0
  156. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/my_log.py +0 -0
  157. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/vac_service.py +0 -0
  158. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/__init__.py +0 -0
  159. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/app.py +0 -0
  160. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/my_log.py +0 -0
  161. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/terraform/__init__.py +0 -0
  162. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/terraform/tfvars_editor.py +0 -0
  163. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/tools/__init__.py +0 -0
  164. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/tools/web_browser.py +0 -0
  165. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/__init__.py +0 -0
  166. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/api_key.py +0 -0
  167. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/big_context.py +0 -0
  168. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config.py +0 -0
  169. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config_class.py +0 -0
  170. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config_schema.py +0 -0
  171. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/gcp.py +0 -0
  172. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/gcp_project.py +0 -0
  173. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/mime.py +0 -0
  174. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/parsers.py +0 -0
  175. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/proto_convert.py +0 -0
  176. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/timedelta.py +0 -0
  177. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/user_ids.py +0 -0
  178. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/version.py +0 -0
  179. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/__init__.py +0 -0
  180. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/extensions_call.py +0 -0
  181. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/extensions_class.py +0 -0
  182. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/genai_functions.py +0 -0
  183. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/init.py +0 -0
  184. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/memory_tools.py +0 -0
  185. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/safety.py +0 -0
  186. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/type_dict_to_json.py +0 -0
  187. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/dependency_links.txt +0 -0
  188. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/entry_points.txt +0 -0
  189. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/requires.txt +0 -0
  190. {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/top_level.txt +0 -0
  191. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_async.py +0 -0
  192. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_async_genai2.py +0 -0
  193. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_chat_history.py +0 -0
  194. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_config.py +0 -0
  195. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_genai2.py +0 -0
  196. {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_unstructured.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.143.3
3
+ Version: 0.143.9
4
4
  Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
5
  Author-email: Holosun ApS <multivac@sunholo.com>
6
6
  License: Apache License, Version 2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sunholo"
7
- version = "0.143.3"
7
+ version = "0.143.9"
8
8
  description = "AI DevOps - a package to help deploy GenAI to the Cloud."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -15,7 +15,10 @@ from . import invoke
15
15
  from . import langfuse
16
16
  from . import llamaindex
17
17
  from . import lookup
18
- from . import mcp
18
+ try:
19
+ from . import mcp
20
+ except ImportError:
21
+ mcp = None
19
22
  from . import ollama
20
23
  from . import pubsub
21
24
  from . import qna
@@ -38,12 +38,14 @@ except ImportError:
38
38
 
39
39
  try:
40
40
  from ...mcp.vac_mcp_server import VACMCPServer
41
- from mcp.server.models import InitializationOptions
42
- from mcp import JSONRPCMessage, ErrorData, INTERNAL_ERROR
41
+ from mcp.server import Server
42
+ from mcp.types import JSONRPCMessage, ErrorData, INTERNAL_ERROR
43
43
  except ImportError:
44
44
  VACMCPServer = None
45
- InitializationOptions = None
45
+ Server = None
46
46
  JSONRPCMessage = None
47
+ ErrorData = None
48
+ INTERNAL_ERROR = None
47
49
 
48
50
  try:
49
51
  from ...a2a.vac_a2a_agent import VACA2AAgent
@@ -1024,75 +1026,64 @@ if __name__ == "__main__":
1024
1026
 
1025
1027
  # Create an async handler for the request
1026
1028
  async def process_request():
1027
- # Create mock read/write streams for the server
1028
- from io import StringIO
1029
- import asyncio
1029
+ # Handle JSON-RPC requests directly
1030
+ if not isinstance(data, dict) or "method" not in data:
1031
+ raise ValueError("Invalid JSON-RPC request")
1030
1032
 
1031
- # Convert request to proper format
1032
- request_str = json_module.dumps(data) + '\n'
1033
-
1034
- # Create read queue with the request
1035
- read_queue = asyncio.Queue()
1036
- await read_queue.put(request_str.encode())
1037
- await read_queue.put(None) # EOF signal
1038
-
1039
- # Create write queue for response
1040
- write_queue = asyncio.Queue()
1041
-
1042
- # Create async iterators
1043
- async def read_messages():
1044
- while True:
1045
- msg = await read_queue.get()
1046
- if msg is None:
1047
- break
1048
- yield msg
1049
-
1050
- responses = []
1051
- async def write_messages():
1052
- async for msg in write_queue:
1053
- if msg is None:
1054
- break
1055
- responses.append(msg.decode())
1056
-
1057
- # Run the server with these streams
1058
- server = self.vac_mcp_server.get_server()
1059
-
1060
- # Start write handler
1061
- write_task = asyncio.create_task(write_messages())
1033
+ method = data["method"]
1034
+ params = data.get("params", {})
1035
+ request_id = data.get("id")
1062
1036
 
1063
1037
  try:
1064
- # Process the request through the server
1065
- await server.run(
1066
- read_messages(),
1067
- write_queue,
1068
- InitializationOptions() if InitializationOptions else None
1069
- )
1038
+ # Handle different MCP methods
1039
+ if method == "tools/list":
1040
+ # Get the server and call list_tools handler
1041
+ server = self.vac_mcp_server.get_server()
1042
+ tools = await server._request_handlers["tools/list"]()
1043
+
1044
+ return {
1045
+ "jsonrpc": "2.0",
1046
+ "result": {"tools": [tool.model_dump() for tool in tools]},
1047
+ "id": request_id
1048
+ }
1049
+
1050
+ elif method == "tools/call":
1051
+ # Handle tool calls
1052
+ tool_name = params.get("name")
1053
+ arguments = params.get("arguments", {})
1054
+
1055
+ if not tool_name:
1056
+ raise ValueError("Missing tool name")
1057
+
1058
+ server = self.vac_mcp_server.get_server()
1059
+ result = await server._request_handlers["tools/call"](tool_name, arguments)
1060
+
1061
+ return {
1062
+ "jsonrpc": "2.0",
1063
+ "result": {"content": [item.model_dump() for item in result]},
1064
+ "id": request_id
1065
+ }
1066
+
1067
+ else:
1068
+ raise ValueError(f"Unknown method: {method}")
1069
+
1070
1070
  except Exception as e:
1071
- log.error(f"Error processing MCP request: {e}")
1072
- await write_queue.put(None)
1073
- await write_task
1074
- raise
1075
-
1076
- # Signal end and wait for write task
1077
- await write_queue.put(None)
1078
- await write_task
1079
-
1080
- # Return collected responses
1081
- return responses
1071
+ log.error(f"Error handling MCP method {method}: {e}")
1072
+ return {
1073
+ "jsonrpc": "2.0",
1074
+ "error": {
1075
+ "code": -32603,
1076
+ "message": str(e)
1077
+ },
1078
+ "id": request_id
1079
+ }
1082
1080
 
1083
1081
  # Run the async handler
1084
1082
  loop = asyncio.new_event_loop()
1085
1083
  asyncio.set_event_loop(loop)
1086
1084
  try:
1087
- responses = loop.run_until_complete(process_request())
1088
-
1089
- # Parse and return the response
1090
- if responses:
1091
- # The response should be a single JSON-RPC response
1092
- response_data = json_module.loads(responses[0])
1093
- return jsonify(response_data)
1094
- else:
1095
- return jsonify({"error": "No response from MCP server"}), 500
1085
+ response_data = loop.run_until_complete(process_request())
1086
+ return jsonify(response_data)
1096
1087
 
1097
1088
  except Exception as e:
1098
1089
  log.error(f"MCP server error: {str(e)}")
@@ -14,7 +14,16 @@
14
14
 
15
15
  """MCP (Model Context Protocol) integration for Sunholo."""
16
16
 
17
- from .mcp_manager import MCPClientManager
18
- from .vac_mcp_server import VACMCPServer
17
+ try:
18
+ from .mcp_manager import MCPClientManager
19
+ except ImportError as e:
20
+ print(f"Warning: MCPClientManager not available - {e}")
21
+ MCPClientManager = None
22
+
23
+ try:
24
+ from .vac_mcp_server import VACMCPServer
25
+ except ImportError as e:
26
+ print(f"Warning: VACMCPServer not available - {e}")
27
+ VACMCPServer = None
19
28
 
20
29
  __all__ = ['MCPClientManager', 'VACMCPServer']
@@ -4,11 +4,34 @@ This shows how to integrate MCP servers with your Flask/VACRoutes application.
4
4
  """
5
5
 
6
6
  from typing import Dict, Any, List, Optional
7
+ import asyncio
7
8
 
8
- # Official MCP imports
9
- from mcp import StdioServerParameters, ClientSession
10
- from mcp.client.stdio import stdio_client
11
- from mcp.types import Tool, Resource, TextContent, CallToolResult
9
+ # MCP SDK imports - try different import paths
10
+ try:
11
+ from mcp.client.stdio import StdioClientTransport
12
+ from mcp.client.session import ClientSession
13
+ except ImportError:
14
+ try:
15
+ # Alternative import paths
16
+ from mcp.client import StdioClientTransport, ClientSession
17
+ except ImportError:
18
+ try:
19
+ # Another alternative
20
+ from mcp import StdioClientTransport, ClientSession
21
+ except ImportError:
22
+ StdioClientTransport = None
23
+ ClientSession = None
24
+
25
+ try:
26
+ from mcp.types import Tool, Resource, TextContent, CallToolResult
27
+ except ImportError:
28
+ try:
29
+ from mcp import Tool, Resource, TextContent, CallToolResult
30
+ except ImportError:
31
+ Tool = None
32
+ Resource = None
33
+ TextContent = None
34
+ CallToolResult = None
12
35
 
13
36
 
14
37
  class MCPClientManager:
@@ -23,41 +46,42 @@ class MCPClientManager:
23
46
  if server_name in self.sessions:
24
47
  return self.sessions[server_name]
25
48
 
26
- # Create server parameters
27
- server_params = StdioServerParameters(
49
+ if not StdioClientTransport or not ClientSession:
50
+ raise ImportError("MCP client dependencies not available")
51
+
52
+ # Create transport and session
53
+ transport = StdioClientTransport(
28
54
  command=command,
29
55
  args=args or []
30
56
  )
57
+ session = ClientSession(transport)
58
+ await session.initialize()
31
59
 
32
- # Connect to the server
33
- async with stdio_client(server_params) as (read, write):
34
- # Create and initialize client session directly
35
- session = ClientSession(read, write)
36
- await session.initialize()
37
- self.sessions[server_name] = session
38
- self.server_configs[server_name] = {
39
- "command": command,
40
- "args": args
41
- }
42
- return session
60
+ self.sessions[server_name] = session
61
+ self.server_configs[server_name] = {
62
+ "command": command,
63
+ "args": args
64
+ }
65
+ return session
43
66
 
44
67
  async def list_tools(self, server_name: Optional[str] = None) -> List[Tool]:
45
68
  """List available tools from one or all connected servers."""
46
69
  if server_name:
47
70
  session = self.sessions.get(server_name)
48
71
  if session:
49
- return await session.list_tools()
72
+ result = await session.list_tools()
73
+ return result.tools
50
74
  return []
51
75
 
52
76
  # List from all servers
53
77
  all_tools = []
54
78
  for name, session in self.sessions.items():
55
- tools = await session.list_tools()
79
+ result = await session.list_tools()
56
80
  # Add server name to tool metadata
57
- for tool in tools:
81
+ for tool in result.tools:
58
82
  tool.metadata = tool.metadata or {}
59
83
  tool.metadata["server"] = name
60
- all_tools.extend(tools)
84
+ all_tools.extend(result.tools)
61
85
  return all_tools
62
86
 
63
87
  async def call_tool(self, server_name: str, tool_name: str, arguments: Dict[str, Any]) -> CallToolResult:
@@ -67,7 +91,13 @@ class MCPClientManager:
67
91
  raise ValueError(f"Not connected to server: {server_name}")
68
92
 
69
93
  # Call the tool
70
- result = await session.call_tool(tool_name, arguments)
94
+ try:
95
+ from mcp.types import CallToolRequest
96
+ request = CallToolRequest(name=tool_name, arguments=arguments)
97
+ result = await session.call_tool(request)
98
+ except ImportError:
99
+ # Try direct call if Request types not available
100
+ result = await session.call_tool(tool_name, arguments)
71
101
  return result
72
102
 
73
103
  async def list_resources(self, server_name: Optional[str] = None) -> List[Resource]:
@@ -75,17 +105,18 @@ class MCPClientManager:
75
105
  if server_name:
76
106
  session = self.sessions.get(server_name)
77
107
  if session:
78
- return await session.list_resources()
108
+ result = await session.list_resources()
109
+ return result.resources
79
110
  return []
80
111
 
81
112
  # List from all servers
82
113
  all_resources = []
83
114
  for name, session in self.sessions.items():
84
- resources = await session.list_resources()
85
- for resource in resources:
115
+ result = await session.list_resources()
116
+ for resource in result.resources:
86
117
  resource.metadata = resource.metadata or {}
87
118
  resource.metadata["server"] = name
88
- all_resources.extend(resources)
119
+ all_resources.extend(result.resources)
89
120
  return all_resources
90
121
 
91
122
  async def read_resource(self, server_name: str, uri: str) -> List[TextContent]:
@@ -94,5 +125,12 @@ class MCPClientManager:
94
125
  if not session:
95
126
  raise ValueError(f"Not connected to server: {server_name}")
96
127
 
97
- result = await session.read_resource(uri)
98
- return result.contents
128
+ try:
129
+ from mcp.types import ReadResourceRequest
130
+ request = ReadResourceRequest(uri=uri)
131
+ result = await session.read_resource(request)
132
+ except ImportError:
133
+ # Try direct call if Request types not available
134
+ result = await session.read_resource(uri)
135
+
136
+ return result.contents if hasattr(result, 'contents') else result
@@ -22,13 +22,8 @@ import json
22
22
  import asyncio
23
23
  from functools import partial
24
24
 
25
- try:
26
- from mcp.server import Server
27
- from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
28
- except ImportError:
29
- Server = None
30
- Tool = None
31
- TextContent = None
25
+ from mcp.server import Server
26
+ from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
32
27
 
33
28
  from ..custom_logging import log
34
29
  from ..streaming import start_streaming_chat_async
@@ -45,8 +40,7 @@ class VACMCPServer:
45
40
  stream_interpreter: The streaming interpreter function
46
41
  vac_interpreter: The static VAC interpreter function (optional)
47
42
  """
48
- if Server is None:
49
- raise ImportError("MCP server requires `pip install sunholo[anthropic]`")
43
+ # MCP server is always available with current SDK
50
44
 
51
45
  self.stream_interpreter = stream_interpreter
52
46
  self.vac_interpreter = vac_interpreter
@@ -172,18 +166,31 @@ class VACMCPServer:
172
166
  # Collect streaming responses
173
167
  full_response = ""
174
168
 
175
- async for chunk in start_streaming_chat_async(
176
- question=user_input,
177
- vector_name=vector_name,
178
- qna_func_async=self.stream_interpreter,
179
- chat_history=chat_history,
180
- wait_time=stream_wait_time,
181
- timeout=stream_timeout
182
- ):
183
- if isinstance(chunk, dict) and 'answer' in chunk:
184
- full_response = chunk['answer']
185
- elif isinstance(chunk, str):
186
- full_response += chunk
169
+ # Check if stream_interpreter is async
170
+ if asyncio.iscoroutinefunction(self.stream_interpreter):
171
+ async for chunk in start_streaming_chat_async(
172
+ question=user_input,
173
+ vector_name=vector_name,
174
+ qna_func_async=self.stream_interpreter,
175
+ chat_history=chat_history,
176
+ wait_time=stream_wait_time,
177
+ timeout=stream_timeout
178
+ ):
179
+ if isinstance(chunk, dict) and 'answer' in chunk:
180
+ full_response = chunk['answer']
181
+ elif isinstance(chunk, str):
182
+ full_response += chunk
183
+ else:
184
+ # Fall back to sync version for non-async interpreters
185
+ result = self.stream_interpreter(
186
+ question=user_input,
187
+ vector_name=vector_name,
188
+ chat_history=chat_history
189
+ )
190
+ if isinstance(result, dict):
191
+ full_response = result.get("answer", str(result))
192
+ else:
193
+ full_response = str(result)
187
194
 
188
195
  return [
189
196
  TextContent(
@@ -167,16 +167,16 @@ async def start_streaming_chat_async(question, vector_name, qna_func_async, chat
167
167
  content_buffer = ContentBuffer()
168
168
  chat_callback_handler = BufferStreamingStdOutCallbackHandlerAsync(content_buffer=content_buffer, tokens=".!?\n")
169
169
 
170
- result_queue = Queue()
171
- exception_queue = Queue()
172
- stop_event = Event()
170
+ result_queue = asyncio.Queue()
171
+ exception_queue = asyncio.Queue()
172
+ stop_event = asyncio.Event()
173
173
 
174
174
  async def start_chat():
175
175
  try:
176
176
  final_result = await qna_func_async(question, vector_name, chat_history, callback=chat_callback_handler, **kwargs)
177
- result_queue.put(final_result)
177
+ await result_queue.put(final_result)
178
178
  except Exception as e:
179
- exception_queue.put(e)
179
+ await exception_queue.put(e)
180
180
 
181
181
  # Run start_chat asynchronously
182
182
  chat_task = asyncio.create_task(start_chat())
@@ -222,10 +222,10 @@ async def start_streaming_chat_async(question, vector_name, qna_func_async, chat
222
222
  final_yield = ""
223
223
  else:
224
224
  log.info("Sending final full message plus sources...")
225
- if not result_queue.empty():
226
- final_result = result_queue.get()
225
+ try:
226
+ final_result = result_queue.get_nowait()
227
227
  final_yield = parse_output(final_result)
228
- else:
228
+ except asyncio.QueueEmpty:
229
229
  final_yield = ""
230
230
 
231
231
  # Match the non-async behavior - yield the parsed output directly, not as JSON
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sunholo
3
- Version: 0.143.3
3
+ Version: 0.143.9
4
4
  Summary: AI DevOps - a package to help deploy GenAI to the Cloud.
5
5
  Author-email: Holosun ApS <multivac@sunholo.com>
6
6
  License: Apache License, Version 2.0
@@ -190,5 +190,4 @@ tests/test_async_genai2.py
190
190
  tests/test_chat_history.py
191
191
  tests/test_config.py
192
192
  tests/test_genai2.py
193
- tests/test_unstructured.py
194
- tests/test_vac_routes_mcp.py
193
+ tests/test_unstructured.py