sunholo 0.144.3__tar.gz → 0.144.4__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.
- {sunholo-0.144.3/src/sunholo.egg-info → sunholo-0.144.4}/PKG-INFO +1 -1
- {sunholo-0.144.3 → sunholo-0.144.4}/pyproject.toml +1 -1
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/fastapi/vac_routes.py +58 -37
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/__init__.py +10 -1
- sunholo-0.144.4/src/sunholo/mcp/sse_utils.py +105 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/vac_mcp_server_fastmcp.py +2 -1
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/vac_tools.py +2 -5
- {sunholo-0.144.3 → sunholo-0.144.4/src/sunholo.egg-info}/PKG-INFO +1 -1
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo.egg-info/SOURCES.txt +1 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/LICENSE.txt +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/MANIFEST.in +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/README.md +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/setup.cfg +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/a2a/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/a2a/agent_card.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/a2a/task_manager.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/auth/refresh.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/database.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/download_gcs_text.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/file_handling.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/cli_fastmcp.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/extensible_mcp_server.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/mcp_manager.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/stdio_http_bridge.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/mcp/vac_mcp_server.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/ollama/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/ollama/ollama_images.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/config_class.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/proto_convert.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_async.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_async_genai2.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_chat_history.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_config.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_genai2.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_unstructured.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_vac_routes_fastapi.py +0 -0
- {sunholo-0.144.3 → sunholo-0.144.4}/tests/test_vac_routes_mcp.py +0 -0
@@ -534,44 +534,64 @@ class VACRoutesFastAPI:
|
|
534
534
|
async def app_lifespan(app: FastAPI):
|
535
535
|
yield
|
536
536
|
|
537
|
-
#
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
mcp_app =
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
if mcp_app:
|
537
|
+
# Import here to avoid circular imports
|
538
|
+
if VACMCPServer:
|
539
|
+
from fastmcp import FastMCP
|
540
|
+
|
541
|
+
# Create MCP server directly to get its lifespan
|
542
|
+
mcp_server = FastMCP("sunholo-vac-fastapi-server")
|
543
|
+
|
544
|
+
# Register built-in VAC tools directly
|
545
|
+
from sunholo.mcp.vac_tools import register_vac_tools
|
546
|
+
register_vac_tools(mcp_server, None)
|
547
|
+
|
548
|
+
# Get the MCP app with path="" so when mounted at /mcp it's accessible at /mcp
|
549
|
+
mcp_app = mcp_server.http_app(path="", stateless_http=True)
|
550
|
+
|
551
|
+
# Create combined lifespan
|
552
|
+
@asynccontextmanager
|
553
|
+
async def combined_lifespan(app: FastAPI):
|
554
|
+
async with app_lifespan(app):
|
556
555
|
async with mcp_app.lifespan(app):
|
557
556
|
yield
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
557
|
+
|
558
|
+
# Create the actual app with combined lifespan
|
559
|
+
app = FastAPI(
|
560
|
+
title=title,
|
561
|
+
lifespan=combined_lifespan
|
562
|
+
)
|
563
|
+
|
564
|
+
# Mount the MCP app at /mcp
|
565
|
+
app.mount("/mcp", mcp_app)
|
566
|
+
|
567
|
+
# Now create VAC routes WITHOUT MCP (since we already mounted it)
|
568
|
+
vac_routes = VACRoutesFastAPI(
|
569
|
+
app,
|
570
|
+
stream_interpreter=stream_interpreter,
|
571
|
+
vac_interpreter=vac_interpreter,
|
572
|
+
enable_mcp_server=False, # Don't enable again since we manually mounted
|
573
|
+
**kwargs
|
574
|
+
)
|
575
|
+
|
576
|
+
# Store reference to MCP server for tool registration
|
577
|
+
vac_routes.vac_mcp_server = type('MockMCPServer', (), {
|
578
|
+
'add_tool': lambda self, func, name=None, desc=None: mcp_server.tool(func) if name is None else mcp_server.tool(name=name)(func),
|
579
|
+
'server': mcp_server
|
580
|
+
})()
|
581
|
+
else:
|
582
|
+
# No MCP support available
|
583
|
+
app = FastAPI(
|
584
|
+
title=title,
|
585
|
+
lifespan=app_lifespan
|
586
|
+
)
|
587
|
+
|
588
|
+
vac_routes = VACRoutesFastAPI(
|
589
|
+
app,
|
590
|
+
stream_interpreter=stream_interpreter,
|
591
|
+
vac_interpreter=vac_interpreter,
|
592
|
+
enable_mcp_server=False,
|
593
|
+
**kwargs
|
594
|
+
)
|
575
595
|
|
576
596
|
return app, vac_routes
|
577
597
|
|
@@ -682,7 +702,8 @@ class VACRoutesFastAPI:
|
|
682
702
|
# so we can't easily check if it's configured. The error will be
|
683
703
|
# caught below if lifespan is missing.
|
684
704
|
|
685
|
-
|
705
|
+
# Mount at root - the MCP app already has /mcp path configured
|
706
|
+
self.app.mount("", mcp_app)
|
686
707
|
log.info("✅ MCP server mounted at /mcp endpoint")
|
687
708
|
|
688
709
|
except RuntimeError as e:
|
@@ -26,4 +26,13 @@ except ImportError as e:
|
|
26
26
|
print(f"Warning: VACMCPServer not available - {e}")
|
27
27
|
VACMCPServer = None
|
28
28
|
|
29
|
-
|
29
|
+
# SSE utilities are always available
|
30
|
+
from .sse_utils import parse_sse_response, is_sse_response, extract_sse_data
|
31
|
+
|
32
|
+
__all__ = [
|
33
|
+
'MCPClientManager',
|
34
|
+
'VACMCPServer',
|
35
|
+
'parse_sse_response',
|
36
|
+
'is_sse_response',
|
37
|
+
'extract_sse_data'
|
38
|
+
]
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# Copyright [2024] [Holosun ApS]
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""
|
16
|
+
Utilities for parsing Server-Sent Events (SSE) responses from MCP servers.
|
17
|
+
"""
|
18
|
+
|
19
|
+
import json
|
20
|
+
from typing import Any, Dict, Optional
|
21
|
+
|
22
|
+
|
23
|
+
def parse_sse_response(text: str) -> Dict[str, Any]:
|
24
|
+
"""
|
25
|
+
Parse SSE-formatted response from MCP server.
|
26
|
+
|
27
|
+
FastMCP returns responses in SSE format when using HTTP transport,
|
28
|
+
even with stateless_http=True. This function extracts the JSON data
|
29
|
+
from the SSE format.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
text: Raw response text from MCP server
|
33
|
+
|
34
|
+
Returns:
|
35
|
+
Parsed JSON data from the SSE response
|
36
|
+
|
37
|
+
Raises:
|
38
|
+
ValueError: If the response cannot be parsed
|
39
|
+
|
40
|
+
Example:
|
41
|
+
>>> response_text = 'event: message\\ndata: {"jsonrpc": "2.0", "id": 1, "result": {...}}'
|
42
|
+
>>> data = parse_sse_response(response_text)
|
43
|
+
>>> print(data['result'])
|
44
|
+
"""
|
45
|
+
# Check if it's SSE format
|
46
|
+
if text.startswith('event:') or text.startswith('data:'):
|
47
|
+
# Parse SSE format - extract JSON from data: line
|
48
|
+
lines = text.split('\n')
|
49
|
+
|
50
|
+
# Find the data line
|
51
|
+
data_line = None
|
52
|
+
for line in lines:
|
53
|
+
if line.startswith('data:'):
|
54
|
+
data_line = line
|
55
|
+
break
|
56
|
+
|
57
|
+
if data_line:
|
58
|
+
# Remove 'data:' prefix and parse JSON
|
59
|
+
json_str = data_line[5:].strip()
|
60
|
+
try:
|
61
|
+
return json.loads(json_str)
|
62
|
+
except json.JSONDecodeError as e:
|
63
|
+
raise ValueError(f"Failed to parse JSON from SSE data: {e}")
|
64
|
+
else:
|
65
|
+
raise ValueError("No data line found in SSE response")
|
66
|
+
else:
|
67
|
+
# Try parsing as regular JSON
|
68
|
+
try:
|
69
|
+
return json.loads(text)
|
70
|
+
except json.JSONDecodeError as e:
|
71
|
+
raise ValueError(f"Response is not valid JSON or SSE format: {e}")
|
72
|
+
|
73
|
+
|
74
|
+
def is_sse_response(text: str) -> bool:
|
75
|
+
"""
|
76
|
+
Check if a response is in SSE format.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
text: Response text to check
|
80
|
+
|
81
|
+
Returns:
|
82
|
+
True if the response appears to be SSE format
|
83
|
+
"""
|
84
|
+
return text.startswith('event:') or text.startswith('data:')
|
85
|
+
|
86
|
+
|
87
|
+
def extract_sse_data(text: str) -> Optional[str]:
|
88
|
+
"""
|
89
|
+
Extract the data portion from an SSE response.
|
90
|
+
|
91
|
+
Args:
|
92
|
+
text: SSE-formatted response text
|
93
|
+
|
94
|
+
Returns:
|
95
|
+
The extracted data string, or None if not found
|
96
|
+
"""
|
97
|
+
if not is_sse_response(text):
|
98
|
+
return None
|
99
|
+
|
100
|
+
lines = text.split('\n')
|
101
|
+
for line in lines:
|
102
|
+
if line.startswith('data:'):
|
103
|
+
return line[5:].strip()
|
104
|
+
|
105
|
+
return None
|
@@ -73,7 +73,8 @@ class VACMCPServer:
|
|
73
73
|
|
74
74
|
def get_http_app(self):
|
75
75
|
"""Get the HTTP app for mounting in FastAPI."""
|
76
|
-
|
76
|
+
# Following FastMCP docs: when mounted at root "", path="/mcp" gives us /mcp endpoint
|
77
|
+
return self.server.http_app(path="/mcp")
|
77
78
|
|
78
79
|
def add_tool(self, func: Callable, name: str = None, description: str = None):
|
79
80
|
"""
|
@@ -54,12 +54,9 @@ def get_vac_config(vector_name: str = None) -> 'ConfigManager':
|
|
54
54
|
|
55
55
|
default_vac = os.getenv("DEFAULT_VAC_NAME", "demo")
|
56
56
|
vac_name = vector_name or default_vac
|
57
|
-
vac_config_folder = os.getenv("VAC_CONFIG_FOLDER")
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
else:
|
62
|
-
return ConfigManager(vac_name)
|
58
|
+
# ConfigManager uses VAC_CONFIG_FOLDER env var automatically
|
59
|
+
return ConfigManager(vac_name)
|
63
60
|
|
64
61
|
|
65
62
|
async def call_vac_async(question: str, vector_name: str, chat_history: List[Dict[str, str]] = None) -> str:
|
@@ -130,6 +130,7 @@ src/sunholo/mcp/cli.py
|
|
130
130
|
src/sunholo/mcp/cli_fastmcp.py
|
131
131
|
src/sunholo/mcp/extensible_mcp_server.py
|
132
132
|
src/sunholo/mcp/mcp_manager.py
|
133
|
+
src/sunholo/mcp/sse_utils.py
|
133
134
|
src/sunholo/mcp/stdio_http_bridge.py
|
134
135
|
src/sunholo/mcp/vac_mcp_server.py
|
135
136
|
src/sunholo/mcp/vac_mcp_server_fastmcp.py
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|