fast-agent-mcp 0.2.57__py3-none-any.whl → 0.3.0__py3-none-any.whl
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.
Potentially problematic release.
This version of fast-agent-mcp might be problematic. Click here for more details.
- fast_agent/__init__.py +127 -0
- fast_agent/agents/__init__.py +36 -0
- {mcp_agent/core → fast_agent/agents}/agent_types.py +2 -1
- fast_agent/agents/llm_agent.py +217 -0
- fast_agent/agents/llm_decorator.py +486 -0
- mcp_agent/agents/base_agent.py → fast_agent/agents/mcp_agent.py +377 -385
- fast_agent/agents/tool_agent.py +168 -0
- {mcp_agent → fast_agent}/agents/workflow/chain_agent.py +43 -33
- {mcp_agent → fast_agent}/agents/workflow/evaluator_optimizer.py +31 -35
- {mcp_agent → fast_agent}/agents/workflow/iterative_planner.py +56 -47
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_models.py +4 -4
- {mcp_agent → fast_agent}/agents/workflow/parallel_agent.py +34 -41
- {mcp_agent → fast_agent}/agents/workflow/router_agent.py +54 -39
- {mcp_agent → fast_agent}/cli/__main__.py +5 -3
- {mcp_agent → fast_agent}/cli/commands/check_config.py +95 -66
- {mcp_agent → fast_agent}/cli/commands/go.py +20 -11
- {mcp_agent → fast_agent}/cli/commands/quickstart.py +4 -4
- {mcp_agent → fast_agent}/cli/commands/server_helpers.py +1 -1
- {mcp_agent → fast_agent}/cli/commands/setup.py +64 -134
- {mcp_agent → fast_agent}/cli/commands/url_parser.py +9 -8
- {mcp_agent → fast_agent}/cli/main.py +36 -16
- {mcp_agent → fast_agent}/cli/terminal.py +2 -2
- {mcp_agent → fast_agent}/config.py +13 -2
- fast_agent/constants.py +8 -0
- {mcp_agent → fast_agent}/context.py +24 -19
- {mcp_agent → fast_agent}/context_dependent.py +9 -5
- fast_agent/core/__init__.py +17 -0
- {mcp_agent → fast_agent}/core/agent_app.py +39 -36
- fast_agent/core/core_app.py +135 -0
- {mcp_agent → fast_agent}/core/direct_decorators.py +12 -26
- {mcp_agent → fast_agent}/core/direct_factory.py +95 -73
- {mcp_agent → fast_agent/core}/executor/executor.py +4 -5
- {mcp_agent → fast_agent}/core/fastagent.py +32 -32
- fast_agent/core/logging/__init__.py +5 -0
- {mcp_agent → fast_agent/core}/logging/events.py +3 -3
- {mcp_agent → fast_agent/core}/logging/json_serializer.py +1 -1
- {mcp_agent → fast_agent/core}/logging/listeners.py +85 -7
- {mcp_agent → fast_agent/core}/logging/logger.py +7 -7
- {mcp_agent → fast_agent/core}/logging/transport.py +10 -11
- fast_agent/core/prompt.py +9 -0
- {mcp_agent → fast_agent}/core/validation.py +4 -4
- fast_agent/event_progress.py +61 -0
- fast_agent/history/history_exporter.py +44 -0
- {mcp_agent → fast_agent}/human_input/__init__.py +9 -12
- {mcp_agent → fast_agent}/human_input/elicitation_handler.py +26 -8
- {mcp_agent → fast_agent}/human_input/elicitation_state.py +7 -7
- {mcp_agent → fast_agent}/human_input/simple_form.py +6 -4
- {mcp_agent → fast_agent}/human_input/types.py +1 -18
- fast_agent/interfaces.py +228 -0
- fast_agent/llm/__init__.py +9 -0
- mcp_agent/llm/augmented_llm.py → fast_agent/llm/fastagent_llm.py +128 -218
- fast_agent/llm/internal/passthrough.py +137 -0
- mcp_agent/llm/augmented_llm_playback.py → fast_agent/llm/internal/playback.py +29 -25
- mcp_agent/llm/augmented_llm_silent.py → fast_agent/llm/internal/silent.py +10 -17
- fast_agent/llm/internal/slow.py +38 -0
- {mcp_agent → fast_agent}/llm/memory.py +40 -30
- {mcp_agent → fast_agent}/llm/model_database.py +35 -2
- {mcp_agent → fast_agent}/llm/model_factory.py +103 -77
- fast_agent/llm/model_info.py +126 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/anthropic_utils.py +7 -7
- fast_agent/llm/provider/anthropic/llm_anthropic.py +603 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/anthropic}/multipart_converter_anthropic.py +79 -86
- fast_agent/llm/provider/bedrock/bedrock_utils.py +218 -0
- fast_agent/llm/provider/bedrock/llm_bedrock.py +2192 -0
- {mcp_agent/llm/providers → fast_agent/llm/provider/google}/google_converter.py +66 -14
- fast_agent/llm/provider/google/llm_google_native.py +431 -0
- mcp_agent/llm/providers/augmented_llm_aliyun.py → fast_agent/llm/provider/openai/llm_aliyun.py +6 -7
- mcp_agent/llm/providers/augmented_llm_azure.py → fast_agent/llm/provider/openai/llm_azure.py +4 -4
- mcp_agent/llm/providers/augmented_llm_deepseek.py → fast_agent/llm/provider/openai/llm_deepseek.py +10 -11
- mcp_agent/llm/providers/augmented_llm_generic.py → fast_agent/llm/provider/openai/llm_generic.py +4 -4
- mcp_agent/llm/providers/augmented_llm_google_oai.py → fast_agent/llm/provider/openai/llm_google_oai.py +4 -4
- mcp_agent/llm/providers/augmented_llm_groq.py → fast_agent/llm/provider/openai/llm_groq.py +14 -16
- mcp_agent/llm/providers/augmented_llm_openai.py → fast_agent/llm/provider/openai/llm_openai.py +133 -206
- mcp_agent/llm/providers/augmented_llm_openrouter.py → fast_agent/llm/provider/openai/llm_openrouter.py +6 -6
- mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py → fast_agent/llm/provider/openai/llm_tensorzero_openai.py +17 -16
- mcp_agent/llm/providers/augmented_llm_xai.py → fast_agent/llm/provider/openai/llm_xai.py +6 -6
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/multipart_converter_openai.py +125 -63
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_multipart.py +12 -12
- {mcp_agent/llm/providers → fast_agent/llm/provider/openai}/openai_utils.py +18 -16
- {mcp_agent → fast_agent}/llm/provider_key_manager.py +2 -2
- {mcp_agent → fast_agent}/llm/provider_types.py +2 -0
- {mcp_agent → fast_agent}/llm/sampling_converter.py +15 -12
- {mcp_agent → fast_agent}/llm/usage_tracking.py +23 -5
- fast_agent/mcp/__init__.py +43 -0
- {mcp_agent → fast_agent}/mcp/elicitation_factory.py +3 -3
- {mcp_agent → fast_agent}/mcp/elicitation_handlers.py +19 -10
- {mcp_agent → fast_agent}/mcp/gen_client.py +3 -3
- fast_agent/mcp/helpers/__init__.py +36 -0
- fast_agent/mcp/helpers/content_helpers.py +183 -0
- {mcp_agent → fast_agent}/mcp/helpers/server_config_helpers.py +8 -8
- {mcp_agent → fast_agent}/mcp/hf_auth.py +25 -23
- fast_agent/mcp/interfaces.py +93 -0
- {mcp_agent → fast_agent}/mcp/logger_textio.py +4 -4
- {mcp_agent → fast_agent}/mcp/mcp_agent_client_session.py +49 -44
- {mcp_agent → fast_agent}/mcp/mcp_aggregator.py +66 -115
- {mcp_agent → fast_agent}/mcp/mcp_connection_manager.py +16 -23
- {mcp_agent/core → fast_agent/mcp}/mcp_content.py +23 -15
- {mcp_agent → fast_agent}/mcp/mime_utils.py +39 -0
- fast_agent/mcp/prompt.py +159 -0
- mcp_agent/mcp/prompt_message_multipart.py → fast_agent/mcp/prompt_message_extended.py +27 -20
- {mcp_agent → fast_agent}/mcp/prompt_render.py +21 -19
- {mcp_agent → fast_agent}/mcp/prompt_serialization.py +46 -46
- fast_agent/mcp/prompts/__main__.py +7 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_helpers.py +31 -30
- {mcp_agent → fast_agent}/mcp/prompts/prompt_load.py +8 -8
- {mcp_agent → fast_agent}/mcp/prompts/prompt_server.py +11 -19
- {mcp_agent → fast_agent}/mcp/prompts/prompt_template.py +18 -18
- {mcp_agent → fast_agent}/mcp/resource_utils.py +1 -1
- {mcp_agent → fast_agent}/mcp/sampling.py +31 -26
- {mcp_agent/mcp_server → fast_agent/mcp/server}/__init__.py +1 -1
- {mcp_agent/mcp_server → fast_agent/mcp/server}/agent_server.py +5 -6
- fast_agent/mcp/ui_agent.py +48 -0
- fast_agent/mcp/ui_mixin.py +209 -0
- fast_agent/mcp_server_registry.py +90 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis-campaign.py +5 -4
- {mcp_agent → fast_agent}/resources/examples/data-analysis/analysis.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_forms_server.py +25 -3
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/forms_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/game_character_handler.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/tool_call.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_one.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/agent_two.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-eval.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher-imp.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/researcher/researcher.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/tensorzero/agent.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/tensorzero/image_demo.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/tensorzero/simple_agent.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/chaining.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/evaluator.py +3 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/human_input.py +5 -3
- {mcp_agent → fast_agent}/resources/examples/workflows/orchestrator.py +1 -1
- {mcp_agent → fast_agent}/resources/examples/workflows/parallel.py +2 -2
- {mcp_agent → fast_agent}/resources/examples/workflows/router.py +5 -2
- fast_agent/resources/setup/.gitignore +24 -0
- fast_agent/resources/setup/agent.py +18 -0
- fast_agent/resources/setup/fastagent.config.yaml +44 -0
- fast_agent/resources/setup/fastagent.secrets.yaml.example +38 -0
- fast_agent/tools/elicitation.py +369 -0
- fast_agent/types/__init__.py +32 -0
- fast_agent/types/llm_stop_reason.py +77 -0
- fast_agent/ui/__init__.py +38 -0
- fast_agent/ui/console_display.py +1005 -0
- {mcp_agent/human_input → fast_agent/ui}/elicitation_form.py +56 -39
- mcp_agent/human_input/elicitation_forms.py → fast_agent/ui/elicitation_style.py +1 -1
- {mcp_agent/core → fast_agent/ui}/enhanced_prompt.py +96 -25
- {mcp_agent/core → fast_agent/ui}/interactive_prompt.py +330 -125
- fast_agent/ui/mcp_ui_utils.py +224 -0
- {mcp_agent → fast_agent/ui}/progress_display.py +2 -2
- {mcp_agent/logging → fast_agent/ui}/rich_progress.py +4 -4
- {mcp_agent/core → fast_agent/ui}/usage_display.py +3 -8
- {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/METADATA +7 -7
- fast_agent_mcp-0.3.0.dist-info/RECORD +202 -0
- fast_agent_mcp-0.3.0.dist-info/entry_points.txt +5 -0
- fast_agent_mcp-0.2.57.dist-info/RECORD +0 -192
- fast_agent_mcp-0.2.57.dist-info/entry_points.txt +0 -6
- mcp_agent/__init__.py +0 -114
- mcp_agent/agents/agent.py +0 -92
- mcp_agent/agents/workflow/__init__.py +0 -1
- mcp_agent/agents/workflow/orchestrator_agent.py +0 -597
- mcp_agent/app.py +0 -175
- mcp_agent/core/__init__.py +0 -26
- mcp_agent/core/prompt.py +0 -191
- mcp_agent/event_progress.py +0 -134
- mcp_agent/human_input/handler.py +0 -81
- mcp_agent/llm/__init__.py +0 -2
- mcp_agent/llm/augmented_llm_passthrough.py +0 -232
- mcp_agent/llm/augmented_llm_slow.py +0 -53
- mcp_agent/llm/providers/__init__.py +0 -8
- mcp_agent/llm/providers/augmented_llm_anthropic.py +0 -717
- mcp_agent/llm/providers/augmented_llm_bedrock.py +0 -1788
- mcp_agent/llm/providers/augmented_llm_google_native.py +0 -495
- mcp_agent/llm/providers/sampling_converter_anthropic.py +0 -57
- mcp_agent/llm/providers/sampling_converter_openai.py +0 -26
- mcp_agent/llm/sampling_format_converter.py +0 -37
- mcp_agent/logging/__init__.py +0 -0
- mcp_agent/mcp/__init__.py +0 -50
- mcp_agent/mcp/helpers/__init__.py +0 -25
- mcp_agent/mcp/helpers/content_helpers.py +0 -187
- mcp_agent/mcp/interfaces.py +0 -266
- mcp_agent/mcp/prompts/__init__.py +0 -0
- mcp_agent/mcp/prompts/__main__.py +0 -10
- mcp_agent/mcp_server_registry.py +0 -343
- mcp_agent/tools/tool_definition.py +0 -14
- mcp_agent/ui/console_display.py +0 -790
- mcp_agent/ui/console_display_legacy.py +0 -401
- {mcp_agent → fast_agent}/agents/workflow/orchestrator_prompts.py +0 -0
- {mcp_agent/agents → fast_agent/cli}/__init__.py +0 -0
- {mcp_agent → fast_agent}/cli/constants.py +0 -0
- {mcp_agent → fast_agent}/core/error_handling.py +0 -0
- {mcp_agent → fast_agent}/core/exceptions.py +0 -0
- {mcp_agent/cli → fast_agent/core/executor}/__init__.py +0 -0
- {mcp_agent → fast_agent/core}/executor/task_registry.py +0 -0
- {mcp_agent → fast_agent/core}/executor/workflow_signal.py +0 -0
- {mcp_agent → fast_agent}/human_input/form_fields.py +0 -0
- {mcp_agent → fast_agent}/llm/prompt_utils.py +0 -0
- {mcp_agent/core → fast_agent/llm}/request_params.py +0 -0
- {mcp_agent → fast_agent}/mcp/common.py +0 -0
- {mcp_agent/executor → fast_agent/mcp/prompts}/__init__.py +0 -0
- {mcp_agent → fast_agent}/mcp/prompts/prompt_constants.py +0 -0
- {mcp_agent → fast_agent}/py.typed +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_account_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/elicitation_game_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/elicitations/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/mcp/state-transfer/fastagent.secrets.yaml.example +0 -0
- {mcp_agent → fast_agent}/resources/examples/researcher/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/.env.sample +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/Makefile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/README.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/crab.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/docker-compose.yml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/Dockerfile +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/entrypoint.sh +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/mcp_server.py +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/mcp_server/pyproject.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_schema.json +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +0 -0
- {mcp_agent → fast_agent}/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/fastagent.config.yaml +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/graded_report.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.md +0 -0
- {mcp_agent → fast_agent}/resources/examples/workflows/short_story.txt +0 -0
- {mcp_agent → fast_agent/ui}/console.py +0 -0
- {mcp_agent/core → fast_agent/ui}/mermaid_utils.py +0 -0
- {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.57.dist-info → fast_agent_mcp-0.3.0.dist-info}/licenses/LICENSE +0 -0
mcp_agent/mcp_server_registry.py
DELETED
|
@@ -1,343 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This module defines a `ServerRegistry` class for managing MCP server configurations
|
|
3
|
-
and initialization logic.
|
|
4
|
-
|
|
5
|
-
The class loads server configurations from a YAML file,
|
|
6
|
-
supports dynamic registration of initialization hooks, and provides methods for
|
|
7
|
-
server initialization.
|
|
8
|
-
"""
|
|
9
|
-
|
|
10
|
-
from contextlib import asynccontextmanager
|
|
11
|
-
from datetime import timedelta
|
|
12
|
-
from typing import AsyncGenerator, Callable, Dict
|
|
13
|
-
|
|
14
|
-
from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
|
|
15
|
-
from mcp import ClientSession, stdio_client
|
|
16
|
-
from mcp.client.sse import sse_client
|
|
17
|
-
from mcp.client.stdio import (
|
|
18
|
-
StdioServerParameters,
|
|
19
|
-
get_default_environment,
|
|
20
|
-
)
|
|
21
|
-
from mcp.client.streamable_http import GetSessionIdCallback, streamablehttp_client
|
|
22
|
-
|
|
23
|
-
from mcp_agent.config import (
|
|
24
|
-
MCPServerAuthSettings,
|
|
25
|
-
MCPServerSettings,
|
|
26
|
-
Settings,
|
|
27
|
-
get_settings,
|
|
28
|
-
)
|
|
29
|
-
from mcp_agent.logging.logger import get_logger
|
|
30
|
-
from mcp_agent.mcp.hf_auth import add_hf_auth_header
|
|
31
|
-
from mcp_agent.mcp.logger_textio import get_stderr_handler
|
|
32
|
-
from mcp_agent.mcp.mcp_connection_manager import (
|
|
33
|
-
MCPConnectionManager,
|
|
34
|
-
_add_none_to_context,
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
logger = get_logger(__name__)
|
|
38
|
-
|
|
39
|
-
InitHookCallable = Callable[[ClientSession | None, MCPServerAuthSettings | None], bool]
|
|
40
|
-
"""
|
|
41
|
-
A type alias for an initialization hook function that is invoked after MCP server initialization.
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
session (ClientSession | None): The client session for the server connection.
|
|
45
|
-
auth (MCPServerAuthSettings | None): The authentication configuration for the server.
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
bool: Result of the post-init hook (false indicates failure).
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
class ServerRegistry:
|
|
53
|
-
"""
|
|
54
|
-
A registry for managing server configurations and initialization logic.
|
|
55
|
-
|
|
56
|
-
The `ServerRegistry` class is responsible for loading server configurations
|
|
57
|
-
from a YAML file, registering initialization hooks, initializing servers,
|
|
58
|
-
and executing post-initialization hooks dynamically.
|
|
59
|
-
|
|
60
|
-
Attributes:
|
|
61
|
-
config_path (str): Path to the YAML configuration file.
|
|
62
|
-
registry (Dict[str, MCPServerSettings]): Loaded server configurations.
|
|
63
|
-
init_hooks (Dict[str, InitHookCallable]): Registered initialization hooks.
|
|
64
|
-
"""
|
|
65
|
-
|
|
66
|
-
def __init__(self, config: Settings | None = None, config_path: str | None = None) -> None:
|
|
67
|
-
"""
|
|
68
|
-
Initialize the ServerRegistry with a configuration file.
|
|
69
|
-
|
|
70
|
-
Args:
|
|
71
|
-
config (Settings): The Settings object containing the server configurations.
|
|
72
|
-
config_path (str): Path to the YAML configuration file.
|
|
73
|
-
"""
|
|
74
|
-
if config is None:
|
|
75
|
-
self.registry = self.load_registry_from_file(config_path)
|
|
76
|
-
elif (
|
|
77
|
-
config.mcp is not None
|
|
78
|
-
and hasattr(config.mcp, "servers")
|
|
79
|
-
and config.mcp.servers is not None
|
|
80
|
-
):
|
|
81
|
-
# Ensure config.mcp exists, has a 'servers' attribute, and it's not None
|
|
82
|
-
self.registry = config.mcp.servers
|
|
83
|
-
else:
|
|
84
|
-
# Default to an empty dictionary if config.mcp is None or has no 'servers'
|
|
85
|
-
self.registry = {}
|
|
86
|
-
|
|
87
|
-
self.init_hooks: Dict[str, InitHookCallable] = {}
|
|
88
|
-
self.connection_manager = MCPConnectionManager(self)
|
|
89
|
-
|
|
90
|
-
def load_registry_from_file(
|
|
91
|
-
self, config_path: str | None = None
|
|
92
|
-
) -> Dict[str, MCPServerSettings]:
|
|
93
|
-
"""
|
|
94
|
-
Load the YAML configuration file and validate it.
|
|
95
|
-
|
|
96
|
-
Returns:
|
|
97
|
-
Dict[str, MCPServerSettings]: A dictionary of server configurations.
|
|
98
|
-
|
|
99
|
-
Raises:
|
|
100
|
-
ValueError: If the configuration is invalid.
|
|
101
|
-
"""
|
|
102
|
-
servers = {}
|
|
103
|
-
|
|
104
|
-
settings = get_settings(config_path)
|
|
105
|
-
|
|
106
|
-
if (
|
|
107
|
-
settings.mcp is not None
|
|
108
|
-
and hasattr(settings.mcp, "servers")
|
|
109
|
-
and settings.mcp.servers is not None
|
|
110
|
-
):
|
|
111
|
-
return settings.mcp.servers
|
|
112
|
-
|
|
113
|
-
return servers
|
|
114
|
-
|
|
115
|
-
@asynccontextmanager
|
|
116
|
-
async def start_server(
|
|
117
|
-
self,
|
|
118
|
-
server_name: str,
|
|
119
|
-
client_session_factory: Callable[
|
|
120
|
-
[
|
|
121
|
-
MemoryObjectReceiveStream,
|
|
122
|
-
MemoryObjectSendStream,
|
|
123
|
-
timedelta | None,
|
|
124
|
-
GetSessionIdCallback | None,
|
|
125
|
-
],
|
|
126
|
-
ClientSession,
|
|
127
|
-
] = ClientSession,
|
|
128
|
-
) -> AsyncGenerator[ClientSession, None]:
|
|
129
|
-
"""
|
|
130
|
-
Starts the server process based on its configuration. To initialize, call initialize_server
|
|
131
|
-
|
|
132
|
-
Args:
|
|
133
|
-
server_name (str): The name of the server to initialize.
|
|
134
|
-
|
|
135
|
-
Returns:
|
|
136
|
-
StdioServerParameters: The server parameters for stdio transport.
|
|
137
|
-
|
|
138
|
-
Raises:
|
|
139
|
-
ValueError: If the server is not found or has an unsupported transport.
|
|
140
|
-
"""
|
|
141
|
-
if server_name not in self.registry:
|
|
142
|
-
raise ValueError(f"Server '{server_name}' not found in registry.")
|
|
143
|
-
|
|
144
|
-
config = self.registry[server_name]
|
|
145
|
-
|
|
146
|
-
read_timeout_seconds = (
|
|
147
|
-
timedelta(config.read_timeout_seconds) if config.read_timeout_seconds else None
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
if config.transport == "stdio":
|
|
151
|
-
if not config.command or not config.args:
|
|
152
|
-
raise ValueError(
|
|
153
|
-
f"Command and args are required for stdio transport: {server_name}"
|
|
154
|
-
)
|
|
155
|
-
|
|
156
|
-
server_params = StdioServerParameters(
|
|
157
|
-
command=config.command,
|
|
158
|
-
args=config.args,
|
|
159
|
-
env={**get_default_environment(), **(config.env or {})},
|
|
160
|
-
cwd=config.cwd,
|
|
161
|
-
)
|
|
162
|
-
|
|
163
|
-
# Create a stderr handler that logs to our application logger
|
|
164
|
-
async with _add_none_to_context(
|
|
165
|
-
stdio_client(server_params, errlog=get_stderr_handler(server_name))
|
|
166
|
-
) as (
|
|
167
|
-
read_stream,
|
|
168
|
-
write_stream,
|
|
169
|
-
_,
|
|
170
|
-
):
|
|
171
|
-
session = client_session_factory(
|
|
172
|
-
read_stream,
|
|
173
|
-
write_stream,
|
|
174
|
-
read_timeout_seconds,
|
|
175
|
-
server_config=config,
|
|
176
|
-
)
|
|
177
|
-
async with session:
|
|
178
|
-
logger.info(f"{server_name}: Connected to server using stdio transport.")
|
|
179
|
-
try:
|
|
180
|
-
yield session
|
|
181
|
-
finally:
|
|
182
|
-
logger.debug(f"{server_name}: Closed session to server")
|
|
183
|
-
|
|
184
|
-
elif config.transport == "sse":
|
|
185
|
-
if not config.url:
|
|
186
|
-
raise ValueError(f"URL is required for SSE transport: {server_name}")
|
|
187
|
-
|
|
188
|
-
# Apply HuggingFace authentication if appropriate
|
|
189
|
-
headers = add_hf_auth_header(config.url, config.headers)
|
|
190
|
-
|
|
191
|
-
# Use sse_client to get the read and write streams
|
|
192
|
-
async with _add_none_to_context(
|
|
193
|
-
sse_client(
|
|
194
|
-
config.url,
|
|
195
|
-
headers,
|
|
196
|
-
sse_read_timeout=config.read_transport_sse_timeout_seconds,
|
|
197
|
-
)
|
|
198
|
-
) as (read_stream, write_stream, _):
|
|
199
|
-
session = client_session_factory(
|
|
200
|
-
read_stream,
|
|
201
|
-
write_stream,
|
|
202
|
-
read_timeout_seconds,
|
|
203
|
-
server_config=config,
|
|
204
|
-
)
|
|
205
|
-
async with session:
|
|
206
|
-
logger.info(f"{server_name}: Connected to server using SSE transport.")
|
|
207
|
-
try:
|
|
208
|
-
yield session
|
|
209
|
-
finally:
|
|
210
|
-
logger.debug(f"{server_name}: Closed session to server")
|
|
211
|
-
elif config.transport == "http":
|
|
212
|
-
if not config.url:
|
|
213
|
-
raise ValueError(f"URL is required for HTTP transport: {server_name}")
|
|
214
|
-
|
|
215
|
-
# Apply HuggingFace authentication if appropriate
|
|
216
|
-
headers = add_hf_auth_header(config.url, config.headers)
|
|
217
|
-
|
|
218
|
-
async with streamablehttp_client(config.url, headers) as (
|
|
219
|
-
read_stream,
|
|
220
|
-
write_stream,
|
|
221
|
-
_,
|
|
222
|
-
):
|
|
223
|
-
session = client_session_factory(
|
|
224
|
-
read_stream,
|
|
225
|
-
write_stream,
|
|
226
|
-
read_timeout_seconds,
|
|
227
|
-
server_config=config,
|
|
228
|
-
)
|
|
229
|
-
async with session:
|
|
230
|
-
logger.info(f"{server_name}: Connected to server using HTTP transport.")
|
|
231
|
-
try:
|
|
232
|
-
yield session
|
|
233
|
-
finally:
|
|
234
|
-
logger.debug(f"{server_name}: Closed session to server")
|
|
235
|
-
|
|
236
|
-
# Unsupported transport
|
|
237
|
-
else:
|
|
238
|
-
raise ValueError(f"Unsupported transport: {config.transport}")
|
|
239
|
-
|
|
240
|
-
@asynccontextmanager
|
|
241
|
-
async def initialize_server(
|
|
242
|
-
self,
|
|
243
|
-
server_name: str,
|
|
244
|
-
client_session_factory: Callable[
|
|
245
|
-
[
|
|
246
|
-
MemoryObjectReceiveStream,
|
|
247
|
-
MemoryObjectSendStream,
|
|
248
|
-
timedelta | None,
|
|
249
|
-
GetSessionIdCallback,
|
|
250
|
-
],
|
|
251
|
-
ClientSession,
|
|
252
|
-
] = ClientSession,
|
|
253
|
-
init_hook: InitHookCallable = None,
|
|
254
|
-
) -> AsyncGenerator[ClientSession, None]:
|
|
255
|
-
"""
|
|
256
|
-
Initialize a server based on its configuration.
|
|
257
|
-
After initialization, also calls any registered or provided initialization hook for the server.
|
|
258
|
-
|
|
259
|
-
Args:
|
|
260
|
-
server_name (str): The name of the server to initialize.
|
|
261
|
-
init_hook (InitHookCallable): Optional initialization hook function to call after initialization.
|
|
262
|
-
|
|
263
|
-
Returns:
|
|
264
|
-
StdioServerParameters: The server parameters for stdio transport.
|
|
265
|
-
|
|
266
|
-
Raises:
|
|
267
|
-
ValueError: If the server is not found or has an unsupported transport.
|
|
268
|
-
"""
|
|
269
|
-
|
|
270
|
-
if server_name not in self.registry:
|
|
271
|
-
raise ValueError(f"Server '{server_name}' not found in registry.")
|
|
272
|
-
|
|
273
|
-
config = self.registry[server_name]
|
|
274
|
-
|
|
275
|
-
async with self.start_server(
|
|
276
|
-
server_name, client_session_factory=client_session_factory
|
|
277
|
-
) as session:
|
|
278
|
-
try:
|
|
279
|
-
logger.info(f"{server_name}: Initializing server...")
|
|
280
|
-
await session.initialize()
|
|
281
|
-
logger.info(f"{server_name}: Initialized.")
|
|
282
|
-
|
|
283
|
-
intialization_callback = (
|
|
284
|
-
init_hook if init_hook is not None else self.init_hooks.get(server_name)
|
|
285
|
-
)
|
|
286
|
-
|
|
287
|
-
if intialization_callback:
|
|
288
|
-
logger.info(f"{server_name}: Executing init hook")
|
|
289
|
-
intialization_callback(session, config.auth)
|
|
290
|
-
|
|
291
|
-
logger.info(f"{server_name}: Up and running!")
|
|
292
|
-
yield session
|
|
293
|
-
finally:
|
|
294
|
-
logger.info(f"{server_name}: Ending server session.")
|
|
295
|
-
|
|
296
|
-
def register_init_hook(self, server_name: str, hook: InitHookCallable) -> None:
|
|
297
|
-
"""
|
|
298
|
-
Register an initialization hook for a specific server. This will get called
|
|
299
|
-
after the server is initialized.
|
|
300
|
-
|
|
301
|
-
Args:
|
|
302
|
-
server_name (str): The name of the server.
|
|
303
|
-
hook (callable): The initialization function to register.
|
|
304
|
-
"""
|
|
305
|
-
if server_name not in self.registry:
|
|
306
|
-
raise ValueError(f"Server '{server_name}' not found in registry.")
|
|
307
|
-
|
|
308
|
-
self.init_hooks[server_name] = hook
|
|
309
|
-
|
|
310
|
-
def execute_init_hook(self, server_name: str, session=None) -> bool:
|
|
311
|
-
"""
|
|
312
|
-
Execute the initialization hook for a specific server.
|
|
313
|
-
|
|
314
|
-
Args:
|
|
315
|
-
server_name (str): The name of the server.
|
|
316
|
-
session: The session object to pass to the initialization hook.
|
|
317
|
-
"""
|
|
318
|
-
if server_name in self.init_hooks:
|
|
319
|
-
hook = self.init_hooks[server_name]
|
|
320
|
-
config = self.registry[server_name]
|
|
321
|
-
logger.info(f"Executing init hook for '{server_name}'")
|
|
322
|
-
return hook(session, config.auth)
|
|
323
|
-
else:
|
|
324
|
-
logger.info(f"No init hook registered for '{server_name}'")
|
|
325
|
-
|
|
326
|
-
def get_server_config(self, server_name: str) -> MCPServerSettings | None:
|
|
327
|
-
"""
|
|
328
|
-
Get the configuration for a specific server.
|
|
329
|
-
|
|
330
|
-
Args:
|
|
331
|
-
server_name (str): The name of the server.
|
|
332
|
-
|
|
333
|
-
Returns:
|
|
334
|
-
MCPServerSettings: The server configuration.
|
|
335
|
-
"""
|
|
336
|
-
|
|
337
|
-
server_config = self.registry.get(server_name)
|
|
338
|
-
if server_config is None:
|
|
339
|
-
logger.warning(f"Server '{server_name}' not found in registry.")
|
|
340
|
-
return None
|
|
341
|
-
elif server_config.name is None:
|
|
342
|
-
server_config.name = server_name
|
|
343
|
-
return server_config
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
from dataclasses import dataclass, field
|
|
2
|
-
from typing import Any, Dict, Optional
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
@dataclass
|
|
6
|
-
class ToolDefinition:
|
|
7
|
-
"""
|
|
8
|
-
Represents a definition of a tool available to the agent.
|
|
9
|
-
"""
|
|
10
|
-
|
|
11
|
-
name: str
|
|
12
|
-
description: Optional[str] = None
|
|
13
|
-
inputSchema: Dict[str, Any] = field(default_factory=dict)
|
|
14
|
-
# Add other relevant fields if necessary based on how tools are defined in fast-agent
|