flock-core 0.4.512__py3-none-any.whl → 0.4.513__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/core/flock_agent.py +1 -1
- flock/core/flock_factory.py +85 -2
- flock/core/logging/logging.py +8 -0
- flock/core/mcp/flock_mcp_server.py +30 -4
- flock/core/mcp/flock_mcp_tool_base.py +1 -1
- flock/core/mcp/mcp_client.py +57 -28
- flock/core/mcp/mcp_client_manager.py +1 -1
- flock/core/mcp/mcp_config.py +245 -9
- flock/core/mcp/types/callbacks.py +3 -5
- flock/core/mcp/types/factories.py +12 -14
- flock/core/mcp/types/handlers.py +9 -12
- flock/core/mcp/types/types.py +205 -2
- flock/mcp/servers/sse/flock_sse_server.py +21 -14
- flock/mcp/servers/streamable_http/__init__.py +0 -0
- flock/mcp/servers/streamable_http/flock_streamable_http_server.py +169 -0
- flock/mcp/servers/websockets/flock_websocket_server.py +3 -3
- {flock_core-0.4.512.dist-info → flock_core-0.4.513.dist-info}/METADATA +1 -1
- {flock_core-0.4.512.dist-info → flock_core-0.4.513.dist-info}/RECORD +21 -19
- {flock_core-0.4.512.dist-info → flock_core-0.4.513.dist-info}/WHEEL +0 -0
- {flock_core-0.4.512.dist-info → flock_core-0.4.513.dist-info}/entry_points.txt +0 -0
- {flock_core-0.4.512.dist-info → flock_core-0.4.513.dist-info}/licenses/LICENSE +0 -0
flock/core/flock_agent.py
CHANGED
|
@@ -384,7 +384,7 @@ class FlockAgent(BaseModel, Serializable, DSPyIntegrationMixin, ABC):
|
|
|
384
384
|
)
|
|
385
385
|
else:
|
|
386
386
|
logger.warning(
|
|
387
|
-
f"No Server with name '{server}' registered! Skipping."
|
|
387
|
+
f"No Server with name '{server.config.name}' registered! Skipping."
|
|
388
388
|
)
|
|
389
389
|
mcp_tools = mcp_tools + server_tools
|
|
390
390
|
|
flock/core/flock_factory.py
CHANGED
|
@@ -5,7 +5,8 @@ from collections.abc import Callable
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any, Literal
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
import httpx
|
|
9
|
+
from pydantic import AnyUrl, BaseModel, ConfigDict, Field, FileUrl
|
|
9
10
|
|
|
10
11
|
from flock.core.config.scheduled_agent_config import ScheduledAgentConfig
|
|
11
12
|
from flock.core.flock_agent import FlockAgent, SignatureType
|
|
@@ -24,6 +25,7 @@ from flock.core.mcp.types.types import (
|
|
|
24
25
|
MCPRoot,
|
|
25
26
|
SseServerParameters,
|
|
26
27
|
StdioServerParameters,
|
|
28
|
+
StreamableHttpServerParameters,
|
|
27
29
|
WebsocketServerParameters,
|
|
28
30
|
)
|
|
29
31
|
from flock.evaluators.declarative.declarative_evaluator import (
|
|
@@ -40,6 +42,11 @@ from flock.mcp.servers.stdio.flock_stdio_server import (
|
|
|
40
42
|
FlockStdioConfig,
|
|
41
43
|
FlockStdioConnectionConfig,
|
|
42
44
|
)
|
|
45
|
+
from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
|
|
46
|
+
FlockStreamableHttpConfig,
|
|
47
|
+
FlockStreamableHttpConnectionConfig,
|
|
48
|
+
FlockStreamableHttpServer,
|
|
49
|
+
)
|
|
43
50
|
from flock.mcp.servers.websockets.flock_websocket_server import (
|
|
44
51
|
FlockWSConfig,
|
|
45
52
|
FlockWSConnectionConfig,
|
|
@@ -101,6 +108,44 @@ class FlockFactory:
|
|
|
101
108
|
description="The text encoding error handler. See https://docs.python.org/3/library/codecs.html#codec-base-classes for explanations of possible values",
|
|
102
109
|
)
|
|
103
110
|
|
|
111
|
+
class StreamableHttpParams(BaseModel):
|
|
112
|
+
"""Factory-Params for Streamable Http Servers."""
|
|
113
|
+
|
|
114
|
+
url: str | AnyUrl = Field(
|
|
115
|
+
...,
|
|
116
|
+
description="Url the server listens at."
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
headers: dict[str, Any] | None = Field(
|
|
120
|
+
default=None,
|
|
121
|
+
description="Additional Headers to pass to the client."
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
auth: httpx.Auth | None = Field(
|
|
125
|
+
default=None,
|
|
126
|
+
description="Httpx Auth Schema."
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
timeout_seconds: float | int = Field(
|
|
130
|
+
default=5,
|
|
131
|
+
description="Http Timeout in Seconds"
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
sse_read_timeout_seconds: float | int = Field(
|
|
135
|
+
default=60*5,
|
|
136
|
+
description="How many seconds to wait for server-sent events until closing the connection."
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
terminate_on_close: bool = Field(
|
|
140
|
+
default=True,
|
|
141
|
+
description="Whether or not to terminate the underlying connection on close."
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
model_config = ConfigDict(
|
|
145
|
+
arbitrary_types_allowed=True,
|
|
146
|
+
extra="allow",
|
|
147
|
+
)
|
|
148
|
+
|
|
104
149
|
class SSEParams(BaseModel):
|
|
105
150
|
"""Factory-Params for SSE-Servers."""
|
|
106
151
|
|
|
@@ -123,6 +168,16 @@ class FlockFactory:
|
|
|
123
168
|
description="How many seconds to wait for server-sent events until closing the connection. (connections will be automatically re-established.)",
|
|
124
169
|
)
|
|
125
170
|
|
|
171
|
+
auth: httpx.Auth | None = Field(
|
|
172
|
+
default=None,
|
|
173
|
+
description="Httpx Auth Scheme."
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
model_config = ConfigDict(
|
|
177
|
+
arbitrary_types_allowed=True,
|
|
178
|
+
extra="allow",
|
|
179
|
+
)
|
|
180
|
+
|
|
126
181
|
class WebsocketParams(BaseModel):
|
|
127
182
|
"""Factory-Params for Websocket Servers."""
|
|
128
183
|
|
|
@@ -134,7 +189,7 @@ class FlockFactory:
|
|
|
134
189
|
@staticmethod
|
|
135
190
|
def create_mcp_server(
|
|
136
191
|
name: str,
|
|
137
|
-
connection_params: SSEParams | StdioParams | WebsocketParams,
|
|
192
|
+
connection_params: StreamableHttpParams | SSEParams | StdioParams | WebsocketParams,
|
|
138
193
|
max_retries: int = 3,
|
|
139
194
|
mount_points: list[str | MCPRoot] | None = None,
|
|
140
195
|
timeout_seconds: int | float = 10,
|
|
@@ -176,6 +231,9 @@ class FlockFactory:
|
|
|
176
231
|
if isinstance(connection_params, FlockFactory.WebsocketParams):
|
|
177
232
|
server_kind = "websockets"
|
|
178
233
|
concrete_server_cls = FlockWSServer
|
|
234
|
+
if isinstance(connection_params, FlockFactory.StreamableHttpParams):
|
|
235
|
+
server_kind = "streamable_http"
|
|
236
|
+
concrete_server_cls = FlockStreamableHttpServer
|
|
179
237
|
|
|
180
238
|
# convert mount points.
|
|
181
239
|
mounts: list[MCPRoot] = []
|
|
@@ -244,12 +302,37 @@ class FlockFactory:
|
|
|
244
302
|
caching_config=caching_config,
|
|
245
303
|
callback_config=callback_config,
|
|
246
304
|
)
|
|
305
|
+
elif server_kind == "streamable_http":
|
|
306
|
+
# build streamable http config
|
|
307
|
+
connection_config = FlockStreamableHttpConnectionConfig(
|
|
308
|
+
max_retries=max_retries,
|
|
309
|
+
connection_parameters=StreamableHttpServerParameters(
|
|
310
|
+
url=connection_params.url,
|
|
311
|
+
headers=connection_params.headers,
|
|
312
|
+
auth=connection_params.auth,
|
|
313
|
+
timeout=connection_params.timeout_seconds,
|
|
314
|
+
sse_read_timeout=connection_params.sse_read_timeout_seconds,
|
|
315
|
+
terminate_on_close=connection_params.terminate_on_close,
|
|
316
|
+
),
|
|
317
|
+
mount_points=mounts,
|
|
318
|
+
server_logging_level=server_logging_level,
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
server_config = FlockStreamableHttpConfig(
|
|
322
|
+
name=name,
|
|
323
|
+
connection_config=connection_config,
|
|
324
|
+
feature_config=feature_config,
|
|
325
|
+
caching_config=caching_config,
|
|
326
|
+
callback_config=callback_config,
|
|
327
|
+
)
|
|
328
|
+
|
|
247
329
|
elif server_kind == "sse":
|
|
248
330
|
# build sse config
|
|
249
331
|
connection_config = FlockSSEConnectionConfig(
|
|
250
332
|
max_retries=max_retries,
|
|
251
333
|
connection_parameters=SseServerParameters(
|
|
252
334
|
url=connection_params.url,
|
|
335
|
+
auth=connection_params.auth,
|
|
253
336
|
headers=connection_params.headers,
|
|
254
337
|
timeout=connection_params.timeout_seconds,
|
|
255
338
|
sse_read_timeout=connection_params.sse_read_timeout_seconds,
|
flock/core/logging/logging.py
CHANGED
|
@@ -68,6 +68,14 @@ COLOR_MAP = {
|
|
|
68
68
|
"workflow": "cyan", # Color only
|
|
69
69
|
"activities": "cyan",
|
|
70
70
|
"context": "green",
|
|
71
|
+
"mcp.server": "blue",
|
|
72
|
+
"mcp.tool": "cyan",
|
|
73
|
+
"mcp.client_manager": "light-blue",
|
|
74
|
+
"mcp.client": "light-cyan",
|
|
75
|
+
"mcp.callback.logging": "white",
|
|
76
|
+
"mcp.callback.sampling": "pink",
|
|
77
|
+
"mcp.callback.root": "light-yellow",
|
|
78
|
+
"mcp.callback.message": "light-blue",
|
|
71
79
|
# Components & Mechanisms
|
|
72
80
|
"registry": "yellow", # Color only
|
|
73
81
|
"serialization": "yellow",
|
|
@@ -26,7 +26,7 @@ from flock.core.serialization.serialization_utils import (
|
|
|
26
26
|
serialize_item,
|
|
27
27
|
)
|
|
28
28
|
|
|
29
|
-
logger = get_logger("
|
|
29
|
+
logger = get_logger("mcp.server")
|
|
30
30
|
tracer = trace.get_tracer(__name__)
|
|
31
31
|
T = TypeVar("T", bound="FlockMCPServerBase")
|
|
32
32
|
|
|
@@ -206,7 +206,6 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
206
206
|
async with self.condition:
|
|
207
207
|
try:
|
|
208
208
|
await self.pre_mcp_call()
|
|
209
|
-
# TODO: inject additional params here.
|
|
210
209
|
additional_params: dict[str, Any] = {}
|
|
211
210
|
additional_params = await self.before_connect(
|
|
212
211
|
additional_params=additional_params
|
|
@@ -314,7 +313,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
314
313
|
async def post_terminate(self) -> None:
|
|
315
314
|
"""Run post-terminate hooks on modules."""
|
|
316
315
|
logger.debug(
|
|
317
|
-
f"Running
|
|
316
|
+
f"Running post_terminate hooks for modules in server: '{self.config.name}'"
|
|
318
317
|
)
|
|
319
318
|
with tracer.start_as_current_span("server.post_terminate") as span:
|
|
320
319
|
span.set_attribute("server.name", self.config.name)
|
|
@@ -437,7 +436,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
437
436
|
|
|
438
437
|
FlockRegistry = get_registry()
|
|
439
438
|
|
|
440
|
-
exclude = ["modules"]
|
|
439
|
+
exclude = ["modules", "config"]
|
|
441
440
|
|
|
442
441
|
logger.debug(f"Serializing server '{self.config.name}' to dict.")
|
|
443
442
|
# Use Pydantic's dump, exclued manually handled fields.
|
|
@@ -447,6 +446,11 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
447
446
|
exclude_none=True, # Exclude None values for cleaner output
|
|
448
447
|
)
|
|
449
448
|
|
|
449
|
+
# --- Let the config handle its own serialization ---
|
|
450
|
+
config_data = self.config.to_dict(path_type=path_type)
|
|
451
|
+
data["config"] = config_data
|
|
452
|
+
|
|
453
|
+
|
|
450
454
|
builtin_by_transport = {}
|
|
451
455
|
|
|
452
456
|
try:
|
|
@@ -454,12 +458,16 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
454
458
|
from flock.mcp.servers.stdio.flock_stdio_server import (
|
|
455
459
|
FlockMCPStdioServer,
|
|
456
460
|
)
|
|
461
|
+
from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
|
|
462
|
+
FlockStreamableHttpServer,
|
|
463
|
+
)
|
|
457
464
|
from flock.mcp.servers.websockets.flock_websocket_server import (
|
|
458
465
|
FlockWSServer,
|
|
459
466
|
)
|
|
460
467
|
|
|
461
468
|
builtin_by_transport = {
|
|
462
469
|
"stdio": FlockMCPStdioServer,
|
|
470
|
+
"streamable_http": FlockStreamableHttpServer,
|
|
463
471
|
"sse": FlockSSEServer,
|
|
464
472
|
"websockets": FlockWSServer,
|
|
465
473
|
}
|
|
@@ -570,6 +578,9 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
570
578
|
from flock.mcp.servers.stdio.flock_stdio_server import (
|
|
571
579
|
FlockMCPStdioServer,
|
|
572
580
|
)
|
|
581
|
+
from flock.mcp.servers.streamable_http.flock_streamable_http_server import (
|
|
582
|
+
FlockStreamableHttpServer,
|
|
583
|
+
)
|
|
573
584
|
from flock.mcp.servers.websockets.flock_websocket_server import (
|
|
574
585
|
FlockWSServer,
|
|
575
586
|
)
|
|
@@ -577,6 +588,7 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
577
588
|
builtin_by_transport = {
|
|
578
589
|
"stdio": FlockMCPStdioServer,
|
|
579
590
|
"sse": FlockSSEServer,
|
|
591
|
+
"streamable_http": FlockStreamableHttpServer,
|
|
580
592
|
"websockets": FlockWSServer,
|
|
581
593
|
}
|
|
582
594
|
except ImportError:
|
|
@@ -592,6 +604,20 @@ class FlockMCPServerBase(BaseModel, Serializable, ABC):
|
|
|
592
604
|
transport = data["config"]["connection_config"]["transport_type"]
|
|
593
605
|
real_cls = builtin_by_transport.get(transport, cls)
|
|
594
606
|
|
|
607
|
+
# deserialize the config:
|
|
608
|
+
config_data = data.pop("config", None)
|
|
609
|
+
if config_data:
|
|
610
|
+
# Forcing a square into a round hole
|
|
611
|
+
# pretty ugly, but gets the job done.
|
|
612
|
+
try:
|
|
613
|
+
config_field = real_cls.model_fields["config"]
|
|
614
|
+
config_cls = config_field.annotation
|
|
615
|
+
except (AttributeError, KeyError):
|
|
616
|
+
# fallback if Pydantic v1 or missing
|
|
617
|
+
config_cls = FlockMCPConfigurationBase
|
|
618
|
+
config_object = config_cls.from_dict(config_data)
|
|
619
|
+
data["config"] = config_object
|
|
620
|
+
|
|
595
621
|
# now construct
|
|
596
622
|
server = real_cls(**{k: v for k, v in data.items() if k != "modules"})
|
|
597
623
|
|
|
@@ -10,7 +10,7 @@ from pydantic import BaseModel, Field
|
|
|
10
10
|
|
|
11
11
|
from flock.core.logging.logging import get_logger
|
|
12
12
|
|
|
13
|
-
logger = get_logger("
|
|
13
|
+
logger = get_logger("mcp.tool")
|
|
14
14
|
tracer = trace.get_tracer(__name__)
|
|
15
15
|
|
|
16
16
|
T = TypeVar("T", bound="FlockMCPToolBase")
|
flock/core/mcp/mcp_client.py
CHANGED
|
@@ -4,9 +4,10 @@ import asyncio
|
|
|
4
4
|
import random
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from asyncio import Lock
|
|
7
|
+
from collections.abc import Callable
|
|
7
8
|
from contextlib import (
|
|
8
|
-
AbstractAsyncContextManager,
|
|
9
9
|
AsyncExitStack,
|
|
10
|
+
asynccontextmanager,
|
|
10
11
|
)
|
|
11
12
|
from datetime import timedelta
|
|
12
13
|
from typing import (
|
|
@@ -27,7 +28,7 @@ from mcp import (
|
|
|
27
28
|
McpError,
|
|
28
29
|
ServerCapabilities,
|
|
29
30
|
)
|
|
30
|
-
from mcp.types import CallToolResult
|
|
31
|
+
from mcp.types import CallToolResult
|
|
31
32
|
from opentelemetry import trace
|
|
32
33
|
from pydantic import (
|
|
33
34
|
BaseModel,
|
|
@@ -54,9 +55,11 @@ from flock.core.mcp.types.types import (
|
|
|
54
55
|
)
|
|
55
56
|
from flock.core.mcp.util.helpers import cache_key_generator
|
|
56
57
|
|
|
57
|
-
logger = get_logger("
|
|
58
|
+
logger = get_logger("mcp.client")
|
|
58
59
|
tracer = trace.get_tracer(__name__)
|
|
59
60
|
|
|
61
|
+
GetSessionIdCallback = Callable[[], str | None]
|
|
62
|
+
|
|
60
63
|
|
|
61
64
|
class FlockMCPClientBase(BaseModel, ABC):
|
|
62
65
|
"""Wrapper for mcp ClientSession.
|
|
@@ -159,11 +162,9 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
159
162
|
max_tries = cfg.connection_config.max_retries or 1
|
|
160
163
|
base_delay = 0.1
|
|
161
164
|
span.set_attribute("client.name", client.config.name)
|
|
165
|
+
span.set_attribute("max_tries", max_tries)
|
|
162
166
|
|
|
163
167
|
for attempt in range(1, max_tries + 2):
|
|
164
|
-
span.set_attribute(
|
|
165
|
-
"max_tries", max_tries
|
|
166
|
-
) # TODO: shift outside of loop
|
|
167
168
|
span.set_attribute("base_delay", base_delay)
|
|
168
169
|
span.set_attribute("attempt", attempt)
|
|
169
170
|
await client._ensure_connected()
|
|
@@ -364,12 +365,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
364
365
|
self,
|
|
365
366
|
params: ServerParameters,
|
|
366
367
|
additional_params: dict[str, Any] | None = None,
|
|
367
|
-
) ->
|
|
368
|
-
tuple[
|
|
369
|
-
MemoryObjectReceiveStream[JSONRPCMessage | Exception],
|
|
370
|
-
MemoryObjectSendStream[JSONRPCMessage],
|
|
371
|
-
]
|
|
372
|
-
]:
|
|
368
|
+
) -> Any:
|
|
373
369
|
"""Given your custom ServerParameters, return an async-contextmgr whose __aenter yields (read_stream, write_stream)."""
|
|
374
370
|
...
|
|
375
371
|
|
|
@@ -390,6 +386,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
390
386
|
return []
|
|
391
387
|
|
|
392
388
|
async def _get_tools_internal() -> list[FlockMCPToolBase]:
|
|
389
|
+
# TODO: Crash
|
|
393
390
|
response: ListToolsResult = await self.session.list_tools()
|
|
394
391
|
flock_tools = []
|
|
395
392
|
|
|
@@ -520,13 +517,31 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
520
517
|
if self.session_stack:
|
|
521
518
|
# manually __aexit__
|
|
522
519
|
await self.session_stack.aclose()
|
|
523
|
-
self.
|
|
524
|
-
self.client_session = None
|
|
520
|
+
self.client_session = None # remove the reference
|
|
525
521
|
|
|
526
522
|
# --- Private Methods ---
|
|
523
|
+
@asynccontextmanager
|
|
524
|
+
async def _safe_transport_ctx(self, cm: Any):
|
|
525
|
+
"""Enter the real transport ctxmg, yield its value, but on __aexit__ always swallow all errors."""
|
|
526
|
+
val = await cm.__aenter__()
|
|
527
|
+
try:
|
|
528
|
+
yield val
|
|
529
|
+
finally:
|
|
530
|
+
try:
|
|
531
|
+
await cm.__aexit__(None, None, None)
|
|
532
|
+
except Exception as e:
|
|
533
|
+
logger.debug(
|
|
534
|
+
f"Suppressed transport-ctx exit error "
|
|
535
|
+
f"for server '{self.config.name}': {e!r}"
|
|
536
|
+
)
|
|
537
|
+
|
|
527
538
|
async def _create_session(self) -> None:
|
|
528
|
-
"""Create and
|
|
539
|
+
"""Create and hold onto a single ClientSession + ExitStack."""
|
|
529
540
|
logger.debug(f"Creating Client Session for server '{self.config.name}'")
|
|
541
|
+
if self.session_stack:
|
|
542
|
+
await self.session_stack.aclose()
|
|
543
|
+
if self.client_session:
|
|
544
|
+
self.client_session = None
|
|
530
545
|
stack = AsyncExitStack()
|
|
531
546
|
await stack.__aenter__()
|
|
532
547
|
|
|
@@ -536,7 +551,30 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
536
551
|
transport_ctx = await self.create_transport(
|
|
537
552
|
server_params, self.additional_params
|
|
538
553
|
)
|
|
539
|
-
|
|
554
|
+
safe_transport = self._safe_transport_ctx(transport_ctx)
|
|
555
|
+
result = await stack.enter_async_context(safe_transport)
|
|
556
|
+
|
|
557
|
+
# support old (read, write) or new (read, write, get_sesssion_id_callback)
|
|
558
|
+
read: MemoryObjectReceiveStream | None = None
|
|
559
|
+
write: MemoryObjectSendStream | None = None
|
|
560
|
+
get_session_id_callback: GetSessionIdCallback | None = None
|
|
561
|
+
if isinstance(result, tuple) and len(result) == 2:
|
|
562
|
+
# old type
|
|
563
|
+
read, write = result
|
|
564
|
+
get_session_id_callback = None
|
|
565
|
+
elif isinstance(result, tuple) and len(result) == 3:
|
|
566
|
+
# new type
|
|
567
|
+
read, write, get_session_id_callback = result
|
|
568
|
+
else:
|
|
569
|
+
raise RuntimeError(
|
|
570
|
+
f"create_transport returned unexpected tuple of {result}"
|
|
571
|
+
)
|
|
572
|
+
|
|
573
|
+
if read is None or write is None:
|
|
574
|
+
raise RuntimeError(
|
|
575
|
+
f"create_transport did not create any read or write streams."
|
|
576
|
+
)
|
|
577
|
+
|
|
540
578
|
read_timeout = self.config.connection_config.read_timeout_seconds
|
|
541
579
|
|
|
542
580
|
if (
|
|
@@ -553,6 +591,8 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
553
591
|
else timedelta(seconds=float(read_timeout))
|
|
554
592
|
)
|
|
555
593
|
|
|
594
|
+
# TODO: get_session_id_callback is currently ignored.
|
|
595
|
+
|
|
556
596
|
session = await stack.enter_async_context(
|
|
557
597
|
ClientSession(
|
|
558
598
|
read_stream=read,
|
|
@@ -603,18 +643,7 @@ class FlockMCPClientBase(BaseModel, ABC):
|
|
|
603
643
|
|
|
604
644
|
self.connected_server_capabilities = init
|
|
605
645
|
|
|
606
|
-
init_report = f""
|
|
607
|
-
Server Init Handshake completed Server '{self.config.name}'
|
|
608
|
-
Lists the following Capabilities:
|
|
609
|
-
|
|
610
|
-
- Protocol Version: {init.protocolVersion}
|
|
611
|
-
- Instructions: {init.instructions or "No specific Instructions"}
|
|
612
|
-
- MCP Implementation:
|
|
613
|
-
- Name: {init.serverInfo.name}
|
|
614
|
-
- Version: {init.serverInfo.version}
|
|
615
|
-
- Capabilities:
|
|
616
|
-
{init.capabilities}
|
|
617
|
-
"""
|
|
646
|
+
init_report = f"Server: '{self.config.name}': Protocol-Version: {init.protocolVersion}, Instructions: {init.instructions or 'No specific instructions'}, MCP_Implementation: Name: {init.serverInfo.name}, Version: {init.serverInfo.version}, Capabilities: {init.capabilities}"
|
|
618
647
|
|
|
619
648
|
logger.debug(init_report)
|
|
620
649
|
|
|
@@ -19,7 +19,7 @@ from flock.core.mcp.mcp_client import (
|
|
|
19
19
|
)
|
|
20
20
|
from flock.core.mcp.mcp_config import FlockMCPConfigurationBase
|
|
21
21
|
|
|
22
|
-
logger = get_logger("
|
|
22
|
+
logger = get_logger("mcp.client_manager")
|
|
23
23
|
tracer = trace.get_tracer(__name__)
|
|
24
24
|
|
|
25
25
|
TClient = TypeVar("TClient", bound="FlockMCPClientBase")
|