chuk-tool-processor 0.6.2__py3-none-any.whl → 0.6.4__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 chuk-tool-processor might be problematic. Click here for more details.

@@ -1,364 +1,426 @@
1
1
  # chuk_tool_processor/mcp/transport/sse_transport.py
2
+ """
3
+ Fixed SSE transport that matches your server's actual behavior.
4
+ Based on your working debug script.
5
+ """
2
6
  from __future__ import annotations
3
7
 
4
8
  import asyncio
5
9
  import json
6
- from typing import Dict, Any, List, Optional
10
+ import uuid
11
+ from typing import Dict, Any, List, Optional, Tuple
7
12
  import logging
8
13
 
9
- from .base_transport import MCPBaseTransport
10
-
11
- # Import latest chuk-mcp SSE transport
12
- try:
13
- from chuk_mcp.transports.sse import sse_client
14
- from chuk_mcp.transports.sse.parameters import SSEParameters
15
- from chuk_mcp.protocol.messages import (
16
- send_initialize,
17
- send_ping,
18
- send_tools_list,
19
- send_tools_call,
20
- )
21
- HAS_SSE_SUPPORT = True
22
- except ImportError:
23
- HAS_SSE_SUPPORT = False
14
+ import httpx
24
15
 
25
- # Import optional resource and prompt support
26
- try:
27
- from chuk_mcp.protocol.messages import (
28
- send_resources_list,
29
- send_resources_read,
30
- send_prompts_list,
31
- send_prompts_get,
32
- )
33
- HAS_RESOURCES_PROMPTS = True
34
- except ImportError:
35
- HAS_RESOURCES_PROMPTS = False
16
+ from .base_transport import MCPBaseTransport
36
17
 
37
18
  logger = logging.getLogger(__name__)
38
19
 
39
20
 
40
21
  class SSETransport(MCPBaseTransport):
41
22
  """
42
- Updated SSE transport using latest chuk-mcp APIs.
43
-
44
- Supports all required abstract methods and provides full MCP functionality.
23
+ SSE transport that works with your server's two-step async pattern:
24
+ 1. POST messages to /messages endpoint
25
+ 2. Receive responses via SSE stream
45
26
  """
46
27
 
47
28
  def __init__(self, url: str, api_key: Optional[str] = None,
48
29
  connection_timeout: float = 30.0, default_timeout: float = 30.0):
49
- """
50
- Initialize SSE transport with latest chuk-mcp.
51
-
52
- Args:
53
- url: SSE server URL
54
- api_key: Optional API key for authentication
55
- connection_timeout: Timeout for initial connection
56
- default_timeout: Default timeout for operations
57
- """
58
- self.url = url
30
+ """Initialize SSE transport."""
31
+ self.url = url.rstrip('/')
59
32
  self.api_key = api_key
60
33
  self.connection_timeout = connection_timeout
61
34
  self.default_timeout = default_timeout
62
35
 
63
- # State tracking
64
- self._sse_context = None
65
- self._read_stream = None
66
- self._write_stream = None
36
+ # State
37
+ self.session_id = None
38
+ self.message_url = None
39
+ self.pending_requests: Dict[str, asyncio.Future] = {}
67
40
  self._initialized = False
68
41
 
69
- if not HAS_SSE_SUPPORT:
70
- logger.warning("SSE transport not available - operations will fail")
42
+ # HTTP clients
43
+ self.stream_client = None
44
+ self.send_client = None
45
+
46
+ # SSE stream
47
+ self.sse_task = None
48
+ self.sse_response = None
49
+ self.sse_stream_context = None
50
+
51
+ def _get_headers(self) -> Dict[str, str]:
52
+ """Get headers with auth if available."""
53
+ headers = {}
54
+ if self.api_key:
55
+ headers['Authorization'] = f'Bearer {self.api_key}'
56
+ return headers
71
57
 
72
58
  async def initialize(self) -> bool:
