flock-core 0.5.0b1__py3-none-any.whl → 0.5.0b3__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 flock-core might be problematic. Click here for more details.
- flock/cli/manage_agents.py +3 -3
- flock/components/evaluation/declarative_evaluation_component.py +10 -10
- flock/components/routing/conditional_routing_component.py +7 -6
- flock/components/routing/default_routing_component.py +3 -3
- flock/components/routing/llm_routing_component.py +24 -26
- flock/components/utility/memory_utility_component.py +3 -3
- flock/components/utility/metrics_utility_component.py +11 -11
- flock/components/utility/output_utility_component.py +11 -9
- flock/core/__init__.py +24 -10
- flock/core/agent/flock_agent_components.py +16 -16
- flock/core/agent/flock_agent_integration.py +88 -29
- flock/core/agent/flock_agent_serialization.py +23 -20
- flock/core/api/endpoints.py +1 -1
- flock/core/component/__init__.py +7 -7
- flock/core/component/{evaluation_component_base.py → evaluation_component.py} +2 -2
- flock/core/component/{routing_component_base.py → routing_component.py} +3 -4
- flock/core/component/{utility_component_base.py → utility_component.py} +3 -3
- flock/core/flock.py +7 -7
- flock/core/flock_agent.py +68 -38
- flock/core/flock_factory.py +21 -18
- flock/core/flock_server_manager.py +8 -8
- flock/core/mcp/flock_mcp_server.py +11 -11
- flock/core/mcp/{flock_mcp_tool_base.py → flock_mcp_tool.py} +2 -2
- flock/core/mcp/mcp_client.py +9 -9
- flock/core/mcp/mcp_client_manager.py +9 -9
- flock/core/mcp/mcp_config.py +24 -24
- flock/core/orchestration/flock_execution.py +3 -3
- flock/core/orchestration/flock_initialization.py +6 -6
- flock/core/orchestration/flock_server_manager.py +8 -6
- flock/core/registry/__init__.py +16 -10
- flock/core/registry/registry_hub.py +7 -4
- flock/core/registry/server_registry.py +6 -6
- flock/core/serialization/flock_serializer.py +3 -2
- flock/mcp/servers/sse/flock_sse_server.py +10 -10
- flock/mcp/servers/stdio/flock_stdio_server.py +10 -10
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +10 -10
- flock/mcp/servers/websockets/flock_websocket_server.py +10 -10
- flock/workflow/activities.py +10 -10
- {flock_core-0.5.0b1.dist-info → flock_core-0.5.0b3.dist-info}/METADATA +1 -1
- {flock_core-0.5.0b1.dist-info → flock_core-0.5.0b3.dist-info}/RECORD +43 -45
- flock/core/flock_registry.py.backup +0 -688
- flock/workflow/activities_unified.py +0 -230
- {flock_core-0.5.0b1.dist-info → flock_core-0.5.0b3.dist-info}/WHEEL +0 -0
- {flock_core-0.5.0b1.dist-info → flock_core-0.5.0b3.dist-info}/entry_points.txt +0 -0
- {flock_core-0.5.0b1.dist-info → flock_core-0.5.0b3.dist-info}/licenses/LICENSE +0 -0
flock/core/flock_factory.py
CHANGED
|
@@ -16,13 +16,13 @@ from flock.components.utility.metrics_utility_component import (
|
|
|
16
16
|
# New unified components imported locally to avoid circular imports
|
|
17
17
|
from flock.core.config.flock_agent_config import FlockAgentConfig
|
|
18
18
|
from flock.core.config.scheduled_agent_config import ScheduledAgentConfig
|
|
19
|
-
from flock.core.flock_agent import
|
|
19
|
+
from flock.core.flock_agent import DynamicStr, FlockAgent
|
|
20
20
|
from flock.core.logging.formatters.themes import OutputTheme
|
|
21
|
-
from flock.core.mcp.flock_mcp_server import
|
|
21
|
+
from flock.core.mcp.flock_mcp_server import FlockMCPServer
|
|
22
22
|
from flock.core.mcp.mcp_config import (
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
FlockMCPCachingConfiguration,
|
|
24
|
+
FlockMCPCallbackConfiguration,
|
|
25
|
+
FlockMCPFeatureConfiguration,
|
|
26
26
|
)
|
|
27
27
|
from flock.core.mcp.types.types import (
|
|
28
28
|
FlockListRootsMCPCallback,
|
|
@@ -207,7 +207,7 @@ class FlockFactory:
|
|
|
207
207
|
tool_result_cache_ttl=100,
|
|
208
208
|
description: str | Callable[..., str] | None = None,
|
|
209
209
|
alert_latency_threshold_ms: int = 30000,
|
|
210
|
-
) ->
|
|
210
|
+
) -> FlockMCPServer:
|
|
211
211
|
"""Create a default MCP Server with common modules.
|
|
212
212
|
|
|
213
213
|
Allows for creating one of the three default-implementations provided
|
|
@@ -246,19 +246,19 @@ class FlockFactory:
|
|
|
246
246
|
continue # ignore
|
|
247
247
|
|
|
248
248
|
# build generic configs
|
|
249
|
-
feature_config =
|
|
249
|
+
feature_config = FlockMCPFeatureConfiguration(
|
|
250
250
|
roots_enabled=enable_roots_feature,
|
|
251
251
|
tools_enabled=enable_tools_feature,
|
|
252
252
|
prompts_enabled=enable_prompts_feature,
|
|
253
253
|
sampling_enabled=enable_sampling_feature,
|
|
254
254
|
)
|
|
255
|
-
callback_config =
|
|
255
|
+
callback_config = FlockMCPCallbackConfiguration(
|
|
256
256
|
sampling_callback=sampling_callback,
|
|
257
257
|
list_roots_callback=list_roots_callback,
|
|
258
258
|
logging_callback=logging_callback,
|
|
259
259
|
message_handler=message_handler,
|
|
260
260
|
)
|
|
261
|
-
caching_config =
|
|
261
|
+
caching_config = FlockMCPCachingConfiguration(
|
|
262
262
|
tool_cache_max_size=tool_cache_size,
|
|
263
263
|
tool_cache_max_ttl=tool_cache_ttl,
|
|
264
264
|
resource_contents_cache_max_size=resource_contents_cache_size,
|
|
@@ -388,12 +388,12 @@ class FlockFactory:
|
|
|
388
388
|
@staticmethod
|
|
389
389
|
def create_default_agent(
|
|
390
390
|
name: str,
|
|
391
|
-
description:
|
|
391
|
+
description: DynamicStr| None = None,
|
|
392
392
|
model: str | Callable[..., str] | None = None,
|
|
393
|
-
input:
|
|
394
|
-
output:
|
|
393
|
+
input: DynamicStr = None,
|
|
394
|
+
output: DynamicStr = None,
|
|
395
395
|
tools: list[Callable[..., Any] | Any] | None = None,
|
|
396
|
-
servers: list[str |
|
|
396
|
+
servers: list[str | FlockMCPServer] | None = None,
|
|
397
397
|
use_cache: bool = True,
|
|
398
398
|
enable_rich_tables: bool = False,
|
|
399
399
|
output_theme: OutputTheme = OutputTheme.abernathy,
|
|
@@ -408,6 +408,7 @@ class FlockFactory:
|
|
|
408
408
|
write_to_file: bool = False,
|
|
409
409
|
stream: bool = False,
|
|
410
410
|
include_thought_process: bool = False,
|
|
411
|
+
next_agent: DynamicStr | None = None,
|
|
411
412
|
temporal_activity_config: TemporalActivityConfig | None = None,
|
|
412
413
|
) -> FlockAgent:
|
|
413
414
|
"""Creates a default FlockAgent using unified component architecture.
|
|
@@ -479,7 +480,7 @@ class FlockFactory:
|
|
|
479
480
|
components=[evaluator, output_component, metrics_component],
|
|
480
481
|
config=FlockAgentConfig(write_to_file=write_to_file,
|
|
481
482
|
wait_for_input=wait_for_input),
|
|
482
|
-
next_agent=
|
|
483
|
+
next_agent=next_agent,
|
|
483
484
|
temporal_activity_config=temporal_activity_config,
|
|
484
485
|
)
|
|
485
486
|
|
|
@@ -489,14 +490,15 @@ class FlockFactory:
|
|
|
489
490
|
def create_scheduled_agent(
|
|
490
491
|
name: str,
|
|
491
492
|
schedule_expression: str, # e.g., "every 1h", "0 0 * * *"
|
|
492
|
-
description:
|
|
493
|
-
model: str |
|
|
494
|
-
output:
|
|
493
|
+
description: DynamicStr | None = None,
|
|
494
|
+
model: str | None = None,
|
|
495
|
+
output: DynamicStr | None = None, # Input might be implicit or none
|
|
495
496
|
tools: list[Callable[..., Any] | Any] | None = None,
|
|
496
|
-
servers: list[str |
|
|
497
|
+
servers: list[str | FlockMCPServer] | None = None,
|
|
497
498
|
use_cache: bool = False, # Whether to cache results
|
|
498
499
|
temperature: float = 0.7, # Temperature for model responses
|
|
499
500
|
# ... other common agent params from create_default_agent ...
|
|
501
|
+
next_agent: DynamicStr | None = None,
|
|
500
502
|
temporal_activity_config: TemporalActivityConfig
|
|
501
503
|
| None = None, # If you want scheduled tasks to be Temporal activities
|
|
502
504
|
**kwargs, # Forward other standard agent params
|
|
@@ -522,6 +524,7 @@ class FlockFactory:
|
|
|
522
524
|
temporal_activity_config=temporal_activity_config,
|
|
523
525
|
use_cache=use_cache,
|
|
524
526
|
temperature=temperature,
|
|
527
|
+
next_agent=next_agent,
|
|
525
528
|
**kwargs,
|
|
526
529
|
)
|
|
527
530
|
)
|
|
@@ -6,13 +6,13 @@ from contextlib import AsyncExitStack
|
|
|
6
6
|
from anyio import Lock
|
|
7
7
|
from pydantic import BaseModel, ConfigDict, Field
|
|
8
8
|
|
|
9
|
-
from flock.core.mcp.flock_mcp_server import
|
|
9
|
+
from flock.core.mcp.flock_mcp_server import FlockMCPServer
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class FlockServerManager(BaseModel):
|
|
13
13
|
"""Async-context-manager to start/stop a set of Flock MCP servers."""
|
|
14
14
|
|
|
15
|
-
servers: list[
|
|
15
|
+
servers: list[FlockMCPServer] | None = Field(
|
|
16
16
|
..., exclude=True, description="The servers to manage."
|
|
17
17
|
)
|
|
18
18
|
|
|
@@ -32,7 +32,7 @@ class FlockServerManager(BaseModel):
|
|
|
32
32
|
|
|
33
33
|
def __init__(
|
|
34
34
|
self,
|
|
35
|
-
servers: list[
|
|
35
|
+
servers: list[FlockMCPServer] | None = None,
|
|
36
36
|
stack: AsyncExitStack | None = None,
|
|
37
37
|
lock: asyncio.Lock | None = None,
|
|
38
38
|
) -> None:
|
|
@@ -43,7 +43,7 @@ class FlockServerManager(BaseModel):
|
|
|
43
43
|
lock=lock,
|
|
44
44
|
)
|
|
45
45
|
|
|
46
|
-
def add_server_sync(self, server:
|
|
46
|
+
def add_server_sync(self, server: FlockMCPServer) -> None:
|
|
47
47
|
"""Add a server to be managed by the ServerManager.
|
|
48
48
|
|
|
49
49
|
Note:
|
|
@@ -57,7 +57,7 @@ class FlockServerManager(BaseModel):
|
|
|
57
57
|
|
|
58
58
|
self.servers.append(server)
|
|
59
59
|
|
|
60
|
-
def remove_server_sync(self, server:
|
|
60
|
+
def remove_server_sync(self, server: FlockMCPServer) -> None:
|
|
61
61
|
"""Remove a server from the list of managed servers.
|
|
62
62
|
|
|
63
63
|
Note:
|
|
@@ -71,7 +71,7 @@ class FlockServerManager(BaseModel):
|
|
|
71
71
|
|
|
72
72
|
# -- For future use: Allow adding and removal of servers during runtime ---
|
|
73
73
|
async def add_server_during_runtime(
|
|
74
|
-
self, server:
|
|
74
|
+
self, server: FlockMCPServer
|
|
75
75
|
) -> None:
|
|
76
76
|
"""Add a server to the manager and, if already running, start it immediately."""
|
|
77
77
|
if self.lock is None:
|
|
@@ -88,13 +88,13 @@ class FlockServerManager(BaseModel):
|
|
|
88
88
|
await self.stack.enter_async_context(server)
|
|
89
89
|
|
|
90
90
|
async def remove_server_during_runtime(
|
|
91
|
-
self, server:
|
|
91
|
+
self, server: FlockMCPServer
|
|
92
92
|
) -> None:
|
|
93
93
|
"""Tear down and remove a server from the manager at runtime."""
|
|
94
94
|
if self.lock is None:
|
|
95
95
|
self.lock = asyncio.Lock()
|
|
96
96
|
|
|
97
|
-
retrieved_server:
|
|
97
|
+
retrieved_server: FlockMCPServer | None = None
|
|
98
98
|
|
|
99
99
|
async with self.lock:
|
|
100
100
|
if not self.servers or server not in self.servers:
|
|
@@ -17,9 +17,9 @@ from pydantic import (
|
|
|
17
17
|
|
|
18
18
|
from flock.core.component.agent_component_base import AgentComponent
|
|
19
19
|
from flock.core.logging.logging import get_logger
|
|
20
|
-
from flock.core.mcp.
|
|
21
|
-
from flock.core.mcp.mcp_client_manager import
|
|
22
|
-
from flock.core.mcp.mcp_config import
|
|
20
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
21
|
+
from flock.core.mcp.mcp_client_manager import FlockMCPClientManager
|
|
22
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
23
23
|
from flock.core.serialization.serializable import Serializable
|
|
24
24
|
from flock.core.serialization.serialization_utils import (
|
|
25
25
|
deserialize_component,
|
|
@@ -28,7 +28,7 @@ from flock.core.serialization.serialization_utils import (
|
|
|
28
28
|
|
|
29
29
|
logger = get_logger("mcp.server")
|
|
30
30
|
tracer = trace.get_tracer(__name__)
|
|
31
|
-
T = TypeVar("T", bound="
|
|
31
|
+
T = TypeVar("T", bound="FlockMCPServer")
|
|
32
32
|
|
|
33
33
|
LoggingLevel = Literal[
|
|
34
34
|
"debug",
|
|
@@ -42,7 +42,7 @@ LoggingLevel = Literal[
|
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
-
class
|
|
45
|
+
class FlockMCPServer(BaseModel, Serializable, ABC):
|
|
46
46
|
"""Base class for all Flock MCP Server Types.
|
|
47
47
|
|
|
48
48
|
Servers serve as an abstraction-layer between the underlying MCPClientSession
|
|
@@ -64,7 +64,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
64
64
|
2. Using FlockMCPServerConfig.with_fields() to create a config class.
|
|
65
65
|
"""
|
|
66
66
|
|
|
67
|
-
config:
|
|
67
|
+
config: FlockMCPConfiguration = Field(
|
|
68
68
|
..., description="Config for clients connecting to the server."
|
|
69
69
|
)
|
|
70
70
|
|
|
@@ -82,7 +82,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
82
82
|
# --- Underlying ConnectionManager ---
|
|
83
83
|
# (Manages a pool of ClientConnections and does the actual talking to the MCP Server)
|
|
84
84
|
# (Excluded from Serialization)
|
|
85
|
-
client_manager:
|
|
85
|
+
client_manager: FlockMCPClientManager | None = Field(
|
|
86
86
|
default=None,
|
|
87
87
|
exclude=True,
|
|
88
88
|
description="Underlying Connection Manager. Handles the actual underlying connections to the server.",
|
|
@@ -134,7 +134,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
134
134
|
return [c for c in self.components.values() if c.config.enabled]
|
|
135
135
|
|
|
136
136
|
@abstractmethod
|
|
137
|
-
async def initialize(self) ->
|
|
137
|
+
async def initialize(self) -> FlockMCPClientManager:
|
|
138
138
|
"""Called when initializing the server."""
|
|
139
139
|
pass
|
|
140
140
|
|
|
@@ -211,7 +211,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
211
211
|
additional_params=additional_params
|
|
212
212
|
)
|
|
213
213
|
result: list[
|
|
214
|
-
|
|
214
|
+
FlockMCPTool
|
|
215
215
|
] = await self.client_manager.get_tools(
|
|
216
216
|
agent_id=agent_id,
|
|
217
217
|
run_id=run_id,
|
|
@@ -385,7 +385,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
385
385
|
span.record_exception(module_error)
|
|
386
386
|
|
|
387
387
|
# --- Async Methods ---
|
|
388
|
-
async def __aenter__(self) -> "
|
|
388
|
+
async def __aenter__(self) -> "FlockMCPServer":
|
|
389
389
|
"""Enter the asynchronous context for the server."""
|
|
390
390
|
# Spin up the client-manager
|
|
391
391
|
with tracer.start_as_current_span("server.__aenter__") as span:
|
|
@@ -614,7 +614,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
614
614
|
config_cls = config_field.annotation
|
|
615
615
|
except (AttributeError, KeyError):
|
|
616
616
|
# fallback if Pydantic v1 or missing
|
|
617
|
-
config_cls =
|
|
617
|
+
config_cls = FlockMCPConfiguration
|
|
618
618
|
config_object = config_cls.from_dict(config_data)
|
|
619
619
|
data["config"] = config_object
|
|
620
620
|
|
|
@@ -13,7 +13,7 @@ from flock.core.logging.logging import get_logger
|
|
|
13
13
|
logger = get_logger("mcp.tool")
|
|
14
14
|
tracer = trace.get_tracer(__name__)
|
|
15
15
|
|
|
16
|
-
T = TypeVar("T", bound="
|
|
16
|
+
T = TypeVar("T", bound="FlockMCPTool")
|
|
17
17
|
|
|
18
18
|
TYPE_MAPPING = {
|
|
19
19
|
"string": str,
|
|
@@ -25,7 +25,7 @@ TYPE_MAPPING = {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class
|
|
28
|
+
class FlockMCPTool(BaseModel):
|
|
29
29
|
"""Base Class for MCP Tools for Flock."""
|
|
30
30
|
|
|
31
31
|
name: str = Field(..., description="Name of the tool")
|
flock/core/mcp/mcp_client.py
CHANGED
|
@@ -37,8 +37,8 @@ from pydantic import (
|
|
|
37
37
|
)
|
|
38
38
|
|
|
39
39
|
from flock.core.logging.logging import get_logger
|
|
40
|
-
from flock.core.mcp.
|
|
41
|
-
from flock.core.mcp.mcp_config import
|
|
40
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
41
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
42
42
|
from flock.core.mcp.types.factories import (
|
|
43
43
|
default_flock_mcp_list_roots_callback_factory,
|
|
44
44
|
default_flock_mcp_logging_callback_factory,
|
|
@@ -61,7 +61,7 @@ tracer = trace.get_tracer(__name__)
|
|
|
61
61
|
GetSessionIdCallback = Callable[[], str | None]
|
|
62
62
|
|
|
63
63
|
|
|
64
|
-
class
|
|
64
|
+
class FlockMCPClient(BaseModel, ABC):
|
|
65
65
|
"""Wrapper for mcp ClientSession.
|
|
66
66
|
|
|
67
67
|
Class will attempt to re-establish connection if possible.
|
|
@@ -71,7 +71,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
71
71
|
"""
|
|
72
72
|
|
|
73
73
|
# --- Properties ---
|
|
74
|
-
config:
|
|
74
|
+
config: FlockMCPConfiguration = Field(
|
|
75
75
|
..., description="The config for this client instance."
|
|
76
76
|
)
|
|
77
77
|
|
|
@@ -225,7 +225,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
225
225
|
|
|
226
226
|
def __init__(
|
|
227
227
|
self,
|
|
228
|
-
config:
|
|
228
|
+
config: FlockMCPConfiguration,
|
|
229
229
|
lock: Lock | None = None,
|
|
230
230
|
tool_cache: TTLCache | None = None,
|
|
231
231
|
tool_result_cache: TTLCache | None = None,
|
|
@@ -374,24 +374,24 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
374
374
|
self,
|
|
375
375
|
agent_id: str,
|
|
376
376
|
run_id: str,
|
|
377
|
-
) -> list[
|
|
377
|
+
) -> list[FlockMCPTool]:
|
|
378
378
|
"""Gets a list of available tools from the server."""
|
|
379
379
|
|
|
380
380
|
@cached(cache=self.tool_cache, key=cache_key_generator)
|
|
381
381
|
async def _get_tools_cached(
|
|
382
382
|
agent_id: str,
|
|
383
383
|
run_id: str,
|
|
384
|
-
) -> list[
|
|
384
|
+
) -> list[FlockMCPTool]:
|
|
385
385
|
if not self.config.feature_config.tools_enabled:
|
|
386
386
|
return []
|
|
387
387
|
|
|
388
|
-
async def _get_tools_internal() -> list[
|
|
388
|
+
async def _get_tools_internal() -> list[FlockMCPTool]:
|
|
389
389
|
# TODO: Crash
|
|
390
390
|
response: ListToolsResult = await self.session.list_tools()
|
|
391
391
|
flock_tools = []
|
|
392
392
|
|
|
393
393
|
for tool in response.tools:
|
|
394
|
-
converted_tool =
|
|
394
|
+
converted_tool = FlockMCPTool.from_mcp_tool(
|
|
395
395
|
tool,
|
|
396
396
|
agent_id=agent_id,
|
|
397
397
|
run_id=run_id,
|
|
@@ -13,22 +13,22 @@ from pydantic import (
|
|
|
13
13
|
)
|
|
14
14
|
|
|
15
15
|
from flock.core.logging.logging import get_logger
|
|
16
|
-
from flock.core.mcp.
|
|
16
|
+
from flock.core.mcp.flock_mcp_tool import FlockMCPTool
|
|
17
17
|
from flock.core.mcp.mcp_client import (
|
|
18
|
-
|
|
18
|
+
FlockMCPClient,
|
|
19
19
|
)
|
|
20
|
-
from flock.core.mcp.mcp_config import
|
|
20
|
+
from flock.core.mcp.mcp_config import FlockMCPConfiguration
|
|
21
21
|
|
|
22
22
|
logger = get_logger("mcp.client_manager")
|
|
23
23
|
tracer = trace.get_tracer(__name__)
|
|
24
24
|
|
|
25
|
-
TClient = TypeVar("TClient", bound="
|
|
25
|
+
TClient = TypeVar("TClient", bound="FlockMCPClient")
|
|
26
26
|
|
|
27
27
|
|
|
28
|
-
class
|
|
28
|
+
class FlockMCPClientManager(BaseModel, ABC, Generic[TClient]):
|
|
29
29
|
"""Handles a Pool of MCPClients of type TClient."""
|
|
30
30
|
|
|
31
|
-
client_config:
|
|
31
|
+
client_config: FlockMCPConfiguration = Field(
|
|
32
32
|
..., description="Configuration for clients."
|
|
33
33
|
)
|
|
34
34
|
|
|
@@ -38,7 +38,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
38
38
|
exclude=True,
|
|
39
39
|
)
|
|
40
40
|
|
|
41
|
-
clients: dict[str, dict[str,
|
|
41
|
+
clients: dict[str, dict[str, FlockMCPClient]] = Field(
|
|
42
42
|
default_factory=dict,
|
|
43
43
|
exclude=True,
|
|
44
44
|
description="Internal Store for the clients.",
|
|
@@ -154,7 +154,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
154
154
|
agent_id: str,
|
|
155
155
|
run_id: str,
|
|
156
156
|
additional_params: dict[str, Any] | None = None,
|
|
157
|
-
) -> list[
|
|
157
|
+
) -> list[FlockMCPTool]:
|
|
158
158
|
"""Retrieves a list of tools for the agents to act on."""
|
|
159
159
|
with tracer.start_as_current_span("client_manager.get_tools") as span:
|
|
160
160
|
span.set_attribute("agent_id", agent_id)
|
|
@@ -165,7 +165,7 @@ class FlockMCPClientManagerBase(BaseModel, ABC, Generic[TClient]):
|
|
|
165
165
|
run_id=run_id,
|
|
166
166
|
additional_params=additional_params,
|
|
167
167
|
)
|
|
168
|
-
tools: list[
|
|
168
|
+
tools: list[FlockMCPTool] = await client.get_tools(
|
|
169
169
|
agent_id=agent_id, run_id=run_id
|
|
170
170
|
)
|
|
171
171
|
return tools
|
flock/core/mcp/mcp_config.py
CHANGED
|
@@ -36,14 +36,14 @@ LoggingLevel = Literal[
|
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
|
|
39
|
-
A = TypeVar("A", bound="
|
|
40
|
-
B = TypeVar("B", bound="
|
|
41
|
-
C = TypeVar("C", bound="
|
|
42
|
-
D = TypeVar("D", bound="
|
|
43
|
-
E = TypeVar("E", bound="
|
|
39
|
+
A = TypeVar("A", bound="FlockMCPCallbackConfiguration")
|
|
40
|
+
B = TypeVar("B", bound="FlockMCPConnectionConfiguration")
|
|
41
|
+
C = TypeVar("C", bound="FlockMCPConfiguration")
|
|
42
|
+
D = TypeVar("D", bound="FlockMCPCachingConfiguration")
|
|
43
|
+
E = TypeVar("E", bound="FlockMCPFeatureConfiguration")
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
class
|
|
46
|
+
class FlockMCPCachingConfiguration(BaseModel, Serializable):
|
|
47
47
|
"""Configuration for Caching in Clients."""
|
|
48
48
|
|
|
49
49
|
tool_cache_max_size: float = Field(
|
|
@@ -110,7 +110,7 @@ class FlockMCPCachingConfigurationBase(BaseModel, Serializable):
|
|
|
110
110
|
)
|
|
111
111
|
|
|
112
112
|
|
|
113
|
-
class
|
|
113
|
+
class FlockMCPCallbackConfiguration(BaseModel, Serializable):
|
|
114
114
|
"""Base Configuration Class for Callbacks for Clients."""
|
|
115
115
|
|
|
116
116
|
sampling_callback: FlockSamplingMCPCallback | None = Field(
|
|
@@ -188,7 +188,7 @@ class FlockMCPCallbackConfigurationBase(BaseModel, Serializable):
|
|
|
188
188
|
)
|
|
189
189
|
|
|
190
190
|
|
|
191
|
-
class
|
|
191
|
+
class FlockMCPConnectionConfiguration(BaseModel, Serializable):
|
|
192
192
|
"""Base Configuration Class for Connection Parameters for a client."""
|
|
193
193
|
|
|
194
194
|
max_retries: int = Field(
|
|
@@ -298,7 +298,7 @@ class FlockMCPConnectionConfigurationBase(BaseModel, Serializable):
|
|
|
298
298
|
)
|
|
299
299
|
|
|
300
300
|
|
|
301
|
-
class
|
|
301
|
+
class FlockMCPFeatureConfiguration(BaseModel, Serializable):
|
|
302
302
|
"""Base Configuration Class for switching MCP Features on and off."""
|
|
303
303
|
|
|
304
304
|
roots_enabled: bool = Field(
|
|
@@ -346,7 +346,7 @@ class FlockMCPFeatureConfigurationBase(BaseModel, Serializable):
|
|
|
346
346
|
)
|
|
347
347
|
|
|
348
348
|
|
|
349
|
-
class
|
|
349
|
+
class FlockMCPConfiguration(BaseModel, Serializable):
|
|
350
350
|
"""Base Configuration Class for MCP Clients.
|
|
351
351
|
|
|
352
352
|
Each Client should implement their own config
|
|
@@ -357,22 +357,22 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
357
357
|
..., description="Name of the server the client connects to."
|
|
358
358
|
)
|
|
359
359
|
|
|
360
|
-
connection_config:
|
|
360
|
+
connection_config: FlockMCPConnectionConfiguration = Field(
|
|
361
361
|
..., description="MCP Connection Configuration for a client."
|
|
362
362
|
)
|
|
363
363
|
|
|
364
|
-
caching_config:
|
|
365
|
-
default_factory=
|
|
364
|
+
caching_config: FlockMCPCachingConfiguration = Field(
|
|
365
|
+
default_factory=FlockMCPCachingConfiguration,
|
|
366
366
|
description="Configuration for the internal caches of the client.",
|
|
367
367
|
)
|
|
368
368
|
|
|
369
|
-
callback_config:
|
|
370
|
-
default_factory=
|
|
369
|
+
callback_config: FlockMCPCallbackConfiguration = Field(
|
|
370
|
+
default_factory=FlockMCPCallbackConfiguration,
|
|
371
371
|
description="Callback configuration for the client.",
|
|
372
372
|
)
|
|
373
373
|
|
|
374
|
-
feature_config:
|
|
375
|
-
default_factory=
|
|
374
|
+
feature_config: FlockMCPFeatureConfiguration = Field(
|
|
375
|
+
default_factory=FlockMCPFeatureConfiguration,
|
|
376
376
|
description="Feature configuration for the client.",
|
|
377
377
|
)
|
|
378
378
|
|
|
@@ -425,7 +425,7 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
425
425
|
config_cls = config_field.annotation
|
|
426
426
|
except (AttributeError, KeyError):
|
|
427
427
|
# fallback
|
|
428
|
-
config_cls =
|
|
428
|
+
config_cls = FlockMCPConnectionConfiguration
|
|
429
429
|
instance_data["connection_config"] = config_cls.from_dict(connection_config)
|
|
430
430
|
else:
|
|
431
431
|
raise ValueError(f"connection_config MUST be specified for '{data.get('name', 'unknown_server')}")
|
|
@@ -436,10 +436,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
436
436
|
config_cls = config_field.annotation
|
|
437
437
|
except (AttributeError, KeyError):
|
|
438
438
|
# fallback
|
|
439
|
-
config_cls =
|
|
439
|
+
config_cls = FlockMCPCachingConfiguration
|
|
440
440
|
instance_data["caching_config"] = config_cls.from_dict(caching_config)
|
|
441
441
|
else:
|
|
442
|
-
instance_data["caching_config"] =
|
|
442
|
+
instance_data["caching_config"] = FlockMCPCachingConfiguration()
|
|
443
443
|
|
|
444
444
|
if feature_config:
|
|
445
445
|
try:
|
|
@@ -447,10 +447,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
447
447
|
config_cls = config_field.annotation
|
|
448
448
|
except (AttributeError, KeyError):
|
|
449
449
|
# fallback
|
|
450
|
-
config_cls =
|
|
450
|
+
config_cls = FlockMCPFeatureConfiguration
|
|
451
451
|
instance_data["feature_config"] = config_cls.from_dict(feature_config)
|
|
452
452
|
else:
|
|
453
|
-
instance_data["feature_config"] =
|
|
453
|
+
instance_data["feature_config"] = FlockMCPFeatureConfiguration()
|
|
454
454
|
|
|
455
455
|
if callback_config:
|
|
456
456
|
try:
|
|
@@ -458,10 +458,10 @@ class FlockMCPConfigurationBase(BaseModel, Serializable):
|
|
|
458
458
|
config_cls = config_field.annotation
|
|
459
459
|
except (AttributeError, KeyError):
|
|
460
460
|
# fallback
|
|
461
|
-
config_cls =
|
|
461
|
+
config_cls = FlockMCPCallbackConfiguration
|
|
462
462
|
instance_data["callback_config"] = config_cls.from_dict(callback_config)
|
|
463
463
|
else:
|
|
464
|
-
instance_data["callback_config"] =
|
|
464
|
+
instance_data["callback_config"] = FlockMCPCallbackConfiguration()
|
|
465
465
|
|
|
466
466
|
return cls(**{k: v for k, v in instance_data.items()})
|
|
467
467
|
|
|
@@ -95,7 +95,7 @@ class FlockExecution:
|
|
|
95
95
|
# Import here to allow forward reference resolution
|
|
96
96
|
from flock.core.flock_agent import FlockAgent as ConcreteFlockAgent
|
|
97
97
|
from flock.core.mcp.flock_mcp_server import (
|
|
98
|
-
|
|
98
|
+
FlockMCPServer as ConcreteFlockServer,
|
|
99
99
|
)
|
|
100
100
|
|
|
101
101
|
with tracer.start_as_current_span("flock.run_async") as span:
|
|
@@ -131,7 +131,7 @@ class FlockExecution:
|
|
|
131
131
|
span.set_attribute("input", str(run_input))
|
|
132
132
|
span.set_attribute("run_id", effective_run_id)
|
|
133
133
|
span.set_attribute("enable_temporal", self.flock.enable_temporal)
|
|
134
|
-
|
|
134
|
+
|
|
135
135
|
logger.info(
|
|
136
136
|
f"Initiating Flock run '{self.flock.name}'. Start Agent: '{start_agent_name}'. Temporal: {self.flock.enable_temporal}."
|
|
137
137
|
)
|
|
@@ -169,7 +169,7 @@ class FlockExecution:
|
|
|
169
169
|
logger.error(f"Flock run '{self.flock.name}' failed: {e}", exc_info=True)
|
|
170
170
|
span.record_exception(e)
|
|
171
171
|
span.set_status(trace.Status(trace.StatusCode.ERROR, str(e)))
|
|
172
|
-
|
|
172
|
+
|
|
173
173
|
# Return a consistent error structure
|
|
174
174
|
error_output = {
|
|
175
175
|
"error": str(e),
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
|
|
4
4
|
import os
|
|
5
5
|
import uuid
|
|
6
|
-
from typing import TYPE_CHECKING
|
|
6
|
+
from typing import TYPE_CHECKING
|
|
7
7
|
|
|
8
8
|
from opentelemetry.baggage import get_baggage, set_baggage
|
|
9
9
|
|
|
10
|
-
from flock.core.registry import get_registry
|
|
11
10
|
from flock.core.logging.logging import get_logger
|
|
11
|
+
from flock.core.registry import get_registry
|
|
12
12
|
from flock.core.util.cli_helper import init_console
|
|
13
13
|
|
|
14
14
|
if TYPE_CHECKING:
|
|
15
15
|
from flock.core.flock import Flock
|
|
16
16
|
from flock.core.flock_agent import FlockAgent
|
|
17
|
-
from flock.core.mcp.flock_mcp_server import
|
|
17
|
+
from flock.core.mcp.flock_mcp_server import FlockMCPServer
|
|
18
18
|
|
|
19
19
|
logger = get_logger("flock.initialization")
|
|
20
20
|
|
|
@@ -28,7 +28,7 @@ class FlockInitialization:
|
|
|
28
28
|
def setup(
|
|
29
29
|
self,
|
|
30
30
|
agents: list["FlockAgent"] | None = None,
|
|
31
|
-
servers: list["
|
|
31
|
+
servers: list["FlockMCPServer"] | None = None,
|
|
32
32
|
) -> None:
|
|
33
33
|
"""Handle all initialization side effects and setup."""
|
|
34
34
|
# Register passed servers first (agents may depend on them)
|
|
@@ -64,10 +64,10 @@ class FlockInitialization:
|
|
|
64
64
|
enable_temporal=self.flock.enable_temporal,
|
|
65
65
|
)
|
|
66
66
|
|
|
67
|
-
def _register_servers(self, servers: list["
|
|
67
|
+
def _register_servers(self, servers: list["FlockMCPServer"]) -> None:
|
|
68
68
|
"""Register servers with the Flock instance."""
|
|
69
69
|
from flock.core.mcp.flock_mcp_server import (
|
|
70
|
-
|
|
70
|
+
FlockMCPServer as ConcreteFlockMCPServer,
|
|
71
71
|
)
|
|
72
72
|
|
|
73
73
|
for server in servers:
|
|
@@ -3,12 +3,14 @@
|
|
|
3
3
|
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
|
-
from flock.core.flock_server_manager import
|
|
6
|
+
from flock.core.flock_server_manager import (
|
|
7
|
+
FlockServerManager as InternalServerManager,
|
|
8
|
+
)
|
|
7
9
|
from flock.core.logging.logging import get_logger
|
|
8
10
|
|
|
9
11
|
if TYPE_CHECKING:
|
|
10
12
|
from flock.core.flock import Flock
|
|
11
|
-
from flock.core.mcp.flock_mcp_server import
|
|
13
|
+
from flock.core.mcp.flock_mcp_server import FlockMCPServer
|
|
12
14
|
|
|
13
15
|
logger = get_logger("flock.server_manager")
|
|
14
16
|
|
|
@@ -21,12 +23,12 @@ class FlockServerManager:
|
|
|
21
23
|
# Use the existing internal server manager
|
|
22
24
|
self._internal_mgr = InternalServerManager()
|
|
23
25
|
|
|
24
|
-
def add_server(self, server: "
|
|
26
|
+
def add_server(self, server: "FlockMCPServer") -> "FlockMCPServer":
|
|
25
27
|
"""Adds a server instance to this Flock configuration and registry as well as set it up to be managed by internal manager."""
|
|
26
|
-
from flock.core.registry import get_registry
|
|
27
28
|
from flock.core.mcp.flock_mcp_server import (
|
|
28
|
-
|
|
29
|
+
FlockMCPServer as ConcreteFlockMCPServer,
|
|
29
30
|
)
|
|
31
|
+
from flock.core.registry import get_registry
|
|
30
32
|
|
|
31
33
|
registry = get_registry()
|
|
32
34
|
|
|
@@ -60,6 +62,6 @@ class FlockServerManager:
|
|
|
60
62
|
return await self._internal_mgr.__aexit__(exc_type, exc_val, exc_tb)
|
|
61
63
|
|
|
62
64
|
@property
|
|
63
|
-
def servers(self) -> dict[str, "
|
|
65
|
+
def servers(self) -> dict[str, "FlockMCPServer"]:
|
|
64
66
|
"""Returns the dictionary of servers managed by this Flock instance."""
|
|
65
67
|
return self.flock._servers
|