fast-agent-mcp 0.2.23__tar.gz → 0.2.25__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.
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/.gitignore +0 -2
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/PKG-INFO +7 -3
- fast_agent_mcp-0.2.25/examples/azure-openai/fastagent.config.yaml +54 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/pyproject.toml +13 -3
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/commands/check_config.py +61 -28
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/config.py +17 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/context.py +2 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/event_progress.py +1 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/model_factory.py +2 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/provider_types.py +1 -0
- fast_agent_mcp-0.2.25/src/mcp_agent/llm/providers/augmented_llm_azure.py +137 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_openai.py +8 -7
- fast_agent_mcp-0.2.25/src/mcp_agent/mcp/common.py +16 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/mcp_agent_client_session.py +41 -11
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/mcp_aggregator.py +139 -14
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/ui/console_display.py +28 -1
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/LICENSE +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/README.md +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/data-analysis/analysis-campaign.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/data-analysis/analysis.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/state-transfer/agent_one.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/state-transfer/agent_two.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/vision-examples/example1.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/vision-examples/example2.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/vision-examples/example3.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/mcp/vision-examples/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/otel/agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/otel/agent2.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/otel/docker-compose.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/otel/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/researcher/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/researcher/researcher-eval.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/researcher/researcher-imp.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/researcher/researcher.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/README.md +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/docker-compose.yml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/image_demo.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/mcp_server/mcp_server.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/tensorzero/simple_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/chaining.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/evaluator.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/graded_report.md +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/human_input.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/orchestrator.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/parallel.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/router.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/short_story.md +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/examples/workflows/short_story.txt +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/base_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/chain_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/evaluator_optimizer.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/orchestrator_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/orchestrator_models.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/orchestrator_prompts.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/parallel_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/agents/workflow/router_agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/app.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/__main__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/commands/go.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/commands/quickstart.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/commands/setup.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/commands/url_parser.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/main.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/cli/terminal.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/console.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/context_dependent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/agent_app.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/agent_types.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/direct_decorators.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/direct_factory.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/enhanced_prompt.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/error_handling.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/exceptions.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/fastagent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/interactive_prompt.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/mcp_content.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/prompt.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/request_params.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/core/validation.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/executor/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/executor/executor.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/executor/task_registry.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/executor/workflow_signal.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/human_input/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/human_input/handler.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/human_input/types.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/augmented_llm.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/augmented_llm_passthrough.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/augmented_llm_playback.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/memory.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/prompt_utils.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/provider_key_manager.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/anthropic_utils.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_deepseek.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_generic.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_google.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_openrouter.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_tensorzero.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/multipart_converter_anthropic.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/multipart_converter_openai.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/multipart_converter_tensorzero.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/openai_multipart.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/openai_utils.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/sampling_converter_openai.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/sampling_converter.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/sampling_format_converter.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/events.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/json_serializer.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/listeners.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/logger.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/rich_progress.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/logging/transport.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/gen_client.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/helpers/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/helpers/content_helpers.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/interfaces.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/logger_textio.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/mcp_connection_manager.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/mime_utils.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompt_message_multipart.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompt_render.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompt_serialization.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/__main__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/prompt_constants.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/prompt_helpers.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/prompt_load.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/prompt_server.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/prompts/prompt_template.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/resource_utils.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/sampling.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp_server/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp_server/agent_server.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp_server_registry.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/progress_display.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/data-analysis/analysis.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/in_dev/agent_build.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/in_dev/css-LICENSE.txt +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/in_dev/slides.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/history_transfer.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/job.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/prompt_category.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/prompt_sizing.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/simple.txt +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/sizer.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/internal/social.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_one.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/mcp/state-transfer/agent_two.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/__init__.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/agent.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/delimited_prompt.txt +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/image_server.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/prompt1.txt +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/prompting/work_with_image.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/researcher/researcher-eval.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/researcher/researcher-imp.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/researcher/researcher.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/chaining.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/evaluator.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/human_input.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/orchestrator.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/parallel.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/router.py +0 -0
- {fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/resources/examples/workflows/short_story.txt +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: fast-agent-mcp
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.25
|
4
4
|
Summary: Define, Prompt and Test MCP enabled Agents and Workflows
|
5
5
|
Author-email: Shaun Smith <fastagent@llmindset.co.uk>
|
6
6
|
License: Apache License
|
@@ -212,13 +212,15 @@ Requires-Python: >=3.10
|
|
212
212
|
Requires-Dist: a2a-types>=0.1.0
|
213
213
|
Requires-Dist: aiohttp>=3.11.13
|
214
214
|
Requires-Dist: anthropic>=0.49.0
|
215
|
+
Requires-Dist: azure-identity>=1.14.0
|
215
216
|
Requires-Dist: fastapi>=0.115.6
|
216
217
|
Requires-Dist: mcp>=1.8.0
|
217
218
|
Requires-Dist: openai>=1.63.2
|
218
219
|
Requires-Dist: opentelemetry-distro>=0.50b0
|
219
220
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.29.0
|
220
|
-
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.39.3
|
221
|
-
Requires-Dist: opentelemetry-instrumentation-
|
221
|
+
Requires-Dist: opentelemetry-instrumentation-anthropic>=0.39.3; python_version >= '3.10' and python_version < '4.0'
|
222
|
+
Requires-Dist: opentelemetry-instrumentation-mcp>=0.40.3; python_version >= '3.10' and python_version < '4.0'
|
223
|
+
Requires-Dist: opentelemetry-instrumentation-openai>=0.39.3; python_version >= '3.10' and python_version < '4.0'
|
222
224
|
Requires-Dist: prompt-toolkit>=3.0.50
|
223
225
|
Requires-Dist: pydantic-settings>=2.7.0
|
224
226
|
Requires-Dist: pydantic>=2.10.4
|
@@ -226,6 +228,8 @@ Requires-Dist: pyyaml>=6.0.2
|
|
226
228
|
Requires-Dist: rich>=13.9.4
|
227
229
|
Requires-Dist: tensorzero>=2025.4.7
|
228
230
|
Requires-Dist: typer>=0.15.1
|
231
|
+
Provides-Extra: azure
|
232
|
+
Requires-Dist: azure-identity>=1.14.0; extra == 'azure'
|
229
233
|
Provides-Extra: dev
|
230
234
|
Requires-Dist: anthropic>=0.42.0; extra == 'dev'
|
231
235
|
Requires-Dist: pre-commit>=4.0.1; extra == 'dev'
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# NOTE: Since version X.X, the Azure OpenAI integration in FastAgent reuses the OpenAI logic.
|
2
|
+
# Authentication (API Key or DefaultAzureCredential) and connectivity are managed automatically.
|
3
|
+
# You only need to configure the 'azure' section as indicated below; the system will select the appropriate method.
|
4
|
+
#
|
5
|
+
# Example configuration for Azure OpenAI in fast-agent
|
6
|
+
#
|
7
|
+
# There are three supported authentication/configuration modes for Azure OpenAI:
|
8
|
+
#
|
9
|
+
# 1. Using 'resource_name' and 'api_key' (recommended for most users)
|
10
|
+
# 2. Using 'base_url' and 'api_key' (for custom endpoints or sovereign clouds)
|
11
|
+
# 3. Using 'base_url' and DefaultAzureCredential (for managed identity, Azure CLI, etc.)
|
12
|
+
#
|
13
|
+
# Use ONLY one of the parameters: 'resource_name' or 'base_url'.
|
14
|
+
# - If you define 'base_url', it will be used directly as the endpoint and 'resource_name' will be ignored.
|
15
|
+
# - If you define 'resource_name' (and not 'base_url'), the endpoint will be constructed automatically.
|
16
|
+
# - If both are missing, the configuration is invalid.
|
17
|
+
#
|
18
|
+
# Do not include both at the same time.
|
19
|
+
|
20
|
+
# --- OPTION 1: Using resource_name and api_key (recommended for standard Azure) ---
|
21
|
+
default_model: "azure.my-deployment"
|
22
|
+
|
23
|
+
azure:
|
24
|
+
api_key: "YOUR_AZURE_OPENAI_API_KEY"
|
25
|
+
resource_name: "your-resource-name"
|
26
|
+
azure_deployment: "my-deployment"
|
27
|
+
api_version: "2023-05-15"
|
28
|
+
# Do not include base_url if you use resource_name
|
29
|
+
|
30
|
+
# --- OPTION 2: Using base_url and api_key (for custom endpoints or sovereign clouds) ---
|
31
|
+
# default_model: "azure.my-deployment"
|
32
|
+
#
|
33
|
+
# azure:
|
34
|
+
# api_key: "YOUR_AZURE_OPENAI_API_KEY"
|
35
|
+
# base_url: "https://your-resource-name.openai.azure.com/"
|
36
|
+
# azure_deployment: "my-deployment"
|
37
|
+
# api_version: "2023-05-15"
|
38
|
+
# # Do not include resource_name if you use base_url
|
39
|
+
|
40
|
+
# --- OPTION 3: Using base_url and DefaultAzureCredential (for managed identity, Azure CLI, etc.) ---
|
41
|
+
# Requires the 'azure-identity' package to be installed.
|
42
|
+
# No api_key or resource_name should be present in this mode.
|
43
|
+
# base_url is required and must be the full endpoint URL.
|
44
|
+
#
|
45
|
+
# default_model: "azure.my-deployment"
|
46
|
+
#
|
47
|
+
# azure:
|
48
|
+
# use_default_azure_credential: true
|
49
|
+
# base_url: "https://your-resource-name.openai.azure.com/"
|
50
|
+
# azure_deployment: "my-deployment"
|
51
|
+
# api_version: "2023-05-15"
|
52
|
+
# # Do not include api_key or resource_name in this mode
|
53
|
+
|
54
|
+
# You can add other providers or settings as needed.
|
@@ -1,6 +1,6 @@
|
|
1
1
|
[project]
|
2
2
|
name = "fast-agent-mcp"
|
3
|
-
version = "0.2.
|
3
|
+
version = "0.2.25"
|
4
4
|
description = "Define, Prompt and Test MCP enabled Agents and Workflows"
|
5
5
|
readme = "README.md"
|
6
6
|
license = { file = "LICENSE" }
|
@@ -25,18 +25,24 @@ dependencies = [
|
|
25
25
|
"typer>=0.15.1",
|
26
26
|
"anthropic>=0.49.0",
|
27
27
|
"openai>=1.63.2",
|
28
|
+
"azure-identity>=1.14.0",
|
28
29
|
"prompt-toolkit>=3.0.50",
|
29
30
|
"aiohttp>=3.11.13",
|
30
31
|
"a2a-types>=0.1.0",
|
31
|
-
"opentelemetry-instrumentation-openai>=0.39.3",
|
32
|
-
"opentelemetry-instrumentation-anthropic>=0.39.3",
|
32
|
+
"opentelemetry-instrumentation-openai>=0.39.3; python_version >= '3.10' and python_version < '4.0'",
|
33
|
+
"opentelemetry-instrumentation-anthropic>=0.39.3; python_version >= '3.10' and python_version < '4.0'",
|
33
34
|
"tensorzero>=2025.4.7",
|
35
|
+
"opentelemetry-instrumentation-mcp>=0.40.3; python_version >= '3.10' and python_version < '4.0'",
|
34
36
|
]
|
35
37
|
|
36
38
|
[project.optional-dependencies]
|
37
39
|
openai = [
|
38
40
|
"openai>=1.58.1",
|
39
41
|
]
|
42
|
+
# For Azure OpenAI with DefaultAzureCredential support, install with: pip install fast-agent-mcp[azure]
|
43
|
+
azure = [
|
44
|
+
"azure-identity>=1.14.0"
|
45
|
+
]
|
40
46
|
dev = [
|
41
47
|
"anthropic>=0.42.0",
|
42
48
|
"pre-commit>=4.0.1",
|
@@ -56,6 +62,10 @@ build-backend = "hatchling.build"
|
|
56
62
|
[tool.hatch.build.targets.wheel]
|
57
63
|
packages = ["src/mcp_agent"]
|
58
64
|
|
65
|
+
[[tool.poetry.packages]]
|
66
|
+
include = "mcp_agent"
|
67
|
+
from = "src"
|
68
|
+
|
59
69
|
[tool.hatch.build]
|
60
70
|
include = [
|
61
71
|
"src/mcp_agent/**/*.py",
|
@@ -92,42 +92,73 @@ def get_secrets_summary(secrets_path: Optional[Path]) -> dict:
|
|
92
92
|
return result
|
93
93
|
|
94
94
|
|
95
|
-
def check_api_keys(secrets_summary: dict) -> dict:
|
96
|
-
"""Check if API keys are configured in secrets file or environment.
|
95
|
+
def check_api_keys(secrets_summary: dict, config_summary: dict) -> dict:
|
96
|
+
"""Check if API keys are configured in secrets file or environment, including Azure DefaultAzureCredential.
|
97
|
+
Now also checks Azure config in main config file for retrocompatibility.
|
98
|
+
"""
|
97
99
|
import os
|
98
100
|
|
99
|
-
# Initialize results dict using Provider enum values
|
100
101
|
results = {
|
101
|
-
provider.value: {"env":
|
102
|
+
provider.value: {"env": "", "config": ""}
|
102
103
|
for provider in Provider
|
103
104
|
if provider != Provider.FAST_AGENT
|
104
|
-
}
|
105
|
+
}
|
105
106
|
|
106
107
|
# Get secrets if available
|
107
108
|
secrets = secrets_summary.get("secrets", {})
|
108
109
|
secrets_status = secrets_summary.get("status", "not_found")
|
110
|
+
# Get config if available
|
111
|
+
config = config_summary if config_summary.get("status") == "parsed" else {}
|
112
|
+
config_azure = {}
|
113
|
+
if config and "azure" in config.get("config", {}):
|
114
|
+
config_azure = config["config"]["azure"]
|
109
115
|
|
110
|
-
# Check both environment variables and config file for each provider
|
111
116
|
for provider_value in results:
|
112
|
-
#
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
if
|
126
|
-
|
127
|
-
|
128
|
-
|
117
|
+
# Special handling for Azure: support api_key and DefaultAzureCredential
|
118
|
+
if provider_value == "azure":
|
119
|
+
# Prefer secrets if present, else fallback to config
|
120
|
+
azure_cfg = {}
|
121
|
+
if secrets_status == "parsed" and "azure" in secrets:
|
122
|
+
azure_cfg = secrets.get("azure", {})
|
123
|
+
elif config_azure:
|
124
|
+
azure_cfg = config_azure
|
125
|
+
|
126
|
+
use_default_cred = azure_cfg.get("use_default_azure_credential", False)
|
127
|
+
base_url = azure_cfg.get("base_url")
|
128
|
+
api_key = azure_cfg.get("api_key")
|
129
|
+
# DefaultAzureCredential mode
|
130
|
+
if use_default_cred and base_url:
|
131
|
+
results[provider_value]["config"] = "DefaultAzureCredential"
|
132
|
+
# API key mode (retrocompatible)
|
133
|
+
if api_key and api_key != API_KEY_HINT_TEXT:
|
134
|
+
if len(api_key) > 5:
|
135
|
+
if results[provider_value]["config"]:
|
136
|
+
results[provider_value]["config"] += " + api_key"
|
137
|
+
else:
|
138
|
+
results[provider_value]["config"] = f"...{api_key[-5:]}"
|
129
139
|
else:
|
130
|
-
results[provider_value]["config"]
|
140
|
+
if results[provider_value]["config"]:
|
141
|
+
results[provider_value]["config"] += " + api_key"
|
142
|
+
else:
|
143
|
+
results[provider_value]["config"] = "...***"
|
144
|
+
else:
|
145
|
+
# Check environment variables using ProviderKeyManager
|
146
|
+
env_key_name = ProviderKeyManager.get_env_key_name(provider_value)
|
147
|
+
env_key_value = os.environ.get(env_key_name)
|
148
|
+
if env_key_value:
|
149
|
+
if len(env_key_value) > 5:
|
150
|
+
results[provider_value]["env"] = f"...{env_key_value[-5:]}"
|
151
|
+
else:
|
152
|
+
results[provider_value]["env"] = "...***"
|
153
|
+
|
154
|
+
# Check secrets file if it was parsed successfully
|
155
|
+
if secrets_status == "parsed":
|
156
|
+
config_key = ProviderKeyManager.get_config_file_key(provider_value, secrets)
|
157
|
+
if config_key and config_key != API_KEY_HINT_TEXT:
|
158
|
+
if len(config_key) > 5:
|
159
|
+
results[provider_value]["config"] = f"...{config_key[-5:]}"
|
160
|
+
else:
|
161
|
+
results[provider_value]["config"] = "...***"
|
131
162
|
|
132
163
|
return results
|
133
164
|
|
@@ -235,7 +266,7 @@ def show_check_summary() -> None:
|
|
235
266
|
system_info = get_system_info()
|
236
267
|
config_summary = get_config_summary(config_files["config"])
|
237
268
|
secrets_summary = get_secrets_summary(config_files["secrets"])
|
238
|
-
api_keys = check_api_keys(secrets_summary)
|
269
|
+
api_keys = check_api_keys(secrets_summary, config_summary)
|
239
270
|
fastagent_version = get_fastagent_version()
|
240
271
|
|
241
272
|
# System info panel
|
@@ -341,8 +372,10 @@ def show_check_summary() -> None:
|
|
341
372
|
|
342
373
|
keys_table.add_row(provider.capitalize(), env_status, config_status, active)
|
343
374
|
|
344
|
-
|
345
|
-
|
375
|
+
# Print the API Keys panel (fix: this was missing)
|
376
|
+
keys_panel = Panel(keys_table, title="API Keys", border_style="blue", subtitle_align="left")
|
377
|
+
console.print(keys_panel)
|
378
|
+
|
346
379
|
# MCP Servers panel (shown after API Keys)
|
347
380
|
if config_summary.get("status") == "parsed":
|
348
381
|
mcp_servers = config_summary.get("mcp_servers", [])
|
@@ -447,4 +480,4 @@ def show(
|
|
447
480
|
def main(ctx: typer.Context) -> None:
|
448
481
|
"""Check and diagnose FastAgent configuration."""
|
449
482
|
if ctx.invoked_subcommand is None:
|
450
|
-
show_check_summary()
|
483
|
+
show_check_summary()
|
@@ -179,6 +179,20 @@ class OpenRouterSettings(BaseModel):
|
|
179
179
|
model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
|
180
180
|
|
181
181
|
|
182
|
+
class AzureSettings(BaseModel):
|
183
|
+
"""
|
184
|
+
Settings for using Azure OpenAI Service in the fast-agent application.
|
185
|
+
"""
|
186
|
+
|
187
|
+
api_key: str | None = None
|
188
|
+
resource_name: str | None = None
|
189
|
+
azure_deployment: str | None = None
|
190
|
+
api_version: str | None = None
|
191
|
+
base_url: str | None = None # Optional, can be constructed from resource_name
|
192
|
+
|
193
|
+
model_config = ConfigDict(extra="allow", arbitrary_types_allowed=True)
|
194
|
+
|
195
|
+
|
182
196
|
class OpenTelemetrySettings(BaseModel):
|
183
197
|
"""
|
184
198
|
OTEL settings for the fast-agent application.
|
@@ -302,6 +316,9 @@ class Settings(BaseSettings):
|
|
302
316
|
tensorzero: Optional[TensorZeroSettings] = None
|
303
317
|
"""Settings for using TensorZero inference gateway"""
|
304
318
|
|
319
|
+
azure: AzureSettings | None = None
|
320
|
+
"""Settings for using Azure OpenAI Service in the fast-agent application"""
|
321
|
+
|
305
322
|
logger: LoggerSettings | None = LoggerSettings()
|
306
323
|
"""Logger settings for the fast-agent application"""
|
307
324
|
|
@@ -11,6 +11,7 @@ from mcp import ServerSession
|
|
11
11
|
from opentelemetry import trace
|
12
12
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
13
13
|
from opentelemetry.instrumentation.anthropic import AnthropicInstrumentor
|
14
|
+
from opentelemetry.instrumentation.mcp import McpInstrumentor
|
14
15
|
from opentelemetry.instrumentation.openai import OpenAIInstrumentor
|
15
16
|
from opentelemetry.propagate import set_global_textmap
|
16
17
|
from opentelemetry.sdk.resources import Resource
|
@@ -111,6 +112,7 @@ async def configure_otel(config: "Settings") -> None:
|
|
111
112
|
trace.set_tracer_provider(tracer_provider)
|
112
113
|
AnthropicInstrumentor().instrument()
|
113
114
|
OpenAIInstrumentor().instrument()
|
115
|
+
McpInstrumentor().instrument()
|
114
116
|
|
115
117
|
|
116
118
|
async def configure_logger(config: "Settings") -> None:
|
@@ -10,6 +10,7 @@ from mcp_agent.llm.augmented_llm_passthrough import PassthroughLLM
|
|
10
10
|
from mcp_agent.llm.augmented_llm_playback import PlaybackLLM
|
11
11
|
from mcp_agent.llm.provider_types import Provider
|
12
12
|
from mcp_agent.llm.providers.augmented_llm_anthropic import AnthropicAugmentedLLM
|
13
|
+
from mcp_agent.llm.providers.augmented_llm_azure import AzureOpenAIAugmentedLLM
|
13
14
|
from mcp_agent.llm.providers.augmented_llm_deepseek import DeepSeekAugmentedLLM
|
14
15
|
from mcp_agent.llm.providers.augmented_llm_generic import GenericAugmentedLLM
|
15
16
|
from mcp_agent.llm.providers.augmented_llm_google import GoogleAugmentedLLM
|
@@ -113,6 +114,7 @@ class ModelFactory:
|
|
113
114
|
Provider.GOOGLE: GoogleAugmentedLLM, # type: ignore
|
114
115
|
Provider.OPENROUTER: OpenRouterAugmentedLLM,
|
115
116
|
Provider.TENSORZERO: TensorZeroAugmentedLLM,
|
117
|
+
Provider.AZURE: AzureOpenAIAugmentedLLM,
|
116
118
|
}
|
117
119
|
|
118
120
|
# Mapping of special model names to their specific LLM classes
|
@@ -0,0 +1,137 @@
|
|
1
|
+
from openai import AuthenticationError, AzureOpenAI, OpenAI
|
2
|
+
|
3
|
+
from mcp_agent.core.exceptions import ProviderKeyError
|
4
|
+
from mcp_agent.llm.provider_types import Provider
|
5
|
+
from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
|
6
|
+
|
7
|
+
try:
|
8
|
+
from azure.identity import DefaultAzureCredential
|
9
|
+
except ImportError:
|
10
|
+
DefaultAzureCredential = None
|
11
|
+
|
12
|
+
|
13
|
+
def _extract_resource_name(url: str) -> str | None:
|
14
|
+
from urllib.parse import urlparse
|
15
|
+
|
16
|
+
host = urlparse(url).hostname or ""
|
17
|
+
suffix = ".openai.azure.com"
|
18
|
+
return host.replace(suffix, "") if host.endswith(suffix) else None
|
19
|
+
|
20
|
+
|
21
|
+
DEFAULT_AZURE_API_VERSION = "2023-05-15"
|
22
|
+
|
23
|
+
|
24
|
+
class AzureOpenAIAugmentedLLM(OpenAIAugmentedLLM):
|
25
|
+
"""
|
26
|
+
Azure OpenAI implementation extending OpenAIAugmentedLLM.
|
27
|
+
Handles both API Key and DefaultAzureCredential authentication.
|
28
|
+
"""
|
29
|
+
|
30
|
+
def __init__(self, provider: Provider = Provider.AZURE, *args, **kwargs):
|
31
|
+
# Set provider to AZURE, pass through to base
|
32
|
+
super().__init__(provider=provider, *args, **kwargs)
|
33
|
+
|
34
|
+
# Context/config extraction
|
35
|
+
context = getattr(self, "context", None)
|
36
|
+
config = getattr(context, "config", None) if context else None
|
37
|
+
azure_cfg = getattr(config, "azure", None) if config else None
|
38
|
+
|
39
|
+
if azure_cfg is None:
|
40
|
+
raise ProviderKeyError(
|
41
|
+
"Missing Azure configuration",
|
42
|
+
"Azure provider requires configuration section 'azure' in your config file.",
|
43
|
+
)
|
44
|
+
|
45
|
+
self.use_default_cred = getattr(azure_cfg, "use_default_azure_credential", False)
|
46
|
+
default_request_params = getattr(self, "default_request_params", None)
|
47
|
+
self.deployment_name = getattr(default_request_params, "model", None) or getattr(
|
48
|
+
azure_cfg, "azure_deployment", None
|
49
|
+
)
|
50
|
+
self.api_version = getattr(azure_cfg, "api_version", None) or DEFAULT_AZURE_API_VERSION
|
51
|
+
|
52
|
+
if self.use_default_cred:
|
53
|
+
self.base_url = getattr(azure_cfg, "base_url", None)
|
54
|
+
if not self.base_url:
|
55
|
+
raise ProviderKeyError(
|
56
|
+
"Missing Azure endpoint",
|
57
|
+
"When using 'use_default_azure_credential', 'base_url' is required in azure config.",
|
58
|
+
)
|
59
|
+
if DefaultAzureCredential is None:
|
60
|
+
raise ProviderKeyError(
|
61
|
+
"azure-identity not installed",
|
62
|
+
"You must install 'azure-identity' to use DefaultAzureCredential authentication.",
|
63
|
+
)
|
64
|
+
self.credential = DefaultAzureCredential()
|
65
|
+
|
66
|
+
def get_azure_token():
|
67
|
+
token = self.credential.get_token("https://cognitiveservices.azure.com/.default")
|
68
|
+
return token.token
|
69
|
+
|
70
|
+
self.get_azure_token = get_azure_token
|
71
|
+
else:
|
72
|
+
self.api_key = getattr(azure_cfg, "api_key", None)
|
73
|
+
self.resource_name = getattr(azure_cfg, "resource_name", None)
|
74
|
+
self.base_url = getattr(azure_cfg, "base_url", None) or (
|
75
|
+
f"https://{self.resource_name}.openai.azure.com/" if self.resource_name else None
|
76
|
+
)
|
77
|
+
if not self.api_key:
|
78
|
+
raise ProviderKeyError(
|
79
|
+
"Missing Azure OpenAI credentials",
|
80
|
+
"Field 'api_key' is required in azure config.",
|
81
|
+
)
|
82
|
+
if not (self.resource_name or self.base_url):
|
83
|
+
raise ProviderKeyError(
|
84
|
+
"Missing Azure endpoint",
|
85
|
+
"Provide either 'resource_name' or 'base_url' under azure config.",
|
86
|
+
)
|
87
|
+
if not self.deployment_name:
|
88
|
+
raise ProviderKeyError(
|
89
|
+
"Missing deployment name",
|
90
|
+
"Set 'azure_deployment' in config or pass model=<deployment>.",
|
91
|
+
)
|
92
|
+
# If resource_name was missing, try to extract it from base_url
|
93
|
+
if not self.resource_name and self.base_url:
|
94
|
+
self.resource_name = _extract_resource_name(self.base_url)
|
95
|
+
|
96
|
+
def _openai_client(self) -> OpenAI:
|
97
|
+
"""
|
98
|
+
Returns an AzureOpenAI client, handling both API Key and DefaultAzureCredential.
|
99
|
+
"""
|
100
|
+
try:
|
101
|
+
if self.use_default_cred:
|
102
|
+
if self.base_url is None:
|
103
|
+
raise ProviderKeyError(
|
104
|
+
"Missing Azure endpoint",
|
105
|
+
"azure_endpoint (base_url) is None at client creation time.",
|
106
|
+
)
|
107
|
+
return AzureOpenAI(
|
108
|
+
azure_ad_token_provider=self.get_azure_token,
|
109
|
+
azure_endpoint=self.base_url,
|
110
|
+
api_version=self.api_version,
|
111
|
+
azure_deployment=self.deployment_name,
|
112
|
+
)
|
113
|
+
else:
|
114
|
+
if self.base_url is None:
|
115
|
+
raise ProviderKeyError(
|
116
|
+
"Missing Azure endpoint",
|
117
|
+
"azure_endpoint (base_url) is None at client creation time.",
|
118
|
+
)
|
119
|
+
return AzureOpenAI(
|
120
|
+
api_key=self.api_key,
|
121
|
+
azure_endpoint=self.base_url,
|
122
|
+
api_version=self.api_version,
|
123
|
+
azure_deployment=self.deployment_name,
|
124
|
+
)
|
125
|
+
except AuthenticationError as e:
|
126
|
+
if self.use_default_cred:
|
127
|
+
raise ProviderKeyError(
|
128
|
+
"Invalid Azure AD credentials",
|
129
|
+
"The configured Azure AD credentials were rejected.\n"
|
130
|
+
"Please check your Azure identity setup.",
|
131
|
+
) from e
|
132
|
+
else:
|
133
|
+
raise ProviderKeyError(
|
134
|
+
"Invalid Azure OpenAI API key",
|
135
|
+
"The configured Azure OpenAI API key was rejected.\n"
|
136
|
+
"Please check that your API key is valid and not expired.",
|
137
|
+
) from e
|
{fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/llm/providers/augmented_llm_openai.py
RENAMED
@@ -78,7 +78,7 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
|
|
78
78
|
self._reasoning_effort = self.context.config.openai.reasoning_effort
|
79
79
|
|
80
80
|
# Determine if we're using a reasoning model
|
81
|
-
# TODO -- move this to model
|
81
|
+
# TODO -- move this to model capabilities, add o4.
|
82
82
|
chosen_model = self.default_request_params.model if self.default_request_params else None
|
83
83
|
self._reasoning = chosen_model and (
|
84
84
|
chosen_model.startswith("o3") or chosen_model.startswith("o1")
|
@@ -274,7 +274,9 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
|
|
274
274
|
# Calculate new conversation messages (excluding prompts)
|
275
275
|
new_messages = messages[len(prompt_messages) :]
|
276
276
|
|
277
|
-
|
277
|
+
if system_prompt:
|
278
|
+
new_messages = new_messages[1:]
|
279
|
+
|
278
280
|
self.history.set(new_messages)
|
279
281
|
|
280
282
|
self._log_chat_finished(model=self.default_request_params.model)
|
@@ -323,7 +325,7 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
|
|
323
325
|
return result
|
324
326
|
|
325
327
|
def _prepare_api_request(
|
326
|
-
self, messages, tools, request_params: RequestParams
|
328
|
+
self, messages, tools: List[ChatCompletionToolParam] | None, request_params: RequestParams
|
327
329
|
) -> dict[str, str]:
|
328
330
|
# Create base arguments dictionary
|
329
331
|
|
@@ -343,9 +345,8 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
|
|
343
345
|
)
|
344
346
|
else:
|
345
347
|
base_args["max_tokens"] = request_params.maxTokens
|
346
|
-
|
347
|
-
|
348
|
-
base_args["parallel_tool_calls"] = request_params.parallel_tool_calls
|
348
|
+
if tools:
|
349
|
+
base_args["parallel_tool_calls"] = request_params.parallel_tool_calls
|
349
350
|
|
350
351
|
arguments: Dict[str, str] = self.prepare_provider_arguments(
|
351
352
|
base_args, request_params, self.OPENAI_EXCLUDE_FIELDS.union(self.BASE_EXCLUDE_FIELDS)
|
@@ -354,7 +355,7 @@ class OpenAIAugmentedLLM(AugmentedLLM[ChatCompletionMessageParam, ChatCompletion
|
|
354
355
|
|
355
356
|
def adjust_schema(self, inputSchema: Dict) -> Dict:
|
356
357
|
# return inputSchema
|
357
|
-
if not Provider.OPENAI
|
358
|
+
if self.provider not in [Provider.OPENAI, Provider.AZURE]:
|
358
359
|
return inputSchema
|
359
360
|
|
360
361
|
if "properties" in inputSchema:
|
@@ -0,0 +1,16 @@
|
|
1
|
+
"""
|
2
|
+
Common constants and utilities shared between modules to avoid circular imports.
|
3
|
+
"""
|
4
|
+
|
5
|
+
# Constants
|
6
|
+
SEP = "-"
|
7
|
+
|
8
|
+
|
9
|
+
def create_namespaced_name(server_name: str, resource_name: str) -> str:
|
10
|
+
"""Create a namespaced resource name from server and resource names"""
|
11
|
+
return f"{server_name}{SEP}{resource_name}"
|
12
|
+
|
13
|
+
|
14
|
+
def is_namespaced_name(name: str) -> bool:
|
15
|
+
"""Check if a name is already namespaced"""
|
16
|
+
return SEP in name
|
{fast_agent_mcp-0.2.23 → fast_agent_mcp-0.2.25}/src/mcp_agent/mcp/mcp_agent_client_session.py
RENAMED
@@ -6,21 +6,16 @@ It adds logging and supports sampling requests.
|
|
6
6
|
from datetime import timedelta
|
7
7
|
from typing import TYPE_CHECKING, Optional
|
8
8
|
|
9
|
-
from mcp import ClientSession
|
9
|
+
from mcp import ClientSession, ServerNotification
|
10
10
|
from mcp.shared.session import (
|
11
|
-
ReceiveNotificationT,
|
12
11
|
ReceiveResultT,
|
13
12
|
RequestId,
|
14
13
|
SendNotificationT,
|
15
14
|
SendRequestT,
|
16
15
|
SendResultT,
|
17
16
|
)
|
18
|
-
from mcp.types import
|
19
|
-
|
20
|
-
ListRootsResult,
|
21
|
-
Root,
|
22
|
-
)
|
23
|
-
from pydantic import AnyUrl
|
17
|
+
from mcp.types import ErrorData, ListRootsResult, Root, ToolListChangedNotification
|
18
|
+
from pydantic import FileUrl
|
24
19
|
|
25
20
|
from mcp_agent.context_dependent import ContextDependent
|
26
21
|
from mcp_agent.logging.logger import get_logger
|
@@ -45,7 +40,7 @@ async def list_roots(ctx: ClientSession) -> ListRootsResult:
|
|
45
40
|
):
|
46
41
|
roots = [
|
47
42
|
Root(
|
48
|
-
uri=
|
43
|
+
uri=FileUrl(
|
49
44
|
root.server_uri_alias or root.uri,
|
50
45
|
),
|
51
46
|
name=root.name,
|
@@ -67,6 +62,11 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
|
|
67
62
|
"""
|
68
63
|
|
69
64
|
def __init__(self, *args, **kwargs) -> None:
|
65
|
+
# Extract server_name if provided in kwargs
|
66
|
+
self.session_server_name = kwargs.pop("server_name", None)
|
67
|
+
# Extract the notification callbacks if provided
|
68
|
+
self._tool_list_changed_callback = kwargs.pop("tool_list_changed_callback", None)
|
69
|
+
|
70
70
|
super().__init__(*args, **kwargs, list_roots_callback=list_roots, sampling_callback=sample)
|
71
71
|
self.server_config: Optional[MCPServerSettings] = None
|
72
72
|
|
@@ -104,7 +104,7 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
|
|
104
104
|
)
|
105
105
|
return await super()._send_response(request_id, response)
|
106
106
|
|
107
|
-
async def _received_notification(self, notification:
|
107
|
+
async def _received_notification(self, notification: ServerNotification) -> None:
|
108
108
|
"""
|
109
109
|
Can be overridden by subclasses to handle a notification without needing
|
110
110
|
to listen on the message stream.
|
@@ -113,7 +113,37 @@ class MCPAgentClientSession(ClientSession, ContextDependent):
|
|
113
113
|
"_received_notification: notification=",
|
114
114
|
data=notification.model_dump(),
|
115
115
|
)
|
116
|
-
|
116
|
+
|
117
|
+
# Call parent notification handler first
|
118
|
+
await super()._received_notification(notification)
|
119
|
+
|
120
|
+
# Then process our specific notification types
|
121
|
+
match notification.root:
|
122
|
+
case ToolListChangedNotification():
|
123
|
+
# Simple notification handling - just call the callback if it exists
|
124
|
+
if self._tool_list_changed_callback and self.session_server_name:
|
125
|
+
logger.info(
|
126
|
+
f"Tool list changed for server '{self.session_server_name}', triggering callback"
|
127
|
+
)
|
128
|
+
# Use asyncio.create_task to prevent blocking the notification handler
|
129
|
+
import asyncio
|
130
|
+
asyncio.create_task(self._handle_tool_list_change_callback(self.session_server_name))
|
131
|
+
else:
|
132
|
+
logger.debug(
|
133
|
+
f"Tool list changed for server '{self.session_server_name}' but no callback registered"
|
134
|
+
)
|
135
|
+
|
136
|
+
return None
|
137
|
+
|
138
|
+
async def _handle_tool_list_change_callback(self, server_name: str) -> None:
|
139
|
+
"""
|
140
|
+
Helper method to handle tool list change callback in a separate task
|
141
|
+
to prevent blocking the notification handler
|
142
|
+
"""
|
143
|
+
try:
|
144
|
+
await self._tool_list_changed_callback(server_name)
|
145
|
+
except Exception as e:
|
146
|
+
logger.error(f"Error in tool list changed callback: {e}")
|
117
147
|
|
118
148
|
async def send_progress_notification(
|
119
149
|
self, progress_token: str | int, progress: float, total: float | None = None
|