73
- """Initialize using latest chuk-mcp sse_client."""
74
- if not HAS_SSE_SUPPORT:
75
- logger.error("SSE transport not available in chuk-mcp")
76
- return False
77
-
59
+ """Initialize SSE connection and MCP handshake."""
78
60
  if self._initialized:
79
61
  logger.warning("Transport already initialized")
80
62
  return True
81
-
63
+
82
64
  try:
83
65
  logger.info("Initializing SSE transport...")
84
66
 
85
- # Create SSE parameters for latest chuk-mcp
86
- sse_params = SSEParameters(
87
- url=self.url,
88
- timeout=self.connection_timeout,
89
- auto_reconnect=True,
90
- max_reconnect_attempts=3
91
- )
67
+ # Create HTTP clients
68
+ self.stream_client = httpx.AsyncClient(timeout=self.connection_timeout)
69
+ self.send_client = httpx.AsyncClient(timeout=self.default_timeout)
92
70
 
93
- # Create and enter the context - this should handle the full MCP handshake
94
- self._sse_context = sse_client(sse_params)
71
+ # Connect to SSE stream
72
+ sse_url = f"{self.url}/sse"
73
+ logger.debug(f"Connecting to SSE: {sse_url}")
95
74
 
96
- # The sse_client should handle the entire initialization process
97
- logger.debug("Establishing SSE connection and MCP handshake...")
98
- self._read_stream, self._write_stream = await asyncio.wait_for(
99
- self._sse_context.__aenter__(),
100
- timeout=self.connection_timeout
75
+ self.sse_stream_context = self.stream_client.stream(
76
+ 'GET', sse_url, headers=self._get_headers()
101
77
  )
78
+ self.sse_response = await self.sse_stream_context.__aenter__()
102
79
 
103
- # At this point, chuk-mcp should have already completed the MCP initialization
104
- # Let's verify the connection works with a simple ping
105
- logger.debug("Verifying connection with ping...")
106
- ping_success = await asyncio.wait_for(
107
- send_ping(self._read_stream, self._write_stream),
108
- timeout=5.0
109
- )
80
+ if self.sse_response.status_code != 200:
81
+ logger.error(f"SSE connection failed: {self.sse_response.status_code}")
82
+ return False
83
+
84
+ logger.info("SSE streaming connection established")
85
+
86
+ # Start SSE processing task
87
+ self.sse_task = asyncio.create_task(self._process_sse_stream())
88
+
89
+ # Wait for session discovery
90
+ logger.debug("Waiting for session discovery...")
91
+ for i in range(50): # 5 seconds max
92
+ if self.message_url:
93
+ break
94
+ await asyncio.sleep(0.1)
110
95
 
111
- if ping_success:
96
+ if not self.message_url:
97
+ logger.error("Failed to get session info from SSE")
98
+ return False
99
+
100
+ logger.info(f"Session ready: {self.session_id}")
101
+
102
+ # Now do MCP initialization
103
+ try:
104
+ init_response = await self._send_request("initialize", {
105
+ "protocolVersion": "2024-11-05",
106
+ "capabilities": {},
107
+ "clientInfo": {
108
+ "name": "chuk-tool-processor",
109
+ "version": "1.0.0"
110
+ }
111
+ })
112
+
113
+ if 'error' in init_response:
114
+ logger.error(f"Initialize failed: {init_response['error']}")
115
+ return False
116
+
117
+ # Send initialized notification
118
+ await self._send_notification("notifications/initialized")
119
+
112
120
  self._initialized = True
113
121
  logger.info("SSE transport initialized successfully")
114
122
  return True
115
- else:
116
- logger.warning("SSE connection established but ping failed")
117
- # Still consider it initialized since connection was established
118
- self._initialized = True
119
- return True
120
-
121
- except asyncio.TimeoutError:
122
- logger.error(f"SSE initialization timed out after {self.connection_timeout}s")
123
- logger.error("This may indicate the server is not responding to MCP initialization")
124
- await self._cleanup()
125
- return False
123
+
124
+ except Exception as e:
125
+ logger.error(f"MCP initialization failed: {e}")
126
+ return False
127
+
126
128
  except Exception as e:
127
129
  logger.error(f"Error initializing SSE transport: {e}", exc_info=True)
128
130
  await self._cleanup()
129
131
  return False
130
132
 
131
- async def close(self) -> None:
132
- """Close the SSE transport properly."""
133
- if not self._initialized:
134
- return
135
-
133
+ async def _process_sse_stream(self):
134
+ """Process the persistent SSE stream."""
136
135
  try:
137
- if self._sse_context is not None:
138
- await self._sse_context.__aexit__(None, None, None)
139
- logger.debug("SSE context closed")
136
+ logger.debug("Starting SSE stream processing...")
137
+
138
+ async for line in self.sse_response.aiter_lines():
139
+ line = line.strip()
140
+ if not line:
141
+ continue
142
+
143
+ # Handle session endpoint discovery
144
+ if not self.message_url and line.startswith('data:') and '/messages/' in line:
145
+ endpoint_path = line.split(':', 1)[1].strip()
146
+ self.message_url = f"{self.url}{endpoint_path}"
147
+
148
+ if 'session_id=' in endpoint_path:
149
+ self.session_id = endpoint_path.split('session_id=')[1].split('&')[0]
150
+
151
+ logger.debug(f"Got session info: {self.session_id}")
152
+ continue
140
153
 
154
+ # Handle JSON-RPC responses
155
+ if line.startswith('data:'):
156
+ data_part = line.split(':', 1)[1].strip()
157
+
158
+ # Skip pings and empty data
159
+ if not data_part or data_part.startswith('ping'):
160
+ continue
161
+
162
+ try:
163
+ response_data = json.loads(data_part)
164
+
165
+ if 'jsonrpc' in response_data and 'id' in response_data:
166
+ request_id = str(response_data['id'])
167
+
168
+ # Resolve pending request
169
+ if request_id in self.pending_requests:
170
+ future = self.pending_requests.pop(request_id)
171
+ if not future.done():
172
+ future.set_result(response_data)
173
+ logger.debug(f"Resolved request: {request_id}")
174
+
175
+ except json.JSONDecodeError:
176
+ pass # Not JSON, ignore
177
+
141
178
  except Exception as e:
142
- logger.debug(f"Error during transport close: {e}")
143
- finally:
144
- await self._cleanup()
179
+ logger.error(f"SSE stream error: {e}")
145
180
 
146
- async def _cleanup(self) -> None:
147
- """Clean up internal state."""
148
- self._sse_context = None
149
- self._read_stream = None
150
- self._write_stream = None
151
- self._initialized = False
181
+ async def _send_request(self, method: str, params: Dict[str, Any] = None,
182
+ timeout: Optional[float] = None) -> Dict[str, Any]:
183
+ """Send request and wait for async response."""
184
+ if not self.message_url:
185
+ raise RuntimeError("Not connected")
186
+
187
+ request_id = str(uuid.uuid4())
188
+ message = {
189
+ "jsonrpc": "2.0",
190
+ "id": request_id,
191
+ "method": method,
192
+ "params": params or {}
193
+ }
194
+
195
+ # Create future for response
196
+ future = asyncio.Future()
197
+ self.pending_requests[request_id] = future
198
+
199
+ try:
200
+ # Send message
201
+ headers = {
202
+ 'Content-Type': 'application/json',
203
+ **self._get_headers()
204
+ }
205
+
206
+ response = await self.send_client.post(
207
+ self.message_url,
208
+ headers=headers,
209
+ json=message
210
+ )
211
+
212
+ if response.status_code == 202:
213
+ # Wait for async response
214
+ timeout = timeout or self.default_timeout
215
+ result = await asyncio.wait_for(future, timeout=timeout)
216
+ return result
217
+ elif response.status_code == 200:
218
+ # Immediate response
219
+ self.pending_requests.pop(request_id, None)
220
+ return response.json()
221
+ else:
222
+ self.pending_requests.pop(request_id, None)
223
+ raise RuntimeError(f"Request failed: {response.status_code}")
224
+
225
+ except asyncio.TimeoutError:
226
+ self.pending_requests.pop(request_id, None)
227
+ raise
228
+ except Exception:
229
+ self.pending_requests.pop(request_id, None)
230
+ raise
231
+
232
+ async def _send_notification(self, method: str, params: Dict[str, Any] = None):
233
+ """Send notification (no response expected)."""
234
+ if not self.message_url:
235
+ raise RuntimeError("Not connected")
236
+
237
+ message = {
238
+ "jsonrpc": "2.0",
239
+ "method": method,
240
+ "params": params or {}
241
+ }
242
+
243
+ headers = {
244
+ 'Content-Type': 'application/json',
245
+ **self._get_headers()
246
+ }
247
+
248
+ await self.send_client.post(
249
+ self.message_url,
250
+ headers=headers,
251
+ json=message
252
+ )
152
253
 
153
254
  async def send_ping(self) -> bool:
154
- """Send ping using latest chuk-mcp."""
255
+ """Send ping to check connection."""
155
256
  if not self._initialized:
156
- logger.error("Cannot send ping: transport not initialized")
157
257
  return False
158
258
 
159
259
  try:
160
- result = await asyncio.wait_for(
161
- send_ping(self._read_stream, self._write_stream),
162
- timeout=self.default_timeout
163
- )
164
- logger.debug(f"Ping result: {result}")
165
- return bool(result)
166
- except asyncio.TimeoutError:
167
- logger.error("Ping timed out")
168
- return False
169
- except Exception as e:
170
- logger.error(f"Ping failed: {e}")
260
+ # Your server might not support ping, so we'll just check if we can list tools
261
+ response = await self._send_request("tools/list", {}, timeout=5.0)
262
+ return 'error' not in response
263
+ except Exception:
171
264
  return False
172
265
 
173
266
  async def get_tools(self) -> List[Dict[str, Any]]:
174
- """Get tools list using latest chuk-mcp."""
267
+ """Get tools list."""
175
268
  if not self._initialized:
176
269
  logger.error("Cannot get tools: transport not initialized")
177
270
  return []
178
271
 
179
272
  try:
180
- tools_response = await asyncio.wait_for(
181
- send_tools_list(self._read_stream, self._write_stream),
182
- timeout=self.default_timeout
183
- )
273
+ response = await self._send_request("tools/list", {})
184
274
 
185
- # Normalize response
186
- if isinstance(tools_response, dict):
187
- tools = tools_response.get("tools", [])
188
- elif isinstance(tools_response, list):
189
- tools = tools_response
190
- else:
191
- logger.warning(f"Unexpected tools response type: {type(tools_response)}")
192
- tools = []
275
+ if 'error' in response:
276
+ logger.error(f"Error getting tools: {response['error']}")
277
+ return []
193
278
 
279
+ tools = response.get('result', {}).get('tools', [])
194
280
  logger.debug(f"Retrieved {len(tools)} tools")
195
281
  return tools
196
282
 
197
- except asyncio.TimeoutError:
198
- logger.error("Get tools timed out")
199
- return []
200
283
  except Exception as e:
201
284
  logger.error(f"Error getting tools: {e}")
202
285
  return []
203
286
 
204
287
  async def call_tool(self, tool_name: str, arguments: Dict[str, Any],
205
288
  timeout: Optional[float] = None) -> Dict[str, Any]:
206
- """Call tool using latest chuk-mcp."""
289
+ """Call a tool."""
207
290
  if not self._initialized:
208
291
  return {
209
292
  "isError": True,
210
293
  "error": "Transport not initialized"
211
294
  }
212
295
 
213
- tool_timeout = timeout or self.default_timeout
214
-
215
296
  try:
216
297
  logger.debug(f"Calling tool {tool_name} with args: {arguments}")
217
298
 
218
- raw_response = await asyncio.wait_for(
219
- send_tools_call(
220
- self._read_stream,
221
- self._write_stream,
222
- tool_name,
223
- arguments
224
- ),
225
- timeout=tool_timeout
299
+ response = await self._send_request(
300
+ "tools/call",
301
+ {
302
+ "name": tool_name,
303
+ "arguments": arguments
304
+ },
305
+ timeout=timeout
226
306
  )
227
307
 
228
- logger.debug(f"Tool {tool_name} raw response: {raw_response}")
229
- return self._normalize_tool_response(raw_response)
230
-
308
+ if 'error' in response:
309
+ return {
310
+ "isError": True,
311
+ "error": response['error'].get('message', 'Unknown error')
312
+ }
313
+
314
+ # Extract result
315
+ result = response.get('result', {})
316
+
317
+ # Handle content format
318
+ if 'content' in result:
319
+ content = result['content']
320
+ if isinstance(content, list) and len(content) == 1:
321
+ content_item = content[0]
322
+ if isinstance(content_item, dict) and content_item.get('type') == 'text':
323
+ text_content = content_item.get('text', '')
324
+ try:
325
+ # Try to parse as JSON
326
+ parsed_content = json.loads(text_content)
327
+ return {
328
+ "isError": False,
329
+ "content": parsed_content
330
+ }
331
+ except json.JSONDecodeError:
332
+ return {
333
+ "isError": False,
334
+ "content": text_content
335
+ }
336
+
337
+ return {
338
+ "isError": False,
339
+ "content": content
340
+ }
341
+
342
+ return {
343
+ "isError": False,
344
+ "content": result
345
+ }
346
+
231
347
  except asyncio.TimeoutError:
232
- logger.error(f"Tool {tool_name} timed out after {tool_timeout}s")
233
348
  return {
234
349
  "isError": True,
235
- "error": f"Tool execution timed out after {tool_timeout}s"
350
+ "error": f"Tool execution timed out"
236
351
  }
237
352
  except Exception as e:
238
353
  logger.error(f"Error calling tool {tool_name}: {e}")
239
354
  return {
240
355
  "isError": True,
241
- "error": f"Tool execution failed: {str(e)}"
356
+ "error": str(e)
242
357
  }
243
358
 
244
359
  async def list_resources(self) -> Dict[str, Any]:
245
- """List resources using latest chuk-mcp."""
246
- if not HAS_RESOURCES_PROMPTS:
247
- logger.debug("Resources/prompts not available in chuk-mcp")
248
- return {}
249
-
360
+ """List resources."""
250
361
  if not self._initialized:
251
362
  return {}
252
363
 
253
364
  try:
254
- response = await asyncio.wait_for(
255
- send_resources_list(self._read_stream, self._write_stream),
256
- timeout=self.default_timeout
257
- )
258
- return response if isinstance(response, dict) else {}
259
- except asyncio.TimeoutError:
260
- logger.error("List resources timed out")
261
- return {}
262
- except Exception as e:
263
- logger.debug(f"Error listing resources: {e}")
365
+ response = await self._send_request("resources/list", {}, timeout=10.0)
366
+ if 'error' in response:
367
+ logger.debug(f"Resources not supported: {response['error']}")
368
+ return {}
369
+ return response.get('result', {})
370
+ except Exception:
264
371
  return {}
265
372
 
266
373
  async def list_prompts(self) -> Dict[str, Any]:
267
- """List prompts using latest chuk-mcp."""
268
- if not HAS_RESOURCES_PROMPTS:
269
- logger.debug("Resources/prompts not available in chuk-mcp")
270
- return {}
271
-
374
+ """List prompts."""
272
375
  if not self._initialized:
273
376
  return {}
274
377
 
275
378
  try:
276
- response = await asyncio.wait_for(
277
- send_prompts_list(self._read_stream, self._write_stream),
278
- timeout=self.default_timeout
279
- )
280
- return response if isinstance(response, dict) else {}
281
- except asyncio.TimeoutError:
282
- logger.error("List prompts timed out")
379
+ response = await self._send_request("prompts/list", {}, timeout=10.0)
380
+ if 'error' in response:
381
+ logger.debug(f"Prompts not supported: {response['error']}")
382
+ return {}
383
+ return response.get('result', {})
384
+ except Exception:
283
385
  return {}
284
- except Exception as e:
285
- logger.debug(f"Error listing prompts: {e}")
286
- return {}
287
-
288
- def _normalize_tool_response(self, raw_response: Dict[str, Any]) -> Dict[str, Any]:
289
- """Normalize response for backward compatibility."""
290
- # Handle explicit error in response
291
- if "error" in raw_response:
292
- error_info = raw_response["error"]
293
- if isinstance(error_info, dict):
294
- error_msg = error_info.get("message", "Unknown error")
295
- else:
296
- error_msg = str(error_info)
297
-
298
- return {
299
- "isError": True,
300
- "error": error_msg
301
- }
302
386
 
303
- # Handle successful response with result
304
- if "result" in raw_response:
305
- result = raw_response["result"]
306
-
307
- if isinstance(result, dict) and "content" in result:
308
- return {
309
- "isError": False,
310
- "content": self._extract_content(result["content"])
311
- }
312
- else:
313
- return {
314
- "isError": False,
315
- "content": result
316
- }
317
-
318
- # Handle direct content-based response
319
- if "content" in raw_response:
320
- return {
321
- "isError": False,
322
- "content": self._extract_content(raw_response["content"])
323
- }
324
-
325
- # Fallback
326
- return {
327
- "isError": False,
328
- "content": raw_response
329
- }
387
+ async def close(self) -> None:
388
+ """Close the transport."""
389
+ await self._cleanup()
330
390
 
331
- def _extract_content(self, content_list: Any) -> Any:
332
- """Extract content from MCP content format."""
333
- if not isinstance(content_list, list) or not content_list:
334
- return content_list
391
+ async def _cleanup(self) -> None:
392
+ """Clean up resources."""
393
+ if self.sse_task:
394
+ self.sse_task.cancel()
395
+ try:
396
+ await self.sse_task
397
+ except asyncio.CancelledError:
398
+ pass
335
399
 
336
- # Handle single content item
337
- if len(content_list) == 1:
338
- content_item = content_list[0]
339
- if isinstance(content_item, dict):
340
- if content_item.get("type") == "text":
341
- text_content = content_item.get("text", "")
342
- # Try to parse JSON, fall back to plain text
343
- try:
344
- return json.loads(text_content)
345
- except json.JSONDecodeError:
346
- return text_content
347
- else:
348
- return content_item
400
+ if self.sse_stream_context:
401
+ try:
402
+ await self.sse_stream_context.__aexit__(None, None, None)
403
+ except Exception:
404
+ pass
349
405
 
350
- # Multiple content items
351
- return content_list
406
+ if self.stream_client:
407
+ await self.stream_client.aclose()
408
+
409
+ if self.send_client:
410
+ await self.send_client.aclose()
411
+
412
+ self._initialized = False
413
+ self.session_id = None
414
+ self.message_url = None
415
+ self.pending_requests.clear()
352
416
 
353
417
  def get_streams(self) -> List[tuple]:
354
- """Provide streams for backward compatibility."""
355
- if self._initialized and self._read_stream and self._write_stream:
356
- return [(self._read_stream, self._write_stream)]
418
+ """Not applicable for this transport."""
357
419
  return []
358
420
 
359
421
  def is_connected(self) -> bool:
360
- """Check connection status."""
361
- return self._initialized and self._read_stream is not None and self._write_stream is not None
422
+ """Check if connected."""
423
+ return self._initialized and self.session_id is not None
362
424
 
363
425
  async def __aenter__(self):
364
426
  """Context manager support."""
@@ -372,6 +434,6 @@ class SSETransport(MCPBaseTransport):
372
434
  await self.close()
373
435
 
374
436
  def __repr__(self) -> str:
375
- """String representation for debugging."""
437
+ """String representation."""
376
438
  status = "initialized" if self._initialized else "not initialized"
377
- return f"SSETransport(status={status}, url={self.url})"
439
+ return f"SSETransport(status={status}, url={self.url}, session={self.session_id})"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-tool-processor
3
- Version: 0.6.2
3
+ Version: 0.6.4
4
4
  Summary: Async-native framework for registering, discovering, and executing tools referenced in LLM responses
5
5
  Author-email: CHUK Team <chrishayuk@somejunkmailbox.com>
6
6
  Maintainer-email: CHUK Team <chrishayuk@somejunkmailbox.com>
@@ -20,7 +20,7 @@ Classifier: Framework :: AsyncIO
20
20
  Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.11
22
22
  Description-Content-Type: text/markdown
23
- Requires-Dist: chuk-mcp>=0.5
23
+ Requires-Dist: chuk-mcp>=0.5.1
24
24
  Requires-Dist: dotenv>=0.9.9
25
25
  Requires-Dist: pydantic>=2.11.3
26
26
  Requires-Dist: uuid>=1.30
@@ -26,7 +26,7 @@ chuk_tool_processor/mcp/stream_manager.py,sha256=3JSxoVpvAI0_gZt7Njhp0vgpTnh4mLt
26
26
  chuk_tool_processor/mcp/transport/__init__.py,sha256=0DX7m_VvlXPxijc-88_QTLhq4ZqAgUgzBjSMGL9C_lM,963
27
27
  chuk_tool_processor/mcp/transport/base_transport.py,sha256=bqId34OMQMxzMXtrKq_86sot0_x0NS_ecaIllsCyy6I,3423
28
28
  chuk_tool_processor/mcp/transport/http_streamable_transport.py,sha256=jtjv3RQU7753hV3QV3ZLhzJlP1w9zOy-_hI7OOjEC9A,19067
29
- chuk_tool_processor/mcp/transport/sse_transport.py,sha256=OZjV5LL1o9MZzPvsSNn0z6nn5B2ndA5q2DXluPX-Zm8,13413
29
+ chuk_tool_processor/mcp/transport/sse_transport.py,sha256=BiIQBQUpU5XGdISiPZ_fWvsD54cv2wtFGQ6V9EEpeRM,15571
30
30
  chuk_tool_processor/mcp/transport/stdio_transport.py,sha256=QEpaGufkYmebrUZJMXHM-Q-Kj8TkkagorgUEqT17GwM,9095
31
31
  chuk_tool_processor/models/__init__.py,sha256=TC__rdVa0lQsmJHM_hbLDPRgToa_pQT_UxRcPZk6iVw,40
32
32
  chuk_tool_processor/models/execution_strategy.py,sha256=UVW35YIeMY2B3mpIKZD2rAkyOPayI6ckOOUALyf0YiQ,2115
@@ -54,7 +54,7 @@ chuk_tool_processor/registry/providers/__init__.py,sha256=eigwG_So11j7WbDGSWaKd3
54
54
  chuk_tool_processor/registry/providers/memory.py,sha256=6cMtUwLO6zrk3pguQRgxJ2CReHAzewgZsizWZhsoStk,5184
55
55
  chuk_tool_processor/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  chuk_tool_processor/utils/validation.py,sha256=V5N1dH9sJlHepFIbiI2k2MU82o7nvnh0hKyIt2jdgww,4136
57
- chuk_tool_processor-0.6.2.dist-info/METADATA,sha256=yBRgNT_nMIqMIUnPffD7Yed4awpMji4skCdZ25IsKYQ,23461
58
- chuk_tool_processor-0.6.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
- chuk_tool_processor-0.6.2.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
60
- chuk_tool_processor-0.6.2.dist-info/RECORD,,
57
+ chuk_tool_processor-0.6.4.dist-info/METADATA,sha256=FHCcpjTWntOR3n5HMq_t2IiI49CfXQAvfCckDp_SWZU,23463
58
+ chuk_tool_processor-0.6.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
+ chuk_tool_processor-0.6.4.dist-info/top_level.txt,sha256=7lTsnuRx4cOW4U2sNJWNxl4ZTt_J1ndkjTbj3pHPY5M,20
60
+ chuk_tool_processor-0.6.4.dist-info/RECORD,,