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.
- {sunholo-0.143.3/src/sunholo.egg-info → sunholo-0.143.9}/PKG-INFO +1 -1
- {sunholo-0.143.3 → sunholo-0.143.9}/pyproject.toml +1 -1
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/__init__.py +4 -1
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/vac_routes.py +54 -63
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/__init__.py +11 -2
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/mcp_manager.py +66 -28
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/vac_mcp_server.py +28 -21
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/streaming.py +8 -8
- {sunholo-0.143.3 → sunholo-0.143.9/src/sunholo.egg-info}/PKG-INFO +1 -1
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/SOURCES.txt +1 -2
- sunholo-0.143.3/tests/test_vac_routes_mcp.py +0 -339
- {sunholo-0.143.3 → sunholo-0.143.9}/LICENSE.txt +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/MANIFEST.in +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/README.md +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/setup.cfg +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/agent_card.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/task_manager.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/refresh.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/database.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_gcs_text.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/file_handling.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/ollama/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/ollama/ollama_images.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config_class.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/proto_convert.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_async.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_async_genai2.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_chat_history.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_config.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_genai2.py +0 -0
- {sunholo-0.143.3 → sunholo-0.143.9}/tests/test_unstructured.py +0 -0
@@ -15,7 +15,10 @@ from . import invoke
|
|
15
15
|
from . import langfuse
|
16
16
|
from . import llamaindex
|
17
17
|
from . import lookup
|
18
|
-
|
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
|
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
|
-
|
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
|
-
#
|
1028
|
-
|
1029
|
-
|
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
|
-
|
1032
|
-
|
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
|
-
#
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
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
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
|
1076
|
-
|
1077
|
-
|
1078
|
-
|
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
|
-
|
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
|
-
|
18
|
-
from .
|
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
|
-
#
|
9
|
-
|
10
|
-
from mcp.client.stdio import
|
11
|
-
from mcp.
|
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
|
-
|
27
|
-
|
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
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
98
|
-
|
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
|
-
|
26
|
-
|
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
|
-
|
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
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
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
|
-
|
226
|
-
final_result = result_queue.
|
225
|
+
try:
|
226
|
+
final_result = result_queue.get_nowait()
|
227
227
|
final_yield = parse_output(final_result)
|
228
|
-
|
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
|