blaxel 0.2.0rc1__py3-none-any.whl → 0.2.0rc3__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.
blaxel/core/mcp/client.py CHANGED
@@ -7,6 +7,7 @@ import anyio
7
7
  import mcp.types as types
8
8
  from anyio.abc import TaskStatus
9
9
  from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
10
+ from mcp.shared.message import SessionMessage
10
11
  from websockets.asyncio.client import ClientConnection
11
12
  from websockets.asyncio.client import connect as ws_connect
12
13
 
@@ -28,11 +29,11 @@ async def websocket_client(
28
29
 
29
30
  The `timeout` parameter controls connection timeout.
30
31
  """
31
- read_stream: MemoryObjectReceiveStream[types.JSONRPCMessage | Exception]
32
- read_stream_writer: MemoryObjectSendStream[types.JSONRPCMessage | Exception]
32
+ read_stream: MemoryObjectReceiveStream[SessionMessage | Exception]
33
+ read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception]
33
34
 
34
- write_stream: MemoryObjectSendStream[types.JSONRPCMessage]
35
- write_stream_reader: MemoryObjectReceiveStream[types.JSONRPCMessage]
35
+ write_stream: MemoryObjectSendStream[SessionMessage]
36
+ write_stream_reader: MemoryObjectReceiveStream[SessionMessage]
36
37
 
37
38
  read_stream_writer, read_stream = anyio.create_memory_object_stream(0)
38
39
  write_stream, write_stream_reader = anyio.create_memory_object_stream(0)
@@ -64,7 +65,9 @@ async def websocket_client(
64
65
  message
65
66
  )
66
67
  logger.debug(f"Received server message: {parsed_message}")
67
- await read_stream_writer.send(parsed_message)
68
+ await read_stream_writer.send(
69
+ SessionMessage(message=parsed_message)
70
+ )
68
71
  except Exception as exc:
69
72
  logger.error(f"Error parsing server message: {exc}")
70
73
  await read_stream_writer.send(exc)
@@ -77,10 +80,12 @@ async def websocket_client(
77
80
  async def ws_writer(websocket: ClientConnection):
78
81
  try:
79
82
  async with write_stream_reader:
80
- async for message in write_stream_reader:
81
- logger.debug(f"Sending client message: {message}")
83
+ async for session_message in write_stream_reader:
84
+ logger.debug(
85
+ f"Sending client message: {session_message.message}"
86
+ )
82
87
  await websocket.send(
83
- message.model_dump_json(
88
+ session_message.message.model_dump_json(
84
89
  by_alias=True,
85
90
  exclude_none=True,
86
91
  )
blaxel/core/mcp/server.py CHANGED
@@ -2,71 +2,23 @@ import logging
2
2
  import traceback
3
3
  import uuid
4
4
  from contextlib import asynccontextmanager
5
- from typing import Dict, Literal
5
+ from typing import Literal
6
6
 
7
7
  import anyio
8
8
  import mcp.types as types
9
9
  from anyio.streams.memory import MemoryObjectReceiveStream, MemoryObjectSendStream
10
10
  from mcp.server.fastmcp import FastMCP as FastMCPBase
11
+ from mcp.shared.message import SessionMessage
11
12
  from websockets.asyncio.server import ServerConnection, serve
12
13
 
13
- try:
14
- from opentelemetry.trace import Span, StatusCode
15
-
16
- HAS_OPENTELEMETRY = True
17
- except ImportError:
18
- HAS_OPENTELEMETRY = False
19
-
20
- # Create dummy classes for when opentelemetry is not available
21
- class Span:
22
- def set_attributes(self, *args, **kwargs):
23
- pass
24
-
25
- def set_status(self, *args, **kwargs):
26
- pass
27
-
28
- def record_exception(self, *args, **kwargs):
29
- pass
30
-
31
- def end(self, *args, **kwargs):
32
- pass
33
-
34
- def add_event(self, *args, **kwargs):
35
- pass
36
-
37
- def get_span_context(self, *args, **kwargs):
38
- return None
39
-
40
- def is_recording(self, *args, **kwargs):
41
- return False
42
-
43
- def set_attribute(self, *args, **kwargs):
44
- pass
45
-
46
- def update_name(self, *args, **kwargs):
47
- pass
48
-
49
- class StatusCode:
50
- ERROR = "ERROR"
51
-
52
-
53
14
  from ..common.env import env
54
15
 
55
16
  logger = logging.getLogger(__name__)
56
17
 
57
18
 
58
- class DummySpanManager:
59
- """Dummy span manager for when opentelemetry is not available."""
60
-
61
- def create_span(self, name: str, attributes: dict = None):
62
- return Span()
63
-
64
-
65
19
  class BlaxelMcpServerTransport:
66
20
  """WebSocket server transport for MCP."""
67
21
 
68
- spans: Dict[str, Span] = {}
69
-
70
22
  def __init__(self, port: int = 8080):
71
23
  """Initialize the WebSocket server transport.
72
24
 
@@ -80,21 +32,14 @@ class BlaxelMcpServerTransport:
80
32
  self.clients = {}
81
33
  self.server = None
82
34
 
83
- # Initialize span manager
84
- if HAS_OPENTELEMETRY:
85
- # TODO: Implement proper OpenTelemetry span manager when telemetry is available
86
- self.span_manager = DummySpanManager()
87
- else:
88
- self.span_manager = DummySpanManager()
89
-
90
35
  @asynccontextmanager
91
36
  async def websocket_server(self):
92
37
  """Create and run a WebSocket server for MCP communication."""
93
- read_stream: MemoryObjectReceiveStream[types.JSONRPCMessage | Exception]
94
- read_stream_writer: MemoryObjectSendStream[types.JSONRPCMessage | Exception]
38
+ read_stream: MemoryObjectReceiveStream[SessionMessage | Exception]
39
+ read_stream_writer: MemoryObjectSendStream[SessionMessage | Exception]
95
40
 
96
- write_stream: MemoryObjectSendStream[types.JSONRPCMessage]
97
- write_stream_reader: MemoryObjectReceiveStream[types.JSONRPCMessage]
41
+ write_stream: MemoryObjectSendStream[SessionMessage]
42
+ write_stream_reader: MemoryObjectReceiveStream[SessionMessage]
98
43
 
99
44
  read_stream_writer, read_stream = anyio.create_memory_object_stream(0)
100
45
  write_stream, write_stream_reader = anyio.create_memory_object_stream(0)
@@ -106,30 +51,14 @@ class BlaxelMcpServerTransport:
106
51
 
107
52
  try:
108
53
  async for message in websocket:
109
- span = self.span_manager.create_span("message", {"mcp.client.id": client_id})
110
54
  try:
111
55
  msg = types.JSONRPCMessage.model_validate_json(message)
112
56
  # Modify message ID to include client ID
113
57
  if hasattr(msg, "id") and msg.id is not None:
114
58
  original_id = msg.id
115
59
  msg.id = f"{client_id}:{original_id}"
116
- span.set_attributes(
117
- {
118
- "mcp.message.parsed": True,
119
- "mcp.method": getattr(msg, "method", None),
120
- "mcp.messageId": getattr(msg, "id", None),
121
- "mcp.toolName": getattr(
122
- getattr(msg, "params", None), "name", None
123
- ),
124
- "span.type": "mcp.message",
125
- }
126
- )
127
- self.spans[client_id + ":" + msg.id] = span
128
- await read_stream_writer.send(msg)
60
+ await read_stream_writer.send(SessionMessage(message=msg))
129
61
  except Exception as exc:
130
- span.set_status(StatusCode.ERROR)
131
- span.record_exception(exc)
132
- span.end()
133
62
  logger.error(f"Failed to parse message: {exc}\n{traceback.format_exc()}")
134
63
  await read_stream_writer.send(exc)
135
64
  except Exception as e:
@@ -141,11 +70,11 @@ class BlaxelMcpServerTransport:
141
70
 
142
71
  async def message_sender():
143
72
  async with write_stream_reader:
144
- async for message in write_stream_reader:
73
+ async for session_message in write_stream_reader:
145
74
  # Extract client ID from message ID
146
75
  client_id = None
147
76
  msg_id = None
148
-
77
+ message = session_message.message
149
78
  if hasattr(message, "id") and message.id is not None:
150
79
  parts = str(message.id).split(":", 1)
151
80
  if len(parts) == 2:
@@ -158,25 +87,12 @@ class BlaxelMcpServerTransport:
158
87
  if client_id and client_id in self.clients:
159
88
  # Send to specific client
160
89
  websocket = self.clients[client_id]
161
- span = self.spans.get(client_id + ":" + msg_id)
162
90
  try:
163
91
  await websocket.send(data)
164
- if span:
165
- span.set_attributes(
166
- {
167
- "mcp.message.response_sent": True,
168
- }
169
- )
170
92
  except Exception as e:
171
- if span:
172
- span.set_status(StatusCode.ERROR)
173
- span.record_exception(e)
174
93
  logger.error(f"Failed to send message to client {client_id}: {e}")
175
94
  if client_id in self.clients:
176
95
  del self.clients[client_id]
177
- finally:
178
- if span:
179
- span.end()
180
96
  else:
181
97
  # Broadcast to all clients
182
98
  dead_clients = []
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: blaxel
3
- Version: 0.2.0rc1
3
+ Version: 0.2.0rc3
4
4
  Summary: Blaxel - AI development platform SDK
5
5
  Project-URL: Homepage, https://blaxel.ai
6
6
  Project-URL: Documentation, https://docs.blaxel.ai
@@ -11,7 +11,7 @@ License-File: LICENSE
11
11
  Requires-Python: >=3.10
12
12
  Requires-Dist: attrs>=21.3.0
13
13
  Requires-Dist: httpx>=0.27.0
14
- Requires-Dist: mcp<=1.7.1
14
+ Requires-Dist: mcp>=1.9.4
15
15
  Requires-Dist: pydantic>=2.0.0
16
16
  Requires-Dist: pyjwt>=2.0.0
17
17
  Requires-Dist: python-dateutil>=2.8.0
@@ -43,7 +43,7 @@ Requires-Dist: llama-index-llms-groq>=0.3.1; extra == 'all'
43
43
  Requires-Dist: llama-index-llms-mistralai>=0.4.0; extra == 'all'
44
44
  Requires-Dist: llama-index-llms-openai>=0.3.42; extra == 'all'
45
45
  Requires-Dist: llama-index>=0.12.37; extra == 'all'
46
- Requires-Dist: openai-agents>=0.0.7; extra == 'all'
46
+ Requires-Dist: openai-agents>=0.0.14; extra == 'all'
47
47
  Requires-Dist: opentelemetry-exporter-otlp>=1.28.0; extra == 'all'
48
48
  Requires-Dist: opentelemetry-instrumentation-anthropic==0.40.6; extra == 'all'
49
49
  Requires-Dist: opentelemetry-instrumentation-cohere==0.40.6; extra == 'all'
@@ -95,7 +95,7 @@ Requires-Dist: llama-index-llms-openai>=0.3.42; extra == 'llamaindex'
95
95
  Requires-Dist: llama-index>=0.12.37; extra == 'llamaindex'
96
96
  Requires-Dist: opentelemetry-instrumentation-llamaindex>=0.40.7; extra == 'llamaindex'
97
97
  Provides-Extra: openai
98
- Requires-Dist: openai-agents>=0.0.7; extra == 'openai'
98
+ Requires-Dist: openai-agents>=0.0.14; extra == 'openai'
99
99
  Provides-Extra: pydantic
100
100
  Requires-Dist: pydantic-ai>=0.0.48; extra == 'pydantic'
101
101
  Provides-Extra: telemetry
@@ -301,8 +301,8 @@ blaxel/core/common/logger.py,sha256=Jt0MCJgYDPq36rl7UyKRDJH76a-AwYdfggNeNYJt6N0,
301
301
  blaxel/core/common/settings.py,sha256=7KTryuBdud0IfHqykX7xEEtpgq5M5h1Z8YEzYKsHB-Q,2327
302
302
  blaxel/core/jobs/__init__.py,sha256=tApZ6t6Savd5c9yH1RhuiPDGq19B464Fakd-YqCOEtI,5441
303
303
  blaxel/core/mcp/__init__.py,sha256=5VjkiQFb1QWW5QKRgwPHARlxZJ9Xqaz0diJTpM8LLF0,142
304
- blaxel/core/mcp/client.py,sha256=dFjPHirybqA3IMecSvdDss-iU5ferPUaunNrPyhFm8o,5195
305
- blaxel/core/mcp/server.py,sha256=OU1sYcwepnvGtWrxH5IxZdcZfMqMF8hwjvyAzssM6bo,8741
304
+ blaxel/core/mcp/client.py,sha256=aK3wSnsO8DmT1BZqw4eiCMF71Jwvni6Qga0DhPP806Y,5437
305
+ blaxel/core/mcp/server.py,sha256=tXySGZKgK3IllYOzYOecp58BixKBkmAIvQp_4nSM_Ww,5919
306
306
  blaxel/core/models/__init__.py,sha256=HbRDsMnUFHkPC-MMkzPXh4mUqkVjqO6p3j7m00N_XSo,1722
307
307
  blaxel/core/sandbox/__init__.py,sha256=eWTH7PWNQZe9efqParwgXzltc7L4OyPtT_REqCdQybU,551
308
308
  blaxel/core/sandbox/action.py,sha256=9Zjkco7YkLzBThD3N2Hr5SpeEiqU_-Ktk8HlKpkpiAg,2802
@@ -402,7 +402,7 @@ blaxel/telemetry/instrumentation/map.py,sha256=EVCw6ug1hemE-9kh77Vxs9cqr_p9TPzFw
402
402
  blaxel/telemetry/instrumentation/utils.py,sha256=KInMYZH-mu9_wvetmf0EmgrfN3Sw8IWk2Y95v2u90_U,1901
403
403
  blaxel/telemetry/log/log.py,sha256=RvQByRjZMoP_dRaAZu8oK6DTegsHs-xV4W-UIqis6CA,2461
404
404
  blaxel/telemetry/log/logger.py,sha256=NPAS3g82ryROjvc_DEZaTIfrcehoLEZoP-JkLxADxc0,4113
405
- blaxel-0.2.0rc1.dist-info/METADATA,sha256=n61p-dUYa8NGsZdSxAllJkrdiq2PzI1BvlI_UNXPRAQ,9876
406
- blaxel-0.2.0rc1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
407
- blaxel-0.2.0rc1.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
408
- blaxel-0.2.0rc1.dist-info/RECORD,,
405
+ blaxel-0.2.0rc3.dist-info/METADATA,sha256=6uAwLfyFgd98jymj7QVZMz6et4U1oAr3JgqyL0ZcMkQ,9878
406
+ blaxel-0.2.0rc3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
407
+ blaxel-0.2.0rc3.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
408
+ blaxel-0.2.0rc3.dist-info/RECORD,,