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/mcp/types/types.py
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
"""Types for Flock's MCP functionality."""
|
|
2
2
|
|
|
3
|
+
import importlib
|
|
4
|
+
import inspect
|
|
5
|
+
import os
|
|
3
6
|
from collections.abc import Awaitable, Callable
|
|
4
7
|
from contextlib import AbstractAsyncContextManager
|
|
5
|
-
from typing import Any
|
|
8
|
+
from typing import Any, Literal
|
|
6
9
|
|
|
10
|
+
import httpx
|
|
7
11
|
from anyio.streams.memory import (
|
|
8
12
|
MemoryObjectReceiveStream,
|
|
9
13
|
MemoryObjectSendStream,
|
|
@@ -36,6 +40,7 @@ from mcp.types import (
|
|
|
36
40
|
from pydantic import AnyUrl, BaseModel, ConfigDict, Field
|
|
37
41
|
|
|
38
42
|
from flock.core.mcp.util.helpers import get_default_env
|
|
43
|
+
from flock.core.serialization.serializable import Serializable
|
|
39
44
|
|
|
40
45
|
|
|
41
46
|
class ServerNotification(_MCPServerNotification):
|
|
@@ -80,17 +85,40 @@ class MCPRoot(_MCPRoot):
|
|
|
80
85
|
"""Wrapper for mcp.types.Root."""
|
|
81
86
|
|
|
82
87
|
|
|
83
|
-
class ServerParameters(BaseModel):
|
|
88
|
+
class ServerParameters(BaseModel, Serializable):
|
|
84
89
|
"""Base Type for server parameters."""
|
|
85
90
|
|
|
86
91
|
model_config = ConfigDict(
|
|
87
92
|
arbitrary_types_allowed=True,
|
|
88
93
|
)
|
|
89
94
|
|
|
95
|
+
transport_type: Literal["stdio", "websockets", "sse", "streamable_http"] = Field(
|
|
96
|
+
...,
|
|
97
|
+
description="which type of transport these connection params are used for."
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
def to_dict(self, path_type: str = "relative"):
|
|
101
|
+
"""Serialize."""
|
|
102
|
+
return self.model_dump(
|
|
103
|
+
exclude_defaults=False,
|
|
104
|
+
exclude_none=True,
|
|
105
|
+
mode="json"
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
@classmethod
|
|
109
|
+
def from_dict(cls, data: dict[str, Any]):
|
|
110
|
+
"""Deserialize."""
|
|
111
|
+
return cls(**data)
|
|
112
|
+
|
|
90
113
|
|
|
91
114
|
class StdioServerParameters(_MCPStdioServerParameters, ServerParameters):
|
|
92
115
|
"""Base Type for Stdio Server parameters."""
|
|
93
116
|
|
|
117
|
+
transport_type: Literal["stdio"] = Field(
|
|
118
|
+
default="stdio",
|
|
119
|
+
description="Use stdio params."
|
|
120
|
+
)
|
|
121
|
+
|
|
94
122
|
env: dict[str, str] | None = Field(
|
|
95
123
|
default_factory=get_default_env,
|
|
96
124
|
description="Environment for the MCP Server.",
|
|
@@ -100,12 +128,121 @@ class StdioServerParameters(_MCPStdioServerParameters, ServerParameters):
|
|
|
100
128
|
class WebsocketServerParameters(ServerParameters):
|
|
101
129
|
"""Base Type for Websocket Server params."""
|
|
102
130
|
|
|
131
|
+
transport_type: Literal["websockets"] = Field(
|
|
132
|
+
default="websockets",
|
|
133
|
+
description="Use websocket params."
|
|
134
|
+
)
|
|
135
|
+
|
|
103
136
|
url: str | AnyUrl = Field(..., description="Url the server listens at.")
|
|
104
137
|
|
|
138
|
+
class StreamableHttpServerParameters(ServerParameters):
|
|
139
|
+
"""Base Type for StreamableHttp params."""
|
|
140
|
+
|
|
141
|
+
transport_type: Literal["streamable_http"] = Field(
|
|
142
|
+
default="streamable_http",
|
|
143
|
+
description="Use streamable http params."
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
url: str | AnyUrl = Field(
|
|
147
|
+
...,
|
|
148
|
+
description="The url the server listens at."
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
headers: dict[str, Any] | None = Field(
|
|
152
|
+
default=None,
|
|
153
|
+
description="Additional headers to pass to the client."
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
timeout: float | int = Field(
|
|
157
|
+
default=5,
|
|
158
|
+
description="Http Timeout",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
sse_read_timeout: float | int = Field(
|
|
162
|
+
default=60*5,
|
|
163
|
+
description="How long the client will wait before disconnecting from the server."
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
terminate_on_close: bool = Field(
|
|
167
|
+
default=True,
|
|
168
|
+
description="Terminate connection on close"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
auth: httpx.Auth | None = Field(
|
|
172
|
+
default=None,
|
|
173
|
+
description="Httpx Auth Scheme"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
@classmethod
|
|
177
|
+
def from_dict(cls, data: dict[str, Any]):
|
|
178
|
+
"""Deserialize the object from a dict."""
|
|
179
|
+
# find and import the concrete implementation for
|
|
180
|
+
# the auth object
|
|
181
|
+
auth_obj: httpx.Auth | None = None
|
|
182
|
+
auth_impl = data.pop("auth", None)
|
|
183
|
+
if auth_impl:
|
|
184
|
+
# find the concrete implementation
|
|
185
|
+
impl = auth_impl.pop("implementation", None)
|
|
186
|
+
params = auth_impl.pop("params", None)
|
|
187
|
+
if impl:
|
|
188
|
+
mod = importlib.import_module(impl["module_path"])
|
|
189
|
+
real_cls = getattr(mod, impl["classname"])
|
|
190
|
+
if params:
|
|
191
|
+
auth_obj = real_cls(**{k: v for k, v in params.items()})
|
|
192
|
+
else:
|
|
193
|
+
# assume that the implementation handles it.
|
|
194
|
+
auth_obj = real_cls()
|
|
195
|
+
else:
|
|
196
|
+
raise ValueError("No concrete implementation for auth provided.")
|
|
197
|
+
|
|
198
|
+
data["auth"] = auth_obj
|
|
199
|
+
return cls(**{k: v for k, v in data.items()})
|
|
200
|
+
|
|
201
|
+
def to_dict(self, path_type = "relative"):
|
|
202
|
+
"""Serialize the object."""
|
|
203
|
+
exclude = ["auth"]
|
|
204
|
+
|
|
205
|
+
data = self.model_dump(
|
|
206
|
+
exclude=exclude,
|
|
207
|
+
exclude_defaults=False,
|
|
208
|
+
exclude_none=True,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# inject implentation info for auth
|
|
212
|
+
if self.auth is not None:
|
|
213
|
+
file_path = inspect.getsourcefile(type(self.auth))
|
|
214
|
+
if path_type == "relative":
|
|
215
|
+
file_path = os.path.relpath(file_path)
|
|
216
|
+
try:
|
|
217
|
+
# params should be primitive types, keeping with the
|
|
218
|
+
# declarative approach of flock.
|
|
219
|
+
params = {
|
|
220
|
+
k: getattr(self.auth, k)
|
|
221
|
+
for k in getattr(self.auth, "__dict__", {})
|
|
222
|
+
if not k.startswith("_")
|
|
223
|
+
}
|
|
224
|
+
except Exception:
|
|
225
|
+
params = None
|
|
226
|
+
|
|
227
|
+
data["auth"] = {
|
|
228
|
+
"implementation": {
|
|
229
|
+
"class_name": type(self.auth).__name__,
|
|
230
|
+
"module_path": type(self.auth).__module__,
|
|
231
|
+
"file_path": file_path,
|
|
232
|
+
},
|
|
233
|
+
"params": params,
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
return data
|
|
105
237
|
|
|
106
238
|
class SseServerParameters(ServerParameters):
|
|
107
239
|
"""Base Type for SSE Server params."""
|
|
108
240
|
|
|
241
|
+
transport_type: Literal["sse"] = Field(
|
|
242
|
+
default="sse",
|
|
243
|
+
description="Use sse server params."
|
|
244
|
+
)
|
|
245
|
+
|
|
109
246
|
url: str | AnyUrl = Field(..., description="The url the server listens at.")
|
|
110
247
|
|
|
111
248
|
headers: dict[str, Any] | None = Field(
|
|
@@ -119,6 +256,72 @@ class SseServerParameters(ServerParameters):
|
|
|
119
256
|
description="How long the client will wait before disconnecting from the server.",
|
|
120
257
|
)
|
|
121
258
|
|
|
259
|
+
auth: httpx.Auth | None = Field(
|
|
260
|
+
default=None,
|
|
261
|
+
description="Httpx Auth Scheme."
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
@classmethod
|
|
265
|
+
def from_dict(cls, data: dict[str, Any]):
|
|
266
|
+
"""Deserialize the object from a dict."""
|
|
267
|
+
# find and import the concrete implementation for
|
|
268
|
+
# the auth object.
|
|
269
|
+
auth_obj: httpx.Auth | None = None
|
|
270
|
+
auth_impl = data.pop("auth", None) # get the specs for the auth class
|
|
271
|
+
if auth_impl:
|
|
272
|
+
# find the concrete implementation
|
|
273
|
+
impl = auth_impl.pop("implementation", None)
|
|
274
|
+
params = auth_impl.pop("params", None)
|
|
275
|
+
if impl:
|
|
276
|
+
mod = importlib.import_module(impl["module_path"])
|
|
277
|
+
real_cls = getattr(mod, impl["class_name"])
|
|
278
|
+
if params:
|
|
279
|
+
auth_obj = real_cls(**{k: v for k, v in params.items()})
|
|
280
|
+
else:
|
|
281
|
+
# assume that implementation handles it
|
|
282
|
+
auth_obj = real_cls()
|
|
283
|
+
else:
|
|
284
|
+
raise ValueError("No concrete implementation for auth provided.")
|
|
285
|
+
|
|
286
|
+
data["auth"] = auth_obj
|
|
287
|
+
return cls(**{k: v for k, v in data.items()})
|
|
288
|
+
|
|
289
|
+
def to_dict(self, path_type = "relative"):
|
|
290
|
+
"""Serialize the object."""
|
|
291
|
+
exclude = ["auth"]
|
|
292
|
+
|
|
293
|
+
data = self.model_dump(
|
|
294
|
+
exclude=exclude,
|
|
295
|
+
exclude_defaults=False,
|
|
296
|
+
exclude_none=True,
|
|
297
|
+
)
|
|
298
|
+
|
|
299
|
+
# inject implentation info for auth
|
|
300
|
+
if self.auth is not None:
|
|
301
|
+
file_path = inspect.getsourcefile(type(self.auth))
|
|
302
|
+
if path_type == "relative":
|
|
303
|
+
file_path = os.path.relpath(file_path)
|
|
304
|
+
try:
|
|
305
|
+
# params should be primitive types, keeping with the
|
|
306
|
+
# declarative approach of flock.
|
|
307
|
+
params = {
|
|
308
|
+
k: getattr(self.auth, k)
|
|
309
|
+
for k in getattr(self.auth, "__dict__", {})
|
|
310
|
+
if not k.startswith("_")
|
|
311
|
+
}
|
|
312
|
+
except Exception:
|
|
313
|
+
params = None
|
|
314
|
+
|
|
315
|
+
data["auth"] = {
|
|
316
|
+
"implementation": {
|
|
317
|
+
"class_name": type(self.auth).__name__,
|
|
318
|
+
"module_path": type(self.auth).__module__,
|
|
319
|
+
"file_path": file_path,
|
|
320
|
+
},
|
|
321
|
+
"params": params,
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return data
|
|
122
325
|
|
|
123
326
|
MCPCLientInitFunction = Callable[
|
|
124
327
|
...,
|
|
@@ -4,12 +4,13 @@ import copy
|
|
|
4
4
|
from contextlib import AbstractAsyncContextManager
|
|
5
5
|
from typing import Any, Literal
|
|
6
6
|
|
|
7
|
+
import httpx
|
|
7
8
|
from anyio.streams.memory import (
|
|
8
9
|
MemoryObjectReceiveStream,
|
|
9
10
|
MemoryObjectSendStream,
|
|
10
11
|
)
|
|
11
12
|
from mcp.client.sse import sse_client
|
|
12
|
-
from mcp.
|
|
13
|
+
from mcp.shared.message import SessionMessage
|
|
13
14
|
from opentelemetry import trace
|
|
14
15
|
from pydantic import Field
|
|
15
16
|
|
|
@@ -63,45 +64,51 @@ class FlockSSEClient(FlockMCPClientBase):
|
|
|
63
64
|
additional_params: dict[str, Any] | None = None,
|
|
64
65
|
) -> AbstractAsyncContextManager[
|
|
65
66
|
tuple[
|
|
66
|
-
MemoryObjectReceiveStream[
|
|
67
|
-
MemoryObjectSendStream[
|
|
67
|
+
MemoryObjectReceiveStream[SessionMessage | Exception],
|
|
68
|
+
MemoryObjectSendStream[SessionMessage],
|
|
68
69
|
]
|
|
69
70
|
]:
|
|
70
71
|
"""Return an async context manager whose __aenter__ method yields (read_stream, send_stream)."""
|
|
71
72
|
# avoid modifying the config of the client as a side-effect.
|
|
72
73
|
param_copy = copy.deepcopy(params)
|
|
73
74
|
|
|
74
|
-
if
|
|
75
|
+
if additional_params:
|
|
75
76
|
override_headers = bool(
|
|
76
|
-
|
|
77
|
+
additional_params.get("override_headers", False)
|
|
77
78
|
)
|
|
78
|
-
if "headers" in
|
|
79
|
+
if "headers" in additional_params:
|
|
79
80
|
if override_headers:
|
|
80
|
-
param_copy.headers =
|
|
81
|
+
param_copy.headers = additional_params.get(
|
|
81
82
|
"headers", params.headers
|
|
82
83
|
)
|
|
83
84
|
else:
|
|
84
85
|
param_copy.headers.update(
|
|
85
|
-
|
|
86
|
+
additional_params.get("headers", {})
|
|
86
87
|
)
|
|
87
|
-
if "read_timeout_seconds" in
|
|
88
|
-
param_copy.timeout =
|
|
88
|
+
if "read_timeout_seconds" in additional_params:
|
|
89
|
+
param_copy.timeout = additional_params.get(
|
|
89
90
|
"read_timeout_seconds", params.timeout
|
|
90
91
|
)
|
|
91
92
|
|
|
92
|
-
if "sse_read_timeout" in
|
|
93
|
-
param_copy.sse_read_timeout =
|
|
93
|
+
if "sse_read_timeout" in additional_params:
|
|
94
|
+
param_copy.sse_read_timeout = additional_params.get(
|
|
94
95
|
"sse_read_timeout",
|
|
95
96
|
params.sse_read_timeout,
|
|
96
97
|
)
|
|
97
|
-
if "url" in
|
|
98
|
-
param_copy.url =
|
|
98
|
+
if "url" in additional_params:
|
|
99
|
+
param_copy.url = additional_params.get(
|
|
99
100
|
"url",
|
|
100
101
|
params.url,
|
|
101
102
|
)
|
|
102
103
|
|
|
104
|
+
if "auth" in additional_params and isinstance(
|
|
105
|
+
additional_params.get("auth"), httpx.Auth
|
|
106
|
+
):
|
|
107
|
+
param_copy.auth = additional_params.get("auth", param_copy.auth)
|
|
108
|
+
|
|
103
109
|
return sse_client(
|
|
104
110
|
url=param_copy.url,
|
|
111
|
+
auth=param_copy.auth,
|
|
105
112
|
headers=param_copy.headers,
|
|
106
113
|
timeout=float(param_copy.timeout),
|
|
107
114
|
sse_read_timeout=float(param_copy.sse_read_timeout),
|
|
File without changes
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"""This module provides the Flock Streamable-Http functionality."""
|
|
2
|
+
|
|
3
|
+
import copy
|
|
4
|
+
from collections.abc import Callable
|
|
5
|
+
from contextlib import AbstractAsyncContextManager
|
|
6
|
+
from datetime import timedelta
|
|
7
|
+
from typing import Any, Literal
|
|
8
|
+
|
|
9
|
+
import httpx
|
|
10
|
+
from anyio.streams.memory import (
|
|
11
|
+
MemoryObjectReceiveStream,
|
|
12
|
+
MemoryObjectSendStream,
|
|
13
|
+
)
|
|
14
|
+
from mcp.client.streamable_http import streamablehttp_client
|
|
15
|
+
from mcp.shared.message import SessionMessage
|
|
16
|
+
from opentelemetry import trace
|
|
17
|
+
from pydantic import Field
|
|
18
|
+
|
|
19
|
+
from flock.core.logging.logging import get_logger
|
|
20
|
+
from flock.core.mcp.flock_mcp_server import FlockMCPServerBase
|
|
21
|
+
from flock.core.mcp.mcp_client import FlockMCPClientBase
|
|
22
|
+
from flock.core.mcp.mcp_client_manager import FlockMCPClientManagerBase
|
|
23
|
+
from flock.core.mcp.mcp_config import (
|
|
24
|
+
FlockMCPConfigurationBase,
|
|
25
|
+
FlockMCPConnectionConfigurationBase,
|
|
26
|
+
)
|
|
27
|
+
from flock.core.mcp.types.types import (
|
|
28
|
+
StreamableHttpServerParameters,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
logger = get_logger("mcp.streamable_http.server")
|
|
32
|
+
tracer = trace.get_tracer(__name__)
|
|
33
|
+
|
|
34
|
+
GetSessionIdCallback = Callable[[], str | None]
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class FlockStreamableHttpConnectionConfig(FlockMCPConnectionConfigurationBase):
|
|
38
|
+
"""Concrete ConnectionConfig for a StreamableHttpClient."""
|
|
39
|
+
|
|
40
|
+
# Only thing we need to override here is the concrete transport_type
|
|
41
|
+
# and connection parameter fields.
|
|
42
|
+
transport_type: Literal["streamable_http"] = Field(
|
|
43
|
+
default="streamable_http",
|
|
44
|
+
description="Use the streamable_http Transport type.",
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
connection_parameters: StreamableHttpServerParameters = Field(
|
|
48
|
+
..., description="Streamable HTTP Server Connection Parameters."
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class FlockStreamableHttpConfig(FlockMCPConfigurationBase):
|
|
53
|
+
"""Configuration for Streamable HTTP Clients."""
|
|
54
|
+
|
|
55
|
+
# The only thing we need to override here is the
|
|
56
|
+
# concrete connection config.
|
|
57
|
+
# The rest is generic enough to handle everything else.
|
|
58
|
+
connection_config: FlockStreamableHttpConnectionConfig = Field(
|
|
59
|
+
..., description="Concrete StreamableHttp Connection Configuration."
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
class FlockStreamableHttpClient(FlockMCPClientBase):
|
|
64
|
+
"""Client for StreamableHttpServers."""
|
|
65
|
+
|
|
66
|
+
config: FlockStreamableHttpConfig = Field(
|
|
67
|
+
..., description="Client configuration."
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
async def create_transport(
|
|
71
|
+
self,
|
|
72
|
+
params: StreamableHttpServerParameters,
|
|
73
|
+
additional_params: dict[str, Any] | None = None,
|
|
74
|
+
) -> AbstractAsyncContextManager[
|
|
75
|
+
tuple[
|
|
76
|
+
MemoryObjectReceiveStream[SessionMessage | Exception],
|
|
77
|
+
MemoryObjectSendStream[SessionMessage],
|
|
78
|
+
GetSessionIdCallback,
|
|
79
|
+
],
|
|
80
|
+
None,
|
|
81
|
+
]:
|
|
82
|
+
"""Return an async context manager whose __aenter__ method yields (read_stream, send_stream)."""
|
|
83
|
+
param_copy = copy.deepcopy(params)
|
|
84
|
+
|
|
85
|
+
if additional_params:
|
|
86
|
+
override_headers = bool(
|
|
87
|
+
additional_params.get("override_headers", False)
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
if "headers" in additional_params:
|
|
91
|
+
if override_headers:
|
|
92
|
+
param_copy.headers = additional_params.get(
|
|
93
|
+
"headers", params.headers
|
|
94
|
+
)
|
|
95
|
+
else:
|
|
96
|
+
param_copy.headers.update(
|
|
97
|
+
additional_params.get("headers", {})
|
|
98
|
+
)
|
|
99
|
+
if "auth" in additional_params and isinstance(
|
|
100
|
+
additional_params.get("auth"), httpx.Auth
|
|
101
|
+
):
|
|
102
|
+
param_copy.auth = additional_params.get("auth", param_copy.auth)
|
|
103
|
+
|
|
104
|
+
if "read_timeout_seconds" in additional_params:
|
|
105
|
+
param_copy.timeout = additional_params.get(
|
|
106
|
+
"read_timeout_seconds", params.timeout
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if "sse_read_timeout" in additional_params:
|
|
110
|
+
param_copy.sse_read_timeout = additional_params.get(
|
|
111
|
+
"sse_read_timeout",
|
|
112
|
+
params.sse_read_timeout,
|
|
113
|
+
)
|
|
114
|
+
if "url" in additional_params:
|
|
115
|
+
param_copy.url = additional_params.get(
|
|
116
|
+
"url",
|
|
117
|
+
params.url,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if "terminate_on_close" in additional_params:
|
|
121
|
+
param_copy.terminate_on_close = bool(
|
|
122
|
+
additional_params.get("terminate_on_close", True)
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
timeout_http = timedelta(seconds=param_copy.timeout)
|
|
126
|
+
sse_timeout = timedelta(seconds=param_copy.sse_read_timeout)
|
|
127
|
+
|
|
128
|
+
return streamablehttp_client(
|
|
129
|
+
url=param_copy.url,
|
|
130
|
+
headers=param_copy.headers,
|
|
131
|
+
timeout=timeout_http,
|
|
132
|
+
sse_read_timeout=sse_timeout,
|
|
133
|
+
terminate_on_close=param_copy.terminate_on_close,
|
|
134
|
+
auth=param_copy.auth,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class FlockStreamableHttpClientManager(FlockMCPClientManagerBase):
|
|
139
|
+
"""Manager for handling StreamableHttpClients."""
|
|
140
|
+
|
|
141
|
+
client_config: FlockStreamableHttpConfig = Field(
|
|
142
|
+
..., description="Configuration for clients."
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
async def make_client(
|
|
146
|
+
self, additional_params: dict[str, Any] | None = None
|
|
147
|
+
) -> FlockStreamableHttpClient:
|
|
148
|
+
"""Create a new client instance."""
|
|
149
|
+
new_client = FlockStreamableHttpClient(
|
|
150
|
+
config=self.client_config,
|
|
151
|
+
additional_params=additional_params,
|
|
152
|
+
)
|
|
153
|
+
return new_client
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class FlockStreamableHttpServer(FlockMCPServerBase):
|
|
157
|
+
"""Class which represents a MCP Server using the streamable Http Transport type."""
|
|
158
|
+
|
|
159
|
+
config: FlockStreamableHttpConfig = Field(
|
|
160
|
+
..., description="Config for the server."
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
async def initialize(self) -> FlockStreamableHttpClientManager:
|
|
164
|
+
"""Called when initializing the server."""
|
|
165
|
+
client_manager = FlockStreamableHttpClientManager(
|
|
166
|
+
client_config=self.config
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
return client_manager
|
|
@@ -9,7 +9,7 @@ from anyio.streams.memory import (
|
|
|
9
9
|
MemoryObjectSendStream,
|
|
10
10
|
)
|
|
11
11
|
from mcp.client.websocket import websocket_client
|
|
12
|
-
from mcp.
|
|
12
|
+
from mcp.shared.message import SessionMessage
|
|
13
13
|
from opentelemetry import trace
|
|
14
14
|
from pydantic import Field
|
|
15
15
|
|
|
@@ -69,8 +69,8 @@ class FlockWSClient(FlockMCPClientBase):
|
|
|
69
69
|
additional_params: dict[str, Any] | None = None,
|
|
70
70
|
) -> AbstractAsyncContextManager[
|
|
71
71
|
tuple[
|
|
72
|
-
MemoryObjectReceiveStream[
|
|
73
|
-
MemoryObjectSendStream[
|
|
72
|
+
MemoryObjectReceiveStream[SessionMessage | Exception],
|
|
73
|
+
MemoryObjectSendStream[SessionMessage],
|
|
74
74
|
]
|
|
75
75
|
]:
|
|
76
76
|
"""Return an async context manager whose __aenter__ method yields a read_stream and a send_stream."""
|
|
@@ -27,9 +27,9 @@ flock/cli/yaml_editor.py,sha256=K3N0bh61G1TSDAZDnurqW9e_-hO6CtSQKXQqlDhCjVo,1252
|
|
|
27
27
|
flock/cli/assets/release_notes.md,sha256=bqnk50jxM3w5uY44Dc7MkdT8XmRREFxrVBAG9XCOSSU,4896
|
|
28
28
|
flock/core/__init__.py,sha256=juwyNr3QqKXUS5-E3hlMYRhgqHgQBqgtP12OF3tUCAI,1249
|
|
29
29
|
flock/core/flock.py,sha256=iR4i0_z0w2ns_iHbP7FqN--7wlsPIWch1H-BVecPs_I,38205
|
|
30
|
-
flock/core/flock_agent.py,sha256=
|
|
30
|
+
flock/core/flock_agent.py,sha256=Hl6TONSiJi2I-N_49-1hkW2q_hyPXMebMr-5oZLI-PY,48842
|
|
31
31
|
flock/core/flock_evaluator.py,sha256=TPy6u6XX3cqkY1r9NW1w2lTwCMNW7pxhFYKLefnEbXg,1820
|
|
32
|
-
flock/core/flock_factory.py,sha256=
|
|
32
|
+
flock/core/flock_factory.py,sha256=L3EFEUKqQmyxM_q0mh23ikLHPexSkV4Q8ifxIBSGA6s,18805
|
|
33
33
|
flock/core/flock_module.py,sha256=ObILimpVaPnaaqYvcBYJJ20lQzfrjgTdADplaNRjHU0,7448
|
|
34
34
|
flock/core/flock_registry.py,sha256=KzdFfc3QC-Dk42G24hdf6Prp3HvGj9ymXR3TTBe-T-A,27161
|
|
35
35
|
flock/core/flock_router.py,sha256=1OAXDsdaIIFApEfo6SRfFEDoTuGt3Si7n2MXiySEfis,2644
|
|
@@ -55,7 +55,7 @@ flock/core/execution/local_executor.py,sha256=rnIQvaJOs6zZORUcR3vvyS6LPREDJTjayg
|
|
|
55
55
|
flock/core/execution/temporal_executor.py,sha256=dHcb0xuzPFWU_wbwTgI7glLNyyppei93Txs2sapjhaw,6283
|
|
56
56
|
flock/core/interpreter/python_interpreter.py,sha256=RaUMZuufsKBNQ4FAeSaOgUuxzs8VYu5TgUUs-xwaxxM,26376
|
|
57
57
|
flock/core/logging/__init__.py,sha256=xn5fC-8IgsdIv0ywe_cICK1KVhTrVD8t-jYORg0ETUA,155
|
|
58
|
-
flock/core/logging/logging.py,sha256
|
|
58
|
+
flock/core/logging/logging.py,sha256=VyBsin-3q8UQ0DY-K72t8FtrGJQbUwIfzxaC7rIWMvQ,19820
|
|
59
59
|
flock/core/logging/telemetry.py,sha256=Trssqx02SBovTL843YwY3L-ZGj3KvcfMHLMU7Syk8L0,6561
|
|
60
60
|
flock/core/logging/trace_and_logged.py,sha256=5vNrK1kxuPMoPJ0-QjQg-EDJL1oiEzvU6UNi6X8FiMs,2117
|
|
61
61
|
flock/core/logging/formatters/enum_builder.py,sha256=LgEYXUv84wK5vwHflZ5h8HBGgvLH3sByvUQe8tZiyY0,981
|
|
@@ -67,16 +67,16 @@ flock/core/logging/telemetry_exporter/base_exporter.py,sha256=rQJJzS6q9n2aojoSqw
|
|
|
67
67
|
flock/core/logging/telemetry_exporter/file_exporter.py,sha256=nKAjJSZtA7FqHSTuTiFtYYepaxOq7l1rDvs8U8rSBlA,3023
|
|
68
68
|
flock/core/logging/telemetry_exporter/sqlite_exporter.py,sha256=CDsiMb9QcqeXelZ6ZqPSS56ovMPGqOu6whzBZRK__Vg,3498
|
|
69
69
|
flock/core/mcp/__init__.py,sha256=g3hzM_9ntsr-Af9dE9cCZEjQ9YX2jk7-Jm-0JcHSk1A,25
|
|
70
|
-
flock/core/mcp/flock_mcp_server.py,sha256
|
|
71
|
-
flock/core/mcp/flock_mcp_tool_base.py,sha256=
|
|
72
|
-
flock/core/mcp/mcp_client.py,sha256=
|
|
73
|
-
flock/core/mcp/mcp_client_manager.py,sha256=
|
|
74
|
-
flock/core/mcp/mcp_config.py,sha256=
|
|
70
|
+
flock/core/mcp/flock_mcp_server.py,sha256=WgvQDMq5qFj-PzuTXght0uFsztodYEkcIUXQ5TC4Q4M,25852
|
|
71
|
+
flock/core/mcp/flock_mcp_tool_base.py,sha256=ZY6bUJEW3FY0Q5W5vNW0F8RqIovzKZU-X0JrVmK0TuA,6804
|
|
72
|
+
flock/core/mcp/mcp_client.py,sha256=Nf-fC5EtX2egeoqgDx02EIWlwEd6aaNuT1n2DEbnvg0,25934
|
|
73
|
+
flock/core/mcp/mcp_client_manager.py,sha256=hn97F9xEpYNbs02ruEbrtQo4PYD7TNKQAC0AwuAh6xw,8061
|
|
74
|
+
flock/core/mcp/mcp_config.py,sha256=izO07hTD-2CrAhilqF9WDTpHNaK5l1T4UwFn6VsDwYc,16575
|
|
75
75
|
flock/core/mcp/types/__init__.py,sha256=YgEJvTXe5VfSMfJNlpefdBYJOmMbMWQsXzc_qmOAybg,25
|
|
76
|
-
flock/core/mcp/types/callbacks.py,sha256=
|
|
77
|
-
flock/core/mcp/types/factories.py,sha256=
|
|
78
|
-
flock/core/mcp/types/handlers.py,sha256=
|
|
79
|
-
flock/core/mcp/types/types.py,sha256=
|
|
76
|
+
flock/core/mcp/types/callbacks.py,sha256=M4dvL9-PUVmojPTK18fg8ngHqYd7AogMoO6HixM9q10,2494
|
|
77
|
+
flock/core/mcp/types/factories.py,sha256=T4fIyyJYibP8AGg_gjR1Pu5LO5xP5LsAfmBxyD6bBmY,3440
|
|
78
|
+
flock/core/mcp/types/handlers.py,sha256=VEpOx5ShvlvOEvgo2Fs5rql-x0obVQYgEpcb8FBrm24,7788
|
|
79
|
+
flock/core/mcp/types/types.py,sha256=2amE-oastGe1GGVI4gbH2ltCX7QvYnJebSArATvttUU,11410
|
|
80
80
|
flock/core/mcp/util/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
81
|
flock/core/mcp/util/helpers.py,sha256=Xlf4iKW_lZxsVMTRoOnV29JsJfAppfmEJrb6sIcoCH4,636
|
|
82
82
|
flock/core/mixin/dspy_integration.py,sha256=LQN4cfcG6Myi6kX0-2bKCuK1K_k_lu3SNaTdHHk3lEU,17745
|
|
@@ -101,11 +101,13 @@ flock/evaluators/memory/memory_evaluator.py,sha256=ySwz7kcc8suXMJ7gKNSWThW8iOMlE
|
|
|
101
101
|
flock/evaluators/test/test_case_evaluator.py,sha256=3Emcoty0LOLLBIuPGxSpKphuZC9Fu1DTr1vbGg-hd0Q,1233
|
|
102
102
|
flock/evaluators/zep/zep_evaluator.py,sha256=6_5vTdU0yJAH8I8w3-MPXiAZx6iUPhAVCsHjrHzkPLM,2058
|
|
103
103
|
flock/mcp/servers/sse/__init__.py,sha256=r6YtleRSOMJqKhTtKQeFKd3QDaUJVz9R1BGJgOm_PF8,51
|
|
104
|
-
flock/mcp/servers/sse/flock_sse_server.py,sha256=
|
|
104
|
+
flock/mcp/servers/sse/flock_sse_server.py,sha256=YesBrgdbxOsZO6Lgm8EQ8SsDDqhQGkTUPcEuLcqy89A,4980
|
|
105
105
|
flock/mcp/servers/stdio/__init__.py,sha256=36QMguWwHCklLbISNNe1m2cq-y9klAWRf_QnuYpD2aY,53
|
|
106
106
|
flock/mcp/servers/stdio/flock_stdio_server.py,sha256=E78F7iJ6hDyiHREZqNvou5-31NOBRGAYnpeEcRUF5VA,4921
|
|
107
|
+
flock/mcp/servers/streamable_http/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
|
+
flock/mcp/servers/streamable_http/flock_streamable_http_server.py,sha256=3bKxx5zBkVXZIvD9qz31oL1ucsMeEO4kdOpv4S558zo,5818
|
|
107
109
|
flock/mcp/servers/websockets/__init__.py,sha256=KeNgNQRdeCQ9xgpaHB1I0-HyYeBhkifAuZPTIA8eDqM,47
|
|
108
|
-
flock/mcp/servers/websockets/flock_websocket_server.py,sha256=
|
|
110
|
+
flock/mcp/servers/websockets/flock_websocket_server.py,sha256=ntDLKMM20xTGd7k2TbNEK3ToJAF14oyW6vwofNzvqtM,4324
|
|
109
111
|
flock/modules/__init__.py,sha256=Y0cEkx0dujRmy--TDpKoTqFSLzbyFz8BwEOv8kdSUhg,22
|
|
110
112
|
flock/modules/assertion/__init__.py,sha256=Y0cEkx0dujRmy--TDpKoTqFSLzbyFz8BwEOv8kdSUhg,22
|
|
111
113
|
flock/modules/assertion/assertion_module.py,sha256=2p9mIj8yBXRGgfe5pUWYXcLT86Ny13KyWHpRhe0Ehtg,12877
|
|
@@ -558,8 +560,8 @@ flock/workflow/agent_execution_activity.py,sha256=Gy6FtuVAjf0NiUXmC3syS2eJpNQF4R
|
|
|
558
560
|
flock/workflow/flock_workflow.py,sha256=iSUF_soFvWar0ffpkzE4irkDZRx0p4HnwmEBi_Ne2sY,9666
|
|
559
561
|
flock/workflow/temporal_config.py,sha256=3_8O7SDEjMsSMXsWJBfnb6XTp0TFaz39uyzSlMTSF_I,3988
|
|
560
562
|
flock/workflow/temporal_setup.py,sha256=YIHnSBntzOchHfMSh8hoLeNXrz3B1UbR14YrR6soM7A,1606
|
|
561
|
-
flock_core-0.4.
|
|
562
|
-
flock_core-0.4.
|
|
563
|
-
flock_core-0.4.
|
|
564
|
-
flock_core-0.4.
|
|
565
|
-
flock_core-0.4.
|
|
563
|
+
flock_core-0.4.513.dist-info/METADATA,sha256=B1qPt_zjSDR-AT1CZrY4VxbYOa6s6DXdsW2LV_07OsY,22656
|
|
564
|
+
flock_core-0.4.513.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
565
|
+
flock_core-0.4.513.dist-info/entry_points.txt,sha256=rWaS5KSpkTmWySURGFZk6PhbJ87TmvcFQDi2uzjlagQ,37
|
|
566
|
+
flock_core-0.4.513.dist-info/licenses/LICENSE,sha256=iYEqWy0wjULzM9GAERaybP4LBiPeu7Z1NEliLUdJKSc,1072
|
|
567
|
+
flock_core-0.4.513.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|