fast-agent-mcp 0.1.13__py3-none-any.whl → 0.2.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.
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/METADATA +3 -4
- fast_agent_mcp-0.2.0.dist-info/RECORD +123 -0
- mcp_agent/__init__.py +75 -0
- mcp_agent/agents/agent.py +59 -371
- mcp_agent/agents/base_agent.py +522 -0
- mcp_agent/agents/workflow/__init__.py +1 -0
- mcp_agent/agents/workflow/chain_agent.py +173 -0
- mcp_agent/agents/workflow/evaluator_optimizer.py +362 -0
- mcp_agent/agents/workflow/orchestrator_agent.py +591 -0
- mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_models.py +27 -11
- mcp_agent/agents/workflow/parallel_agent.py +182 -0
- mcp_agent/agents/workflow/router_agent.py +307 -0
- mcp_agent/app.py +3 -1
- mcp_agent/cli/commands/bootstrap.py +18 -7
- mcp_agent/cli/commands/setup.py +12 -4
- mcp_agent/cli/main.py +1 -1
- mcp_agent/cli/terminal.py +1 -1
- mcp_agent/config.py +24 -35
- mcp_agent/context.py +3 -1
- mcp_agent/context_dependent.py +3 -1
- mcp_agent/core/agent_types.py +10 -7
- mcp_agent/core/direct_agent_app.py +179 -0
- mcp_agent/core/direct_decorators.py +443 -0
- mcp_agent/core/direct_factory.py +476 -0
- mcp_agent/core/enhanced_prompt.py +15 -20
- mcp_agent/core/fastagent.py +151 -337
- mcp_agent/core/interactive_prompt.py +424 -0
- mcp_agent/core/mcp_content.py +19 -11
- mcp_agent/core/prompt.py +6 -2
- mcp_agent/core/validation.py +89 -16
- mcp_agent/executor/decorator_registry.py +6 -2
- mcp_agent/executor/temporal.py +35 -11
- mcp_agent/executor/workflow_signal.py +8 -2
- mcp_agent/human_input/handler.py +3 -1
- mcp_agent/llm/__init__.py +2 -0
- mcp_agent/{workflows/llm → llm}/augmented_llm.py +131 -256
- mcp_agent/{workflows/llm → llm}/augmented_llm_passthrough.py +35 -107
- mcp_agent/llm/augmented_llm_playback.py +83 -0
- mcp_agent/{workflows/llm → llm}/model_factory.py +26 -8
- mcp_agent/llm/providers/__init__.py +8 -0
- mcp_agent/{workflows/llm → llm/providers}/anthropic_utils.py +5 -1
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_anthropic.py +37 -141
- mcp_agent/llm/providers/augmented_llm_deepseek.py +53 -0
- mcp_agent/{workflows/llm → llm/providers}/augmented_llm_openai.py +112 -148
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_anthropic.py +78 -35
- mcp_agent/{workflows/llm → llm}/providers/multipart_converter_openai.py +73 -44
- mcp_agent/{workflows/llm → llm}/providers/openai_multipart.py +18 -4
- mcp_agent/{workflows/llm → llm/providers}/openai_utils.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_anthropic.py +3 -3
- mcp_agent/{workflows/llm → llm}/providers/sampling_converter_openai.py +3 -3
- mcp_agent/{workflows/llm → llm}/sampling_converter.py +0 -21
- mcp_agent/{workflows/llm → llm}/sampling_format_converter.py +16 -1
- mcp_agent/logging/logger.py +2 -2
- mcp_agent/mcp/gen_client.py +9 -3
- mcp_agent/mcp/interfaces.py +67 -45
- mcp_agent/mcp/logger_textio.py +97 -0
- mcp_agent/mcp/mcp_agent_client_session.py +12 -4
- mcp_agent/mcp/mcp_agent_server.py +3 -1
- mcp_agent/mcp/mcp_aggregator.py +124 -93
- mcp_agent/mcp/mcp_connection_manager.py +21 -7
- mcp_agent/mcp/prompt_message_multipart.py +59 -1
- mcp_agent/mcp/prompt_render.py +77 -0
- mcp_agent/mcp/prompt_serialization.py +20 -13
- mcp_agent/mcp/prompts/prompt_constants.py +18 -0
- mcp_agent/mcp/prompts/prompt_helpers.py +327 -0
- mcp_agent/mcp/prompts/prompt_load.py +15 -5
- mcp_agent/mcp/prompts/prompt_server.py +154 -87
- mcp_agent/mcp/prompts/prompt_template.py +26 -35
- mcp_agent/mcp/resource_utils.py +3 -1
- mcp_agent/mcp/sampling.py +24 -15
- mcp_agent/mcp_server/agent_server.py +8 -5
- mcp_agent/mcp_server_registry.py +22 -9
- mcp_agent/resources/examples/{workflows → in_dev}/agent_build.py +1 -1
- mcp_agent/resources/examples/{data-analysis → in_dev}/slides.py +1 -1
- mcp_agent/resources/examples/internal/agent.py +4 -2
- mcp_agent/resources/examples/internal/fastagent.config.yaml +8 -2
- mcp_agent/resources/examples/prompting/image_server.py +3 -1
- mcp_agent/resources/examples/prompting/work_with_image.py +19 -0
- mcp_agent/ui/console_display.py +27 -7
- fast_agent_mcp-0.1.13.dist-info/RECORD +0 -164
- mcp_agent/core/agent_app.py +0 -570
- mcp_agent/core/agent_utils.py +0 -69
- mcp_agent/core/decorators.py +0 -448
- mcp_agent/core/factory.py +0 -422
- mcp_agent/core/proxies.py +0 -278
- mcp_agent/core/types.py +0 -22
- mcp_agent/eval/__init__.py +0 -0
- mcp_agent/mcp/stdio.py +0 -114
- mcp_agent/resources/examples/data-analysis/analysis-campaign.py +0 -188
- mcp_agent/resources/examples/data-analysis/analysis.py +0 -65
- mcp_agent/resources/examples/data-analysis/fastagent.config.yaml +0 -41
- mcp_agent/resources/examples/data-analysis/mount-point/WA_Fn-UseC_-HR-Employee-Attrition.csv +0 -1471
- mcp_agent/resources/examples/mcp_researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/fastagent.config.yaml +0 -66
- mcp_agent/resources/examples/researcher/researcher-eval.py +0 -53
- mcp_agent/resources/examples/researcher/researcher-imp.py +0 -189
- mcp_agent/resources/examples/researcher/researcher.py +0 -39
- mcp_agent/resources/examples/workflows/chaining.py +0 -45
- mcp_agent/resources/examples/workflows/evaluator.py +0 -79
- mcp_agent/resources/examples/workflows/fastagent.config.yaml +0 -24
- mcp_agent/resources/examples/workflows/human_input.py +0 -26
- mcp_agent/resources/examples/workflows/orchestrator.py +0 -74
- mcp_agent/resources/examples/workflows/parallel.py +0 -79
- mcp_agent/resources/examples/workflows/router.py +0 -54
- mcp_agent/resources/examples/workflows/sse.py +0 -23
- mcp_agent/telemetry/__init__.py +0 -0
- mcp_agent/telemetry/usage_tracking.py +0 -19
- mcp_agent/workflows/__init__.py +0 -0
- mcp_agent/workflows/embedding/__init__.py +0 -0
- mcp_agent/workflows/embedding/embedding_base.py +0 -58
- mcp_agent/workflows/embedding/embedding_cohere.py +0 -49
- mcp_agent/workflows/embedding/embedding_openai.py +0 -37
- mcp_agent/workflows/evaluator_optimizer/__init__.py +0 -0
- mcp_agent/workflows/evaluator_optimizer/evaluator_optimizer.py +0 -447
- mcp_agent/workflows/intent_classifier/__init__.py +0 -0
- mcp_agent/workflows/intent_classifier/intent_classifier_base.py +0 -117
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding.py +0 -130
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_cohere.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_embedding_openai.py +0 -41
- mcp_agent/workflows/intent_classifier/intent_classifier_llm.py +0 -150
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_anthropic.py +0 -60
- mcp_agent/workflows/intent_classifier/intent_classifier_llm_openai.py +0 -58
- mcp_agent/workflows/llm/__init__.py +0 -0
- mcp_agent/workflows/llm/augmented_llm_playback.py +0 -111
- mcp_agent/workflows/llm/providers/__init__.py +0 -8
- mcp_agent/workflows/orchestrator/__init__.py +0 -0
- mcp_agent/workflows/orchestrator/orchestrator.py +0 -535
- mcp_agent/workflows/parallel/__init__.py +0 -0
- mcp_agent/workflows/parallel/fan_in.py +0 -320
- mcp_agent/workflows/parallel/fan_out.py +0 -181
- mcp_agent/workflows/parallel/parallel_llm.py +0 -149
- mcp_agent/workflows/router/__init__.py +0 -0
- mcp_agent/workflows/router/router_base.py +0 -338
- mcp_agent/workflows/router/router_embedding.py +0 -226
- mcp_agent/workflows/router/router_embedding_cohere.py +0 -59
- mcp_agent/workflows/router/router_embedding_openai.py +0 -59
- mcp_agent/workflows/router/router_llm.py +0 -304
- mcp_agent/workflows/swarm/__init__.py +0 -0
- mcp_agent/workflows/swarm/swarm.py +0 -292
- mcp_agent/workflows/swarm/swarm_anthropic.py +0 -42
- mcp_agent/workflows/swarm/swarm_openai.py +0 -41
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.1.13.dist-info → fast_agent_mcp-0.2.0.dist-info}/licenses/LICENSE +0 -0
- /mcp_agent/{workflows/orchestrator → agents/workflow}/orchestrator_prompts.py +0 -0
- /mcp_agent/{workflows/llm → llm}/memory.py +0 -0
- /mcp_agent/{workflows/llm → llm}/prompt_utils.py +0 -0
@@ -13,7 +13,9 @@ class DecoratorRegistry:
|
|
13
13
|
|
14
14
|
def __init__(self) -> None:
|
15
15
|
self._workflow_defn_decorators: Dict[str, Callable[[Type], Type]] = {}
|
16
|
-
self._workflow_run_decorators: Dict[
|
16
|
+
self._workflow_run_decorators: Dict[
|
17
|
+
str, Callable[[Callable[..., R]], Callable[..., R]]
|
18
|
+
] = {}
|
17
19
|
|
18
20
|
def register_workflow_defn_decorator(
|
19
21
|
self,
|
@@ -60,7 +62,9 @@ class DecoratorRegistry:
|
|
60
62
|
)
|
61
63
|
self._workflow_run_decorators[executor_name] = decorator
|
62
64
|
|
63
|
-
def get_workflow_run_decorator(
|
65
|
+
def get_workflow_run_decorator(
|
66
|
+
self, executor_name: str
|
67
|
+
) -> Callable[[Callable[..., R]], Callable[..., R]]:
|
64
68
|
"""
|
65
69
|
Retrieves a workflow run decorator for a given executor.
|
66
70
|
|
mcp_agent/executor/temporal.py
CHANGED
@@ -43,7 +43,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
|
|
43
43
|
|
44
44
|
async def wait_for_signal(self, signal, timeout_seconds=None) -> SignalValueT:
|
45
45
|
if not workflow._Runtime.current():
|
46
|
-
raise RuntimeError(
|
46
|
+
raise RuntimeError(
|
47
|
+
"TemporalSignalHandler.wait_for_signal must be called from within a workflow"
|
48
|
+
)
|
47
49
|
|
48
50
|
unique_signal_name = f"{signal.name}_{uuid.uuid4()}"
|
49
51
|
registration = SignalRegistration(
|
@@ -77,13 +79,19 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
|
|
77
79
|
async with self._lock:
|
78
80
|
# Remove ourselves from _pending_signals
|
79
81
|
if signal.name in self._pending_signals:
|
80
|
-
self._pending_signals[signal.name] = [
|
82
|
+
self._pending_signals[signal.name] = [
|
83
|
+
sr
|
84
|
+
for sr in self._pending_signals[signal.name]
|
85
|
+
if sr.unique_name != unique_signal_name
|
86
|
+
]
|
81
87
|
if not self._pending_signals[signal.name]:
|
82
88
|
del self._pending_signals[signal.name]
|
83
89
|
|
84
90
|
# Remove ourselves from _handlers
|
85
91
|
if signal.name in self._handlers:
|
86
|
-
self._handlers[signal.name] = [
|
92
|
+
self._handlers[signal.name] = [
|
93
|
+
h for h in self._handlers[signal.name] if h[0] != unique_signal_name
|
94
|
+
]
|
87
95
|
if not self._handlers[signal.name]:
|
88
96
|
del self._handlers[signal.name]
|
89
97
|
|
@@ -128,7 +136,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
|
|
128
136
|
registration = pending_signal.registration
|
129
137
|
if registration.workflow_id == signal.workflow_id:
|
130
138
|
# Only signal for registrations of that workflow
|
131
|
-
signal_tasks.append(
|
139
|
+
signal_tasks.append(
|
140
|
+
workflow_handle.signal(registration.unique_name, signal.payload)
|
141
|
+
)
|
132
142
|
else:
|
133
143
|
continue
|
134
144
|
|
@@ -143,7 +153,9 @@ class TemporalSignalHandler(BaseSignalHandler[SignalValueT]):
|
|
143
153
|
super().validate_signal(signal)
|
144
154
|
# Add TemporalSignalHandler-specific validation
|
145
155
|
if signal.workflow_id is None:
|
146
|
-
raise ValueError(
|
156
|
+
raise ValueError(
|
157
|
+
"No workflow_id provided on Signal. That is required for Temporal signals"
|
158
|
+
)
|
147
159
|
|
148
160
|
|
149
161
|
class TemporalExecutorConfig(ExecutorConfig, TemporalSettings):
|
@@ -171,7 +183,9 @@ class TemporalExecutor(Executor):
|
|
171
183
|
context=context,
|
172
184
|
**kwargs,
|
173
185
|
)
|
174
|
-
self.config: TemporalExecutorConfig =
|
186
|
+
self.config: TemporalExecutorConfig = (
|
187
|
+
config or self.context.config.temporal or TemporalExecutorConfig()
|
188
|
+
)
|
175
189
|
self.client = client
|
176
190
|
self._worker = None
|
177
191
|
self._activity_semaphore = None
|
@@ -204,7 +218,9 @@ class TemporalExecutor(Executor):
|
|
204
218
|
|
205
219
|
return wrapped_activity
|
206
220
|
|
207
|
-
async def _execute_task_as_async(
|
221
|
+
async def _execute_task_as_async(
|
222
|
+
self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any
|
223
|
+
) -> R | BaseException:
|
208
224
|
async def run_task(task: Callable[..., R] | Coroutine[Any, Any, R]) -> R:
|
209
225
|
try:
|
210
226
|
if asyncio.iscoroutine(task):
|
@@ -237,7 +253,9 @@ class TemporalExecutor(Executor):
|
|
237
253
|
else:
|
238
254
|
return await run_task(task)
|
239
255
|
|
240
|
-
async def _execute_task(
|
256
|
+
async def _execute_task(
|
257
|
+
self, task: Callable[..., R] | Coroutine[Any, Any, R], **kwargs: Any
|
258
|
+
) -> R | BaseException:
|
241
259
|
func = task.func if isinstance(task, functools.partial) else task
|
242
260
|
is_workflow_task = getattr(func, "is_workflow_task", False)
|
243
261
|
if not is_workflow_task:
|
@@ -250,7 +268,9 @@ class TemporalExecutor(Executor):
|
|
250
268
|
if not activity_name:
|
251
269
|
activity_name = f"{func.__module__}.{func.__qualname__}"
|
252
270
|
|
253
|
-
schedule_to_close = execution_metadata.get(
|
271
|
+
schedule_to_close = execution_metadata.get(
|
272
|
+
"schedule_to_close_timeout", self.config.timeout_seconds
|
273
|
+
)
|
254
274
|
|
255
275
|
retry_policy = execution_metadata.get("retry_policy", None)
|
256
276
|
|
@@ -296,7 +316,9 @@ class TemporalExecutor(Executor):
|
|
296
316
|
**kwargs: Any,
|
297
317
|
) -> AsyncIterator[R | BaseException]:
|
298
318
|
if not workflow._Runtime.current():
|
299
|
-
raise RuntimeError(
|
319
|
+
raise RuntimeError(
|
320
|
+
"TemporalExecutor.execute_streaming must be called from within a workflow"
|
321
|
+
)
|
300
322
|
|
301
323
|
# TODO: saqadri - validate if async with self.execution_context() is needed here
|
302
324
|
async with self.execution_context():
|
@@ -354,6 +376,8 @@ class TemporalExecutor(Executor):
|
|
354
376
|
activities=activities,
|
355
377
|
workflows=[], # We'll auto-load by Python scanning or let the user specify
|
356
378
|
)
|
357
|
-
print(
|
379
|
+
print(
|
380
|
+
f"Starting Temporal Worker on task queue '{self.config.task_queue}' with {len(activities)} activities."
|
381
|
+
)
|
358
382
|
|
359
383
|
await self._worker.run()
|
@@ -147,7 +147,9 @@ class ConsoleSignalHandler(SignalHandler[str]):
|
|
147
147
|
loop = asyncio.get_event_loop()
|
148
148
|
if timeout_seconds is not None:
|
149
149
|
try:
|
150
|
-
value = await asyncio.wait_for(
|
150
|
+
value = await asyncio.wait_for(
|
151
|
+
loop.run_in_executor(None, input, "Enter value: "), timeout_seconds
|
152
|
+
)
|
151
153
|
except asyncio.TimeoutError:
|
152
154
|
print("\nTimeout waiting for input")
|
153
155
|
raise
|
@@ -220,7 +222,11 @@ class AsyncioSignalHandler(BaseSignalHandler[SignalValueT]):
|
|
220
222
|
async with self._lock:
|
221
223
|
# Remove from pending signals
|
222
224
|
if signal.name in self._pending_signals:
|
223
|
-
self._pending_signals[signal.name] = [
|
225
|
+
self._pending_signals[signal.name] = [
|
226
|
+
ps
|
227
|
+
for ps in self._pending_signals[signal.name]
|
228
|
+
if ps.registration.unique_name != unique_name
|
229
|
+
]
|
224
230
|
if not self._pending_signals[signal.name]:
|
225
231
|
del self._pending_signals[signal.name]
|
226
232
|
|
mcp_agent/human_input/handler.py
CHANGED
@@ -30,7 +30,9 @@ async def console_input_callback(request: HumanInputRequest) -> HumanInputRespon
|
|
30
30
|
)
|
31
31
|
|
32
32
|
# Extract agent name from metadata dictionary
|
33
|
-
agent_name =
|
33
|
+
agent_name = (
|
34
|
+
request.metadata.get("agent_name", "Unknown Agent") if request.metadata else "Unknown Agent"
|
35
|
+
)
|
34
36
|
|
35
37
|
# Use the context manager to pause the progress display while getting input
|
36
38
|
with progress_display.paused():
|