sunholo 0.144.7__tar.gz → 0.144.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.144.7/src/sunholo.egg-info → sunholo-0.144.9}/PKG-INFO +1 -1
- {sunholo-0.144.7 → sunholo-0.144.9}/pyproject.toml +1 -1
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/fastapi/vac_routes.py +124 -15
- {sunholo-0.144.7 → sunholo-0.144.9/src/sunholo.egg-info}/PKG-INFO +1 -1
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_vac_routes_mcp.py +58 -3
- {sunholo-0.144.7 → sunholo-0.144.9}/LICENSE.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/MANIFEST.in +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/README.md +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/setup.cfg +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/a2a/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/a2a/agent_card.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/a2a/task_manager.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/a2a/vac_a2a_agent.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/chat_history.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/dispatch_to_qa.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/fastapi/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/fastapi/base.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/fastapi/qna_routes.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/flask/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/flask/base.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/flask/vac_routes.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/langserve.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/pubsub.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/route.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/special_commands.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/agents/swagger.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/archive/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/archive/archive.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/auth/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/auth/gcloud.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/auth/refresh.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/auth/run.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/azure/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/azure/auth.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/azure/blobs.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/azure/event_grid.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/bots/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/bots/discord.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/bots/github_webhook.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/bots/webapp.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/azure.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/doc_handling.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/encode_metadata.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/images.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/loaders.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/message_data.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/pdfs.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/process_chunker_data.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/publish.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/pubsub.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/chunker/splitter.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/chat_vac.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/cli.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/cli_init.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/configs.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/deploy.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/embedder.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/merge_texts.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/run_proxy.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/sun_rich.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/swagger.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/cli/vertex.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/components/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/components/llm.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/components/retriever.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/components/vectorstore.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/custom_logging.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/alloydb.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/alloydb_client.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/database.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/lancedb.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/create_function.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/create_function_time.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/create_table.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/delete_source_row.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/return_sources.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/sql/sb/setup.sql +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/static_dbs.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/database/uuid.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/chunker_handler.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/cli.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/create_new.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/discovery_engine_client.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/discovery_engine/get_ai_search_chunks.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/embedder/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/embedder/embed_chunk.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/embedder/embed_metadata.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/excel/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/excel/plugin.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/add_file.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/download_folder.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/download_gcs_text.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/download_url.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/extract_and_sign.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/gcs/metadata.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/file_handling.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/genaiv2.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/images.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/init.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/process_funcs_cls.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/genai/safety.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/invoke/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/invoke/async_class.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/invoke/direct_vac_func.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/invoke/invoke_vac_utils.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/langchain_types.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/langfuse/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/langfuse/callback.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/langfuse/evals.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/langfuse/prompts.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/llamaindex/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/llamaindex/get_files.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/llamaindex/import_files.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/llamaindex/llamaindex_class.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/llamaindex/user_history.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/lookup/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/lookup/model_lookup.yaml +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/cli.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/cli_fastmcp.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/extensible_mcp_server.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/mcp_manager.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/sse_utils.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/stdio_http_bridge.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/vac_mcp_server.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/vac_mcp_server_fastmcp.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/mcp/vac_tools.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/ollama/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/ollama/ollama_images.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/pubsub/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/pubsub/process_pubsub.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/pubsub/pubsub_manager.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/qna/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/qna/parsers.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/qna/retry.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/senses/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/senses/stream_voice.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/streaming/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/streaming/content_buffer.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/streaming/langserve.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/streaming/stream_lookup.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/streaming/streaming.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/summarise/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/summarise/summarise.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/agent_service.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/app.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/my_log.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/tools/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/tools/your_agent.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/agent/vac_service.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/project/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/project/app.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/project/my_log.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/project/vac_service.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/system_services/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/system_services/app.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/templates/system_services/my_log.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/terraform/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/terraform/tfvars_editor.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/tools/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/tools/web_browser.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/api_key.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/big_context.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/config.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/config_class.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/config_schema.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/gcp.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/gcp_project.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/mime.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/parsers.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/proto_convert.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/timedelta.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/user_ids.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/utils/version.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/__init__.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/extensions_call.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/extensions_class.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/genai_functions.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/init.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/memory_tools.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/safety.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo/vertex/type_dict_to_json.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo.egg-info/SOURCES.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo.egg-info/dependency_links.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo.egg-info/entry_points.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo.egg-info/requires.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/src/sunholo.egg-info/top_level.txt +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_async.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_async_genai2.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_chat_history.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_config.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_genai2.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_unstructured.py +0 -0
- {sunholo-0.144.7 → sunholo-0.144.9}/tests/test_vac_routes_fastapi.py +0 -0
@@ -353,7 +353,6 @@ class VACRoutesFastAPI:
|
|
353
353
|
additional_routes: Optional[List[Dict]] = None,
|
354
354
|
mcp_servers: Optional[List[Dict[str, Any]]] = None,
|
355
355
|
add_langfuse_eval: bool = True,
|
356
|
-
enable_mcp_server: bool = False,
|
357
356
|
enable_a2a_agent: bool = False,
|
358
357
|
a2a_vac_names: Optional[List[str]] = None
|
359
358
|
):
|
@@ -371,9 +370,6 @@ class VACRoutesFastAPI:
|
|
371
370
|
mcp_servers: List of external MCP server configurations to connect to:
|
372
371
|
[{"name": "server-name", "command": "python", "args": ["server.py"]}]
|
373
372
|
add_langfuse_eval: Whether to enable Langfuse evaluation and tracing
|
374
|
-
enable_mcp_server: Whether to enable the MCP server at /mcp endpoint for
|
375
|
-
Claude Desktop/Code integration. When True, automatically
|
376
|
-
includes built-in VAC tools and supports custom tool registration.
|
377
373
|
enable_a2a_agent: Whether to enable A2A (Agent-to-Agent) protocol endpoints
|
378
374
|
a2a_vac_names: List of VAC names available for A2A agent interactions
|
379
375
|
|
@@ -398,7 +394,7 @@ class VACRoutesFastAPI:
|
|
398
394
|
|
399
395
|
## MCP Server Integration
|
400
396
|
|
401
|
-
When
|
397
|
+
When VACMCPServer is available, the following happens automatically:
|
402
398
|
1. MCP server is mounted at /mcp endpoint
|
403
399
|
2. Built-in VAC tools are automatically registered:
|
404
400
|
- vac_stream, vac_query, list_available_vacs, get_vac_info
|
@@ -452,13 +448,13 @@ class VACRoutesFastAPI:
|
|
452
448
|
self.mcp_client_manager = MCPClientManager() if MCPClientManager else None
|
453
449
|
self._mcp_initialized = False
|
454
450
|
|
455
|
-
# MCP server initialization
|
456
|
-
self.enable_mcp_server = enable_mcp_server
|
451
|
+
# MCP server initialization - automatically enabled if VACMCPServer is available
|
457
452
|
self.vac_mcp_server = None
|
458
453
|
self._custom_mcp_tools = []
|
459
454
|
self._custom_mcp_resources = []
|
460
455
|
|
461
|
-
if
|
456
|
+
# Enable MCP server if VACMCPServer is available
|
457
|
+
if VACMCPServer:
|
462
458
|
self.vac_mcp_server = VACMCPServer(
|
463
459
|
server_name="sunholo-vac-fastapi-server",
|
464
460
|
include_vac_tools=True
|
@@ -497,7 +493,7 @@ class VACRoutesFastAPI:
|
|
497
493
|
stream_interpreter: Streaming interpreter function
|
498
494
|
vac_interpreter: Non-streaming interpreter function
|
499
495
|
app_lifespan: Optional app lifespan context manager
|
500
|
-
**kwargs: Additional arguments passed to VACRoutesFastAPI
|
496
|
+
**kwargs: Additional arguments passed to VACRoutesFastAPI
|
501
497
|
|
502
498
|
Returns:
|
503
499
|
Tuple of (FastAPI app, VACRoutesFastAPI instance)
|
@@ -569,7 +565,6 @@ class VACRoutesFastAPI:
|
|
569
565
|
app,
|
570
566
|
stream_interpreter=stream_interpreter,
|
571
567
|
vac_interpreter=vac_interpreter,
|
572
|
-
enable_mcp_server=False, # Don't enable again since we manually mounted
|
573
568
|
**kwargs
|
574
569
|
)
|
575
570
|
|
@@ -589,7 +584,6 @@ class VACRoutesFastAPI:
|
|
589
584
|
app,
|
590
585
|
stream_interpreter=stream_interpreter,
|
591
586
|
vac_interpreter=vac_interpreter,
|
592
|
-
enable_mcp_server=False,
|
593
587
|
**kwargs
|
594
588
|
)
|
595
589
|
|
@@ -694,7 +688,7 @@ class VACRoutesFastAPI:
|
|
694
688
|
self.app.post("/mcp/resources/read")(self.handle_mcp_read_resource)
|
695
689
|
|
696
690
|
# MCP server endpoint - mount the FastMCP app
|
697
|
-
if self.
|
691
|
+
if self.vac_mcp_server:
|
698
692
|
try:
|
699
693
|
mcp_app = self.vac_mcp_server.get_http_app()
|
700
694
|
|
@@ -713,8 +707,7 @@ class VACRoutesFastAPI:
|
|
713
707
|
"The FastAPI app must be created with the MCP lifespan.\n\n"
|
714
708
|
"Quick fix: Use the helper method:\n"
|
715
709
|
" app, vac_routes = VACRoutesFastAPI.create_app_with_mcp(\n"
|
716
|
-
" stream_interpreter=your_interpreter
|
717
|
-
" enable_mcp_server=True\n"
|
710
|
+
" stream_interpreter=your_interpreter\n"
|
718
711
|
" )\n\n"
|
719
712
|
"Or manually configure the lifespan - see documentation for details."
|
720
713
|
)
|
@@ -727,6 +720,10 @@ class VACRoutesFastAPI:
|
|
727
720
|
log.error(f"Failed to mount MCP server: {e}")
|
728
721
|
raise RuntimeError(f"MCP server initialization failed: {e}") from e
|
729
722
|
|
723
|
+
# MCP debug endpoint - add if we have a MCP server instance
|
724
|
+
if self.vac_mcp_server:
|
725
|
+
self.app.get("/debug/mcp")(self.handle_mcp_debug)
|
726
|
+
|
730
727
|
# A2A agent endpoints
|
731
728
|
if self.enable_a2a_agent:
|
732
729
|
self.app.get("/.well-known/agent.json")(self.handle_a2a_agent_card)
|
@@ -1516,4 +1513,116 @@ class VACRoutesFastAPI:
|
|
1516
1513
|
"""
|
1517
1514
|
if self.vac_mcp_server:
|
1518
1515
|
return self.vac_mcp_server.list_resources()
|
1519
|
-
return []
|
1516
|
+
return []
|
1517
|
+
|
1518
|
+
async def handle_mcp_debug(self):
|
1519
|
+
"""
|
1520
|
+
Debug endpoint to check MCP server status and list tools.
|
1521
|
+
|
1522
|
+
Returns:
|
1523
|
+
JSON with MCP server status, tools list, and diagnostic information
|
1524
|
+
"""
|
1525
|
+
import json
|
1526
|
+
|
1527
|
+
has_mcp = self.vac_mcp_server is not None
|
1528
|
+
mcp_tools = []
|
1529
|
+
mcp_response = None
|
1530
|
+
|
1531
|
+
# Try to call the MCP endpoint the same way clients do
|
1532
|
+
if has_mcp:
|
1533
|
+
try:
|
1534
|
+
# Make internal request to MCP server to get tools
|
1535
|
+
import httpx
|
1536
|
+
|
1537
|
+
# Get the base URL from the current request
|
1538
|
+
from fastapi import Request
|
1539
|
+
from starlette.requests import Request as StarletteRequest
|
1540
|
+
|
1541
|
+
# Try common ports since we don't have request context
|
1542
|
+
ports_to_try = [8000, 8001, 8080, 3000, 1956]
|
1543
|
+
successful_response = None
|
1544
|
+
|
1545
|
+
for port in ports_to_try:
|
1546
|
+
try:
|
1547
|
+
base_url = f"http://localhost:{port}"
|
1548
|
+
async with httpx.AsyncClient(timeout=2.0) as client:
|
1549
|
+
response = await client.post(
|
1550
|
+
f"{base_url}/mcp/mcp",
|
1551
|
+
json={
|
1552
|
+
"jsonrpc": "2.0",
|
1553
|
+
"id": 1,
|
1554
|
+
"method": "tools/list"
|
1555
|
+
},
|
1556
|
+
headers={
|
1557
|
+
"Content-Type": "application/json",
|
1558
|
+
"Accept": "application/json, text/event-stream"
|
1559
|
+
}
|
1560
|
+
)
|
1561
|
+
|
1562
|
+
if response.status_code == 200:
|
1563
|
+
successful_response = response
|
1564
|
+
break # Found working port
|
1565
|
+
except (httpx.ConnectError, httpx.TimeoutException):
|
1566
|
+
continue # Try next port
|
1567
|
+
except Exception:
|
1568
|
+
continue # Try next port
|
1569
|
+
|
1570
|
+
if successful_response:
|
1571
|
+
# Parse SSE (Server-Sent Events) response
|
1572
|
+
text = successful_response.text
|
1573
|
+
for line in text.split('\n'):
|
1574
|
+
if line.startswith('data: '):
|
1575
|
+
# Extract JSON from the data line
|
1576
|
+
json_str = line[6:] # Remove 'data: ' prefix
|
1577
|
+
try:
|
1578
|
+
mcp_response = json.loads(json_str)
|
1579
|
+
if "result" in mcp_response and "tools" in mcp_response["result"]:
|
1580
|
+
for tool in mcp_response["result"]["tools"]:
|
1581
|
+
mcp_tools.append({
|
1582
|
+
"name": tool.get("name"),
|
1583
|
+
"description": tool.get("description", "No description")[:100] + "..." if len(tool.get("description", "")) > 100 else tool.get("description", "No description")
|
1584
|
+
})
|
1585
|
+
break # We found the data we need
|
1586
|
+
except json.JSONDecodeError:
|
1587
|
+
continue
|
1588
|
+
else:
|
1589
|
+
mcp_response = {
|
1590
|
+
"error": "Could not connect to MCP server on any common port",
|
1591
|
+
"ports_tried": ports_to_try
|
1592
|
+
}
|
1593
|
+
|
1594
|
+
except Exception as e:
|
1595
|
+
log.error(f"Error calling MCP endpoint in debug: {e}")
|
1596
|
+
mcp_response = {"error": str(e)}
|
1597
|
+
|
1598
|
+
# Fallback: try to get tools from internal MCP server state
|
1599
|
+
try:
|
1600
|
+
# Get tools from the FastMCP server directly
|
1601
|
+
if hasattr(self.vac_mcp_server, 'server'):
|
1602
|
+
mcp_server = self.vac_mcp_server.server
|
1603
|
+
if hasattr(mcp_server, '_tools'):
|
1604
|
+
for tool_name, tool_func in mcp_server._tools.items():
|
1605
|
+
mcp_tools.append({
|
1606
|
+
"name": tool_name,
|
1607
|
+
"description": getattr(tool_func, '__doc__', 'No description') or 'No description'
|
1608
|
+
})
|
1609
|
+
except Exception as inner_e:
|
1610
|
+
log.error(f"Error getting MCP tools from internal state: {inner_e}")
|
1611
|
+
|
1612
|
+
# Check for pending tools that haven't been registered yet
|
1613
|
+
pending_tools = len(self._custom_mcp_tools) if hasattr(self, '_custom_mcp_tools') else 0
|
1614
|
+
|
1615
|
+
return {
|
1616
|
+
"mcp_enabled": has_mcp,
|
1617
|
+
"has_mcp_server": has_mcp,
|
1618
|
+
"mcp_tools_count": len(mcp_tools),
|
1619
|
+
"mcp_tools": [tool["name"] for tool in mcp_tools] if mcp_tools else [],
|
1620
|
+
"tool_details": mcp_tools,
|
1621
|
+
"pending_tools": pending_tools,
|
1622
|
+
"message": f"MCP server is available at /mcp endpoint with {len(mcp_tools)} tools" if has_mcp and mcp_tools else "MCP server is available at /mcp endpoint" if has_mcp else "MCP server not configured",
|
1623
|
+
"debug_info": {
|
1624
|
+
"mcp_server_type": type(self.vac_mcp_server).__name__ if self.vac_mcp_server else None,
|
1625
|
+
"has_custom_tools": len(self._custom_mcp_tools) > 0 if hasattr(self, '_custom_mcp_tools') else False,
|
1626
|
+
"has_custom_resources": len(self._custom_mcp_resources) > 0 if hasattr(self, '_custom_mcp_resources') else False
|
1627
|
+
}
|
1628
|
+
}
|
@@ -214,7 +214,6 @@ def mcp_server_app():
|
|
214
214
|
app,
|
215
215
|
stream_interpreter=mock_async_stream_interpreter,
|
216
216
|
vac_interpreter=mock_async_vac_interpreter,
|
217
|
-
enable_mcp_server=False, # Disable initially
|
218
217
|
add_langfuse_eval=False
|
219
218
|
)
|
220
219
|
|
@@ -253,7 +252,6 @@ def mcp_client_app():
|
|
253
252
|
stream_interpreter=mock_async_stream_interpreter,
|
254
253
|
vac_interpreter=mock_async_vac_interpreter,
|
255
254
|
mcp_servers=mcp_servers,
|
256
|
-
enable_mcp_server=False,
|
257
255
|
add_langfuse_eval=False
|
258
256
|
)
|
259
257
|
# Replace with mock MCP client manager
|
@@ -320,7 +318,6 @@ class TestMCPServer:
|
|
320
318
|
vac_routes = VACRoutesFastAPI(
|
321
319
|
app,
|
322
320
|
stream_interpreter=mock_async_stream_interpreter,
|
323
|
-
enable_mcp_server=False,
|
324
321
|
add_langfuse_eval=False
|
325
322
|
)
|
326
323
|
client = TestClient(app)
|
@@ -331,6 +328,64 @@ class TestMCPServer:
|
|
331
328
|
|
332
329
|
|
333
330
|
|
331
|
+
class TestMCPDebugEndpoint:
|
332
|
+
"""Test MCP debug endpoint functionality."""
|
333
|
+
|
334
|
+
def test_debug_endpoint_with_mcp_server(self):
|
335
|
+
"""Test /debug/mcp endpoint when MCP server is enabled."""
|
336
|
+
app, vac_routes = VACRoutesFastAPI.create_app_with_mcp(
|
337
|
+
title="Test App",
|
338
|
+
stream_interpreter=mock_async_stream_interpreter
|
339
|
+
)
|
340
|
+
|
341
|
+
# Add a mock tool to test
|
342
|
+
@vac_routes.add_mcp_tool
|
343
|
+
async def test_tool(input: str) -> str:
|
344
|
+
"""Test tool for MCP."""
|
345
|
+
return f"Test: {input}"
|
346
|
+
|
347
|
+
client = TestClient(app)
|
348
|
+
response = client.get("/debug/mcp")
|
349
|
+
|
350
|
+
assert response.status_code == 200
|
351
|
+
data = response.json()
|
352
|
+
|
353
|
+
# Check basic structure
|
354
|
+
assert "mcp_enabled" in data
|
355
|
+
assert "has_mcp_server" in data
|
356
|
+
assert "mcp_tools_count" in data
|
357
|
+
assert "mcp_tools" in data
|
358
|
+
|
359
|
+
# Check values
|
360
|
+
assert data["mcp_enabled"] is True
|
361
|
+
assert data["has_mcp_server"] is True
|
362
|
+
assert data["mcp_tools_count"] >= 5 # Built-in tools + test_tool
|
363
|
+
|
364
|
+
# Check that test_tool is in the list
|
365
|
+
tool_names = [tool["name"] for tool in data["mcp_tools"]]
|
366
|
+
assert "test_tool" in tool_names
|
367
|
+
|
368
|
+
# Check built-in tools are present
|
369
|
+
assert "vac_stream" in tool_names
|
370
|
+
assert "vac_query" in tool_names
|
371
|
+
assert "list_available_vacs" in tool_names
|
372
|
+
assert "get_vac_info" in tool_names
|
373
|
+
|
374
|
+
def test_debug_endpoint_without_mcp_server(self):
|
375
|
+
"""Test /debug/mcp endpoint when MCP server is not present."""
|
376
|
+
app = FastAPI()
|
377
|
+
vac_routes = VACRoutesFastAPI(
|
378
|
+
app,
|
379
|
+
stream_interpreter=mock_async_stream_interpreter,
|
380
|
+
add_langfuse_eval=False
|
381
|
+
)
|
382
|
+
|
383
|
+
# Should not have debug endpoint if no MCP server
|
384
|
+
client = TestClient(app)
|
385
|
+
response = client.get("/debug/mcp")
|
386
|
+
assert response.status_code == 404
|
387
|
+
|
388
|
+
|
334
389
|
class TestMCPErrorHandling:
|
335
390
|
"""Test MCP error handling."""
|
336
391
|
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|