fast-agent-mcp 0.2.27__py3-none-any.whl → 0.2.28__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.
- {fast_agent_mcp-0.2.27.dist-info → fast_agent_mcp-0.2.28.dist-info}/METADATA +3 -1
- {fast_agent_mcp-0.2.27.dist-info → fast_agent_mcp-0.2.28.dist-info}/RECORD +24 -19
- mcp_agent/agents/agent.py +1 -17
- mcp_agent/agents/base_agent.py +2 -0
- mcp_agent/config.py +3 -0
- mcp_agent/context.py +2 -0
- mcp_agent/core/agent_app.py +7 -2
- mcp_agent/core/interactive_prompt.py +58 -51
- mcp_agent/llm/augmented_llm_slow.py +42 -0
- mcp_agent/llm/model_factory.py +74 -37
- mcp_agent/llm/provider_types.py +4 -3
- mcp_agent/llm/providers/augmented_llm_google_native.py +459 -0
- mcp_agent/llm/providers/{augmented_llm_google.py → augmented_llm_google_oai.py} +2 -2
- mcp_agent/llm/providers/google_converter.py +361 -0
- mcp_agent/mcp/helpers/server_config_helpers.py +23 -0
- mcp_agent/mcp/mcp_agent_client_session.py +51 -24
- mcp_agent/mcp/mcp_aggregator.py +18 -3
- mcp_agent/mcp/mcp_connection_manager.py +6 -5
- mcp_agent/mcp/sampling.py +40 -10
- mcp_agent/mcp_server_registry.py +15 -4
- mcp_agent/tools/tool_definition.py +14 -0
- {fast_agent_mcp-0.2.27.dist-info → fast_agent_mcp-0.2.28.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.27.dist-info → fast_agent_mcp-0.2.28.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.2.27.dist-info → fast_agent_mcp-0.2.28.dist-info}/licenses/LICENSE +0 -0
mcp_agent/llm/model_factory.py
CHANGED
@@ -8,12 +8,14 @@ from mcp_agent.core.exceptions import ModelConfigError
|
|
8
8
|
from mcp_agent.core.request_params import RequestParams
|
9
9
|
from mcp_agent.llm.augmented_llm_passthrough import PassthroughLLM
|
10
10
|
from mcp_agent.llm.augmented_llm_playback import PlaybackLLM
|
11
|
+
from mcp_agent.llm.augmented_llm_slow import SlowLLM
|
11
12
|
from mcp_agent.llm.provider_types import Provider
|
12
13
|
from mcp_agent.llm.providers.augmented_llm_anthropic import AnthropicAugmentedLLM
|
13
14
|
from mcp_agent.llm.providers.augmented_llm_azure import AzureOpenAIAugmentedLLM
|
14
15
|
from mcp_agent.llm.providers.augmented_llm_deepseek import DeepSeekAugmentedLLM
|
15
16
|
from mcp_agent.llm.providers.augmented_llm_generic import GenericAugmentedLLM
|
16
|
-
from mcp_agent.llm.providers.
|
17
|
+
from mcp_agent.llm.providers.augmented_llm_google_native import GoogleNativeAugmentedLLM
|
18
|
+
from mcp_agent.llm.providers.augmented_llm_google_oai import GoogleOaiAugmentedLLM
|
17
19
|
from mcp_agent.llm.providers.augmented_llm_openai import OpenAIAugmentedLLM
|
18
20
|
from mcp_agent.llm.providers.augmented_llm_openrouter import OpenRouterAugmentedLLM
|
19
21
|
from mcp_agent.llm.providers.augmented_llm_tensorzero import TensorZeroAugmentedLLM
|
@@ -28,9 +30,13 @@ LLMClass = Union[
|
|
28
30
|
Type[OpenAIAugmentedLLM],
|
29
31
|
Type[PassthroughLLM],
|
30
32
|
Type[PlaybackLLM],
|
33
|
+
Type[SlowLLM],
|
31
34
|
Type[DeepSeekAugmentedLLM],
|
32
35
|
Type[OpenRouterAugmentedLLM],
|
33
36
|
Type[TensorZeroAugmentedLLM],
|
37
|
+
Type[GoogleNativeAugmentedLLM],
|
38
|
+
Type[GenericAugmentedLLM],
|
39
|
+
Type[AzureOpenAIAugmentedLLM],
|
34
40
|
]
|
35
41
|
|
36
42
|
|
@@ -60,13 +66,16 @@ class ModelFactory:
|
|
60
66
|
"high": ReasoningEffort.HIGH,
|
61
67
|
}
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
69
|
+
"""
|
70
|
+
TODO -- add context window size information for display/management
|
71
|
+
TODO -- add audio supporting got-4o-audio-preview
|
72
|
+
TODO -- bring model parameter configuration here
|
73
|
+
Mapping of model names to their default providers
|
74
|
+
"""
|
67
75
|
DEFAULT_PROVIDERS = {
|
68
76
|
"passthrough": Provider.FAST_AGENT,
|
69
77
|
"playback": Provider.FAST_AGENT,
|
78
|
+
"slow": Provider.FAST_AGENT,
|
70
79
|
"gpt-4o": Provider.OPENAI,
|
71
80
|
"gpt-4o-mini": Provider.OPENAI,
|
72
81
|
"gpt-4.1": Provider.OPENAI,
|
@@ -91,7 +100,9 @@ class ModelFactory:
|
|
91
100
|
"claude-sonnet-4-20250514": Provider.ANTHROPIC,
|
92
101
|
"claude-sonnet-4-0": Provider.ANTHROPIC,
|
93
102
|
"deepseek-chat": Provider.DEEPSEEK,
|
94
|
-
|
103
|
+
"gemini-2.0-flash": Provider.GOOGLE,
|
104
|
+
"gemini-2.5-flash-preview-05-20": Provider.GOOGLE,
|
105
|
+
"gemini-2.5-pro-preview-05-06": Provider.GOOGLE,
|
95
106
|
}
|
96
107
|
|
97
108
|
MODEL_ALIASES = {
|
@@ -108,6 +119,9 @@ class ModelFactory:
|
|
108
119
|
"opus3": "claude-3-opus-latest",
|
109
120
|
"deepseekv3": "deepseek-chat",
|
110
121
|
"deepseek": "deepseek-chat",
|
122
|
+
"gemini2": "gemini-2.0-flash",
|
123
|
+
"gemini25": "gemini-2.5-flash-preview-05-20",
|
124
|
+
"gemini25pro": "gemini-2.5-pro-preview-05-06",
|
111
125
|
}
|
112
126
|
|
113
127
|
# Mapping of providers to their LLM classes
|
@@ -117,7 +131,8 @@ class ModelFactory:
|
|
117
131
|
Provider.FAST_AGENT: PassthroughLLM,
|
118
132
|
Provider.DEEPSEEK: DeepSeekAugmentedLLM,
|
119
133
|
Provider.GENERIC: GenericAugmentedLLM,
|
120
|
-
Provider.
|
134
|
+
Provider.GOOGLE_OAI: GoogleOaiAugmentedLLM,
|
135
|
+
Provider.GOOGLE: GoogleNativeAugmentedLLM,
|
121
136
|
Provider.OPENROUTER: OpenRouterAugmentedLLM,
|
122
137
|
Provider.TENSORZERO: TensorZeroAugmentedLLM,
|
123
138
|
Provider.AZURE: AzureOpenAIAugmentedLLM,
|
@@ -127,48 +142,66 @@ class ModelFactory:
|
|
127
142
|
# This overrides the provider-based class selection
|
128
143
|
MODEL_SPECIFIC_CLASSES: Dict[str, LLMClass] = {
|
129
144
|
"playback": PlaybackLLM,
|
145
|
+
"slow": SlowLLM,
|
130
146
|
}
|
131
147
|
|
132
148
|
@classmethod
|
133
149
|
def parse_model_string(cls, model_string: str) -> ModelConfig:
|
134
150
|
"""Parse a model string into a ModelConfig object"""
|
135
|
-
# Check if model string is an alias
|
136
151
|
model_string = cls.MODEL_ALIASES.get(model_string, model_string)
|
137
152
|
parts = model_string.split(".")
|
138
153
|
|
139
|
-
#
|
140
|
-
model_parts = parts.copy()
|
154
|
+
model_name_str = model_string # Default full string as model name initially
|
141
155
|
provider = None
|
142
156
|
reasoning_effort = None
|
157
|
+
parts_for_provider_model = []
|
143
158
|
|
144
|
-
# Check
|
159
|
+
# Check for reasoning effort first (last part)
|
145
160
|
if len(parts) > 1 and parts[-1].lower() in cls.EFFORT_MAP:
|
146
161
|
reasoning_effort = cls.EFFORT_MAP[parts[-1].lower()]
|
147
|
-
|
162
|
+
# Remove effort from parts list for provider/model name determination
|
163
|
+
parts_for_provider_model = parts[:-1]
|
164
|
+
else:
|
165
|
+
parts_for_provider_model = parts[:]
|
166
|
+
|
167
|
+
# Try to match longest possible provider string
|
168
|
+
identified_provider_parts = 0 # How many parts belong to the provider string
|
169
|
+
|
170
|
+
if len(parts_for_provider_model) >= 2:
|
171
|
+
potential_provider_str = f"{parts_for_provider_model[0]}.{parts_for_provider_model[1]}"
|
172
|
+
if any(p.value == potential_provider_str for p in Provider):
|
173
|
+
provider = Provider(potential_provider_str)
|
174
|
+
identified_provider_parts = 2
|
175
|
+
|
176
|
+
if provider is None and len(parts_for_provider_model) >= 1:
|
177
|
+
potential_provider_str = parts_for_provider_model[0]
|
178
|
+
if any(p.value == potential_provider_str for p in Provider):
|
179
|
+
provider = Provider(potential_provider_str)
|
180
|
+
identified_provider_parts = 1
|
181
|
+
|
182
|
+
# Construct model_name from remaining parts
|
183
|
+
if identified_provider_parts > 0:
|
184
|
+
model_name_str = ".".join(parts_for_provider_model[identified_provider_parts:])
|
185
|
+
else:
|
186
|
+
# If no provider prefix was matched, the whole string (after effort removal) is the model name
|
187
|
+
model_name_str = ".".join(parts_for_provider_model)
|
148
188
|
|
149
|
-
#
|
150
|
-
if
|
151
|
-
|
152
|
-
if
|
153
|
-
|
154
|
-
|
189
|
+
# If provider still None, try to get from DEFAULT_PROVIDERS using the model_name_str
|
190
|
+
if provider is None:
|
191
|
+
provider = cls.DEFAULT_PROVIDERS.get(model_name_str)
|
192
|
+
if provider is None:
|
193
|
+
raise ModelConfigError(
|
194
|
+
f"Unknown model or provider for: {model_string}. Model name parsed as '{model_name_str}'"
|
195
|
+
)
|
155
196
|
|
156
|
-
if provider == Provider.TENSORZERO and not
|
197
|
+
if provider == Provider.TENSORZERO and not model_name_str:
|
157
198
|
raise ModelConfigError(
|
158
199
|
f"TensorZero provider requires a function name after the provider "
|
159
200
|
f"(e.g., tensorzero.my-function), got: {model_string}"
|
160
201
|
)
|
161
|
-
# Join remaining parts as model name
|
162
|
-
model_name = ".".join(model_parts)
|
163
|
-
|
164
|
-
# If no provider was found in the string, look it up in defaults
|
165
|
-
if provider is None:
|
166
|
-
provider = cls.DEFAULT_PROVIDERS.get(model_name)
|
167
|
-
if provider is None:
|
168
|
-
raise ModelConfigError(f"Unknown model: {model_name}")
|
169
202
|
|
170
203
|
return ModelConfig(
|
171
|
-
provider=provider, model_name=
|
204
|
+
provider=provider, model_name=model_name_str, reasoning_effort=reasoning_effort
|
172
205
|
)
|
173
206
|
|
174
207
|
@classmethod
|
@@ -185,33 +218,37 @@ class ModelFactory:
|
|
185
218
|
Returns:
|
186
219
|
A callable that takes an agent parameter and returns an LLM instance
|
187
220
|
"""
|
188
|
-
# Parse configuration up front
|
189
221
|
config = cls.parse_model_string(model_string)
|
222
|
+
|
223
|
+
# Ensure provider is valid before trying to access PROVIDER_CLASSES with it
|
224
|
+
if (
|
225
|
+
config.provider not in cls.PROVIDER_CLASSES
|
226
|
+
and config.model_name not in cls.MODEL_SPECIFIC_CLASSES
|
227
|
+
):
|
228
|
+
# This check is important if a provider (like old GOOGLE) is commented out from PROVIDER_CLASSES
|
229
|
+
raise ModelConfigError(
|
230
|
+
f"Provider '{config.provider}' not configured in PROVIDER_CLASSES and model '{config.model_name}' not in MODEL_SPECIFIC_CLASSES."
|
231
|
+
)
|
232
|
+
|
190
233
|
if config.model_name in cls.MODEL_SPECIFIC_CLASSES:
|
191
234
|
llm_class = cls.MODEL_SPECIFIC_CLASSES[config.model_name]
|
192
235
|
else:
|
236
|
+
# This line is now safer due to the check above
|
193
237
|
llm_class = cls.PROVIDER_CLASSES[config.provider]
|
194
238
|
|
195
|
-
# Create a factory function matching the updated attach_llm protocol
|
196
239
|
def factory(
|
197
240
|
agent: Agent, request_params: Optional[RequestParams] = None, **kwargs
|
198
241
|
) -> AugmentedLLMProtocol:
|
199
|
-
# Create base params with parsed model name
|
200
242
|
base_params = RequestParams()
|
201
|
-
base_params.model = config.model_name
|
202
|
-
|
203
|
-
# Add reasoning effort if available
|
243
|
+
base_params.model = config.model_name
|
204
244
|
if config.reasoning_effort:
|
205
245
|
kwargs["reasoning_effort"] = config.reasoning_effort.value
|
206
|
-
|
207
|
-
# Forward all arguments to LLM constructor
|
208
246
|
llm_args = {
|
209
247
|
"agent": agent,
|
210
248
|
"model": config.model_name,
|
211
249
|
"request_params": request_params,
|
212
250
|
**kwargs,
|
213
251
|
}
|
214
|
-
|
215
252
|
llm: AugmentedLLMProtocol = llm_class(**llm_args)
|
216
253
|
return llm
|
217
254
|
|
mcp_agent/llm/provider_types.py
CHANGED
@@ -9,11 +9,12 @@ class Provider(Enum):
|
|
9
9
|
"""Supported LLM providers"""
|
10
10
|
|
11
11
|
ANTHROPIC = "anthropic"
|
12
|
-
OPENAI = "openai"
|
13
|
-
FAST_AGENT = "fast-agent"
|
14
|
-
GOOGLE = "google"
|
15
12
|
DEEPSEEK = "deepseek"
|
13
|
+
FAST_AGENT = "fast-agent"
|
16
14
|
GENERIC = "generic"
|
15
|
+
GOOGLE_OAI = "googleoai" # For Google through OpenAI libraries
|
16
|
+
GOOGLE = "google" # For Google GenAI native library
|
17
|
+
OPENAI = "openai"
|
17
18
|
OPENROUTER = "openrouter"
|
18
19
|
TENSORZERO = "tensorzero" # For TensorZero Gateway
|
19
20
|
AZURE = "azure" # Azure OpenAI Service
|