chuk-tool-processor 0.6.3__tar.gz → 0.6.5__tar.gz

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.

Files changed (66) hide show
  1. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/PKG-INFO +2 -2
  2. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/pyproject.toml +2 -2
  3. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/logging/helpers.py +6 -6
  4. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/register_mcp_tools.py +5 -5
  5. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/setup_mcp_http_streamable.py +2 -2
  6. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/setup_mcp_sse.py +2 -2
  7. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/setup_mcp_stdio.py +2 -2
  8. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/stream_manager.py +30 -30
  9. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/transport/http_streamable_transport.py +23 -22
  10. chuk_tool_processor-0.6.5/src/chuk_tool_processor/mcp/transport/sse_transport.py +439 -0
  11. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/transport/stdio_transport.py +4 -4
  12. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor.egg-info/PKG-INFO +2 -2
  13. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor.egg-info/requires.txt +1 -1
  14. chuk_tool_processor-0.6.3/src/chuk_tool_processor/mcp/transport/sse_transport.py +0 -377
  15. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/README.md +0 -0
  16. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/setup.cfg +0 -0
  17. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/__init__.py +0 -0
  18. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/core/__init__.py +0 -0
  19. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/core/exceptions.py +0 -0
  20. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/core/processor.py +0 -0
  21. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/__init__.py +0 -0
  22. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/strategies/__init__.py +0 -0
  23. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/strategies/inprocess_strategy.py +0 -0
  24. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/strategies/subprocess_strategy.py +0 -0
  25. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/tool_executor.py +0 -0
  26. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/wrappers/__init__.py +0 -0
  27. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/wrappers/caching.py +0 -0
  28. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/wrappers/rate_limiting.py +0 -0
  29. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/execution/wrappers/retry.py +0 -0
  30. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/logging/__init__.py +0 -0
  31. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/logging/context.py +0 -0
  32. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/logging/formatter.py +0 -0
  33. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/logging/metrics.py +0 -0
  34. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/__init__.py +0 -0
  35. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/mcp_tool.py +0 -0
  36. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/transport/__init__.py +0 -0
  37. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/mcp/transport/base_transport.py +0 -0
  38. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/__init__.py +0 -0
  39. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/execution_strategy.py +0 -0
  40. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/streaming_tool.py +0 -0
  41. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/tool_call.py +0 -0
  42. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/tool_export_mixin.py +0 -0
  43. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/tool_result.py +0 -0
  44. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/models/validated_tool.py +0 -0
  45. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/__init__.py +0 -0
  46. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/discovery.py +0 -0
  47. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/__init__.py +0 -0
  48. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/base.py +0 -0
  49. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/function_call_tool.py +0 -0
  50. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/json_tool.py +0 -0
  51. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/openai_tool.py +0 -0
  52. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/plugins/parsers/xml_tool.py +0 -0
  53. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/__init__.py +0 -0
  54. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/auto_register.py +0 -0
  55. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/decorators.py +0 -0
  56. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/interface.py +0 -0
  57. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/metadata.py +0 -0
  58. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/provider.py +0 -0
  59. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/providers/__init__.py +0 -0
  60. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/providers/memory.py +0 -0
  61. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/registry/tool_export.py +0 -0
  62. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/utils/__init__.py +0 -0
  63. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor/utils/validation.py +0 -0
  64. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor.egg-info/SOURCES.txt +0 -0
  65. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor.egg-info/dependency_links.txt +0 -0
  66. {chuk_tool_processor-0.6.3 → chuk_tool_processor-0.6.5}/src/chuk_tool_processor.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: chuk-tool-processor
3
- Version: 0.6.3
3
+ Version: 0.6.5
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.2
24
24
  Requires-Dist: dotenv>=0.9.9
25
25
  Requires-Dist: pydantic>=2.11.3
26
26
  Requires-Dist: uuid>=1.30
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "chuk-tool-processor"
7
- version = "0.6.3"
7
+ version = "0.6.5"
8
8
  description = "Async-native framework for registering, discovering, and executing tools referenced in LLM responses"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -41,7 +41,7 @@ classifiers = [
41
41
  "Typing :: Typed",
42
42
  ]
43
43
  dependencies = [
44
- "chuk-mcp>=0.5",
44
+ "chuk-mcp>=0.5.2",
45
45
  "dotenv>=0.9.9",
46
46
  "pydantic>=2.11.3",
47
47
  "uuid>=1.30",
@@ -58,15 +58,15 @@ async def log_context_span(
58
58
  prev = log_context.get_copy()
59
59
  log_context.update(span_ctx)
60
60
 
61
- logger.info("Starting %s", operation)
61
+ logger.debug("Starting %s", operation)
62
62
  try:
63
63
  yield
64
64
  if log_duration:
65
- logger.info(
65
+ logger.debug(
66
66
  "Completed %s", operation, extra={"context": {"duration": time.time() - start}}
67
67
  )
68
68
  else:
69
- logger.info("Completed %s", operation)
69
+ logger.debug("Completed %s", operation)
70
70
  except Exception as exc:
71
71
  logger.exception(
72
72
  "Error in %s: %s", operation, exc, extra={"context": {"duration": time.time() - start}}
@@ -97,10 +97,10 @@ async def request_logging(
97
97
  logger = get_logger("chuk_tool_processor.request")
98
98
  request_id = log_context.start_request(request_id)
99
99
  start = time.time()
100
- logger.info("Starting request %s", request_id)
100
+ logger.debug("Starting request %s", request_id)
101
101
  try:
102
102
  yield request_id
103
- logger.info(
103
+ logger.debug(
104
104
  "Completed request %s",
105
105
  request_id,
106
106
  extra={"context": {"duration": time.time() - start}},
@@ -184,4 +184,4 @@ async def log_tool_call(tool_call: Any, tool_result: Any) -> None:
184
184
  if tool_result.error:
185
185
  logger.error("Tool %s failed: %s", tool_call.tool, tool_result.error, extra={"context": ctx})
186
186
  else:
187
- logger.info("Tool %s succeeded in %.3fs", tool_call.tool, dur, extra={"context": ctx})
187
+ logger.debug("Tool %s succeeded in %.3fs", tool_call.tool, dur, extra={"context": ctx})
@@ -95,7 +95,7 @@ async def register_mcp_tools(
95
95
  except Exception as exc:
96
96
  logger.error("Failed to register MCP tool '%s': %s", tool_name, exc)
97
97
 
98
- logger.info("MCP registration complete - %d tool(s) available", len(registered))
98
+ logger.debug("MCP registration complete - %d tool(s) available", len(registered))
99
99
  return registered
100
100
 
101
101
 
@@ -134,14 +134,14 @@ async def update_mcp_tools_stream_manager(
134
134
  if tool and hasattr(tool, 'set_stream_manager'):
135
135
  tool.set_stream_manager(new_stream_manager)
136
136
  updated_count += 1
137
- logger.debug(f"Updated StreamManager for tool '{namespace}:{tool_name}'")
137
+ logger.debug("Updated StreamManager for tool '%s:%s'", namespace, tool_name)
138
138
  except Exception as e:
139
- logger.warning(f"Failed to update StreamManager for tool '{namespace}:{tool_name}': {e}")
139
+ logger.warning("Failed to update StreamManager for tool '%s:%s': %s", namespace, tool_name, e)
140
140
 
141
141
  action = "connected" if new_stream_manager else "disconnected"
142
- logger.info(f"StreamManager {action} for {updated_count} tools in namespace '{namespace}'")
142
+ logger.debug("StreamManager %s for %d tools in namespace '%s'", action, updated_count, namespace)
143
143
 
144
144
  except Exception as e:
145
- logger.error(f"Failed to update tools in namespace '{namespace}': {e}")
145
+ logger.error("Failed to update tools in namespace '%s': %s", namespace, e)
146
146
 
147
147
  return updated_count
@@ -110,8 +110,8 @@ async def setup_mcp_http_streamable(
110
110
  max_retries=max_retries,
111
111
  )
112
112
 
113
- logger.info(
114
- "MCP (HTTP Streamable) initialised - %s tool%s registered into namespace '%s'",
113
+ logger.debug(
114
+ "MCP (HTTP Streamable) initialised - %d tool%s registered into namespace '%s'",
115
115
  len(registered),
116
116
  "" if len(registered) == 1 else "s",
117
117
  namespace,
@@ -89,8 +89,8 @@ async def setup_mcp_sse( # noqa: C901 - long but just a config facade
89
89
  max_retries=max_retries,
90
90
  )
91
91
 
92
- logger.info(
93
- "MCP (SSE) initialised - %s tool%s registered into namespace '%s'",
92
+ logger.debug(
93
+ "MCP (SSE) initialised - %d tool%s registered into namespace '%s'",
94
94
  len(registered),
95
95
  "" if len(registered) == 1 else "s",
96
96
  namespace,
@@ -73,8 +73,8 @@ async def setup_mcp_stdio( # noqa: C901 - long but just a config facade
73
73
  max_retries=max_retries,
74
74
  )
75
75
 
76
- logger.info(
77
- "MCP (stdio) initialised - %s tool%s registered into namespace '%s'",
76
+ logger.debug(
77
+ "MCP (stdio) initialised - %d tool%s registered into namespace '%s'",
78
78
  len(registered),
79
79
  "" if len(registered) == 1 else "s",
80
80
  namespace,
@@ -73,7 +73,7 @@ class StreamManager:
73
73
  )
74
74
  return inst
75
75
  except asyncio.TimeoutError:
76
- logger.error(f"StreamManager initialization timed out after {initialization_timeout}s")
76
+ logger.error("StreamManager initialization timed out after %ss", initialization_timeout)
77
77
  raise RuntimeError(f"StreamManager initialization timed out after {initialization_timeout}s")
78
78
 
79
79
  @classmethod
@@ -99,7 +99,7 @@ class StreamManager:
99
99
  )
100
100
  return inst
101
101
  except asyncio.TimeoutError:
102
- logger.error(f"SSE StreamManager initialization timed out after {initialization_timeout}s")
102
+ logger.error("SSE StreamManager initialization timed out after %ss", initialization_timeout)
103
103
  raise RuntimeError(f"SSE StreamManager initialization timed out after {initialization_timeout}s")
104
104
 
105
105
  @classmethod
@@ -125,7 +125,7 @@ class StreamManager:
125
125
  )
126
126
  return inst
127
127
  except asyncio.TimeoutError:
128
- logger.error(f"HTTP Streamable StreamManager initialization timed out after {initialization_timeout}s")
128
+ logger.error("HTTP Streamable StreamManager initialization timed out after %ss", initialization_timeout)
129
129
  raise RuntimeError(f"HTTP Streamable StreamManager initialization timed out after {initialization_timeout}s")
130
130
 
131
131
  # ------------------------------------------------------------------ #
@@ -196,7 +196,7 @@ class StreamManager:
196
196
  else:
197
197
  sse_url = "http://localhost:8000"
198
198
  api_key = None
199
- logger.warning(f"No URL configured for SSE transport, using default: {sse_url}")
199
+ logger.warning("No URL configured for SSE transport, using default: %s", sse_url)
200
200
 
201
201
  transport = SSETransport(
202
202
  sse_url,
@@ -215,7 +215,7 @@ class StreamManager:
215
215
  http_url = "http://localhost:8000"
216
216
  api_key = None
217
217
  session_id = None
218
- logger.warning(f"No URL configured for HTTP Streamable transport, using default: {http_url}")
218
+ logger.warning("No URL configured for HTTP Streamable transport, using default: %s", http_url)
219
219
 
220
220
  transport = HTTPStreamableTransport(
221
221
  http_url,
@@ -252,13 +252,13 @@ class StreamManager:
252
252
  "status": status,
253
253
  }
254
254
  )
255
- logger.info("Initialised %s - %d tool(s)", server_name, len(tools))
255
+ logger.debug("Initialised %s - %d tool(s)", server_name, len(tools))
256
256
  except asyncio.TimeoutError:
257
257
  logger.error("Timeout initialising %s", server_name)
258
258
  except Exception as exc:
259
259
  logger.error("Error initialising %s: %s", server_name, exc)
260
260
 
261
- logger.info(
261
+ logger.debug(
262
262
  "StreamManager ready - %d server(s), %d tool(s)",
263
263
  len(self.transports),
264
264
  len(self.all_tools),
@@ -307,13 +307,13 @@ class StreamManager:
307
307
  self.server_info.append(
308
308
  {"id": idx, "name": name, "tools": len(tools), "status": status}
309
309
  )
310
- logger.info("Initialised SSE %s - %d tool(s)", name, len(tools))
310
+ logger.debug("Initialised SSE %s - %d tool(s)", name, len(tools))
311
311
  except asyncio.TimeoutError:
312
312
  logger.error("Timeout initialising SSE %s", name)
313
313
  except Exception as exc:
314
314
  logger.error("Error initialising SSE %s: %s", name, exc)
315
315
 
316
- logger.info(
316
+ logger.debug(
317
317
  "StreamManager ready - %d SSE server(s), %d tool(s)",
318
318
  len(self.transports),
319
319
  len(self.all_tools),
@@ -364,13 +364,13 @@ class StreamManager:
364
364
  self.server_info.append(
365
365
  {"id": idx, "name": name, "tools": len(tools), "status": status}
366
366
  )
367
- logger.info("Initialised HTTP Streamable %s - %d tool(s)", name, len(tools))
367
+ logger.debug("Initialised HTTP Streamable %s - %d tool(s)", name, len(tools))
368
368
  except asyncio.TimeoutError:
369
369
  logger.error("Timeout initialising HTTP Streamable %s", name)
370
370
  except Exception as exc:
371
371
  logger.error("Error initialising HTTP Streamable %s: %s", name, exc)
372
372
 
373
- logger.info(
373
+ logger.debug(
374
374
  "StreamManager ready - %d HTTP Streamable server(s), %d tool(s)",
375
375
  len(self.transports),
376
376
  len(self.all_tools),
@@ -395,20 +395,20 @@ class StreamManager:
395
395
  return []
396
396
 
397
397
  if server_name not in self.transports:
398
- logger.error(f"Server '{server_name}' not found in transports")
398
+ logger.error("Server '%s' not found in transports", server_name)
399
399
  return []
400
400
 
401
401
  transport = self.transports[server_name]
402
402
 
403
403
  try:
404
404
  tools = await asyncio.wait_for(transport.get_tools(), timeout=10.0)
405
- logger.debug(f"Found {len(tools)} tools for server {server_name}")
405
+ logger.debug("Found %d tools for server %s", len(tools), server_name)
406
406
  return tools
407
407
  except asyncio.TimeoutError:
408
- logger.error(f"Timeout listing tools for server {server_name}")
408
+ logger.error("Timeout listing tools for server %s", server_name)
409
409
  return []
410
410
  except Exception as e:
411
- logger.error(f"Error listing tools for server {server_name}: {e}")
411
+ logger.error("Error listing tools for server %s: %s", server_name, e)
412
412
  return []
413
413
 
414
414
  # ------------------------------------------------------------------ #
@@ -541,7 +541,7 @@ class StreamManager:
541
541
  self._closed = True
542
542
  return
543
543
 
544
- logger.debug(f"Closing {len(self.transports)} transports...")
544
+ logger.debug("Closing %d transports...", len(self.transports))
545
545
 
546
546
  try:
547
547
  # Use shield to protect the cleanup operation from cancellation
@@ -551,7 +551,7 @@ class StreamManager:
551
551
  logger.debug("Close operation cancelled, performing synchronous cleanup")
552
552
  self._sync_cleanup()
553
553
  except Exception as e:
554
- logger.debug(f"Error during close: {e}")
554
+ logger.debug("Error during close: %s", e)
555
555
  self._sync_cleanup()
556
556
  finally:
557
557
  self._closed = True
@@ -565,7 +565,7 @@ class StreamManager:
565
565
  try:
566
566
  await self._concurrent_close(transport_items, close_results)
567
567
  except Exception as e:
568
- logger.debug(f"Concurrent close failed: {e}, falling back to sequential close")
568
+ logger.debug("Concurrent close failed: %s, falling back to sequential close", e)
569
569
  # Strategy 2: Fall back to sequential close
570
570
  await self._sequential_close(transport_items, close_results)
571
571
 
@@ -575,7 +575,7 @@ class StreamManager:
575
575
  # Log summary
576
576
  if close_results:
577
577
  successful_closes = sum(1 for _, success, _ in close_results if success)
578
- logger.debug(f"Transport cleanup: {successful_closes}/{len(close_results)} closed successfully")
578
+ logger.debug("Transport cleanup: %d/%d closed successfully", successful_closes, len(close_results))
579
579
 
580
580
  async def _concurrent_close(self, transport_items: List[Tuple[str, MCPBaseTransport]], close_results: List) -> None:
581
581
  """Try to close all transports concurrently."""
@@ -602,10 +602,10 @@ class StreamManager:
602
602
  for i, (name, _) in enumerate(close_tasks):
603
603
  result = results[i] if i < len(results) else None
604
604
  if isinstance(result, Exception):
605
- logger.debug(f"Transport {name} close failed: {result}")
605
+ logger.debug("Transport %s close failed: %s", name, result)
606
606
  close_results.append((name, False, str(result)))
607
607
  else:
608
- logger.debug(f"Transport {name} closed successfully")
608
+ logger.debug("Transport %s closed successfully", name)
609
609
  close_results.append((name, True, None))
610
610
 
611
611
  except asyncio.TimeoutError:
@@ -632,16 +632,16 @@ class StreamManager:
632
632
  self._close_single_transport(name, transport),
633
633
  timeout=0.5 # Short timeout per transport
634
634
  )
635
- logger.debug(f"Closed transport: {name}")
635
+ logger.debug("Closed transport: %s", name)
636
636
  close_results.append((name, True, None))
637
637
  except asyncio.TimeoutError:
638
- logger.debug(f"Transport {name} close timed out (normal during shutdown)")
638
+ logger.debug("Transport %s close timed out (normal during shutdown)", name)
639
639
  close_results.append((name, False, "timeout"))
640
640
  except asyncio.CancelledError:
641
- logger.debug(f"Transport {name} close cancelled during event loop shutdown")
641
+ logger.debug("Transport %s close cancelled during event loop shutdown", name)
642
642
  close_results.append((name, False, "cancelled"))
643
643
  except Exception as e:
644
- logger.debug(f"Error closing transport {name}: {e}")
644
+ logger.debug("Error closing transport %s: %s", name, e)
645
645
  close_results.append((name, False, str(e)))
646
646
 
647
647
  async def _close_single_transport(self, name: str, transport: MCPBaseTransport) -> None:
@@ -650,9 +650,9 @@ class StreamManager:
650
650
  if hasattr(transport, 'close') and callable(transport.close):
651
651
  await transport.close()
652
652
  else:
653
- logger.debug(f"Transport {name} has no close method")
653
+ logger.debug("Transport %s has no close method", name)
654
654
  except Exception as e:
655
- logger.debug(f"Error closing transport {name}: {e}")
655
+ logger.debug("Error closing transport %s: %s", name, e)
656
656
  raise
657
657
 
658
658
  def _sync_cleanup(self) -> None:
@@ -660,9 +660,9 @@ class StreamManager:
660
660
  try:
661
661
  transport_count = len(self.transports)
662
662
  self._cleanup_state()
663
- logger.debug(f"Synchronous cleanup completed for {transport_count} transports")
663
+ logger.debug("Synchronous cleanup completed for %d transports", transport_count)
664
664
  except Exception as e:
665
- logger.debug(f"Error during synchronous cleanup: {e}")
665
+ logger.debug("Error during synchronous cleanup: %s", e)
666
666
 
667
667
  def _cleanup_state(self) -> None:
668
668
  """Clean up internal state synchronously."""
@@ -673,7 +673,7 @@ class StreamManager:
673
673
  self.all_tools.clear()
674
674
  self.server_names.clear()
675
675
  except Exception as e:
676
- logger.debug(f"Error during state cleanup: {e}")
676
+ logger.debug("Error during state cleanup: %s", e)
677
677
 
678
678
  # ------------------------------------------------------------------ #
679
679
  # backwards-compat: streams helper #
@@ -107,7 +107,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
107
107
  start_time = time.time()
108
108
 
109
109
  try:
110
- logger.info(f"Initializing HTTP Streamable transport to {self.url}")
110
+ logger.debug("Initializing HTTP Streamable transport to %s", self.url)
111
111
 
112
112
  # Create HTTP parameters for chuk-mcp (following SSE pattern)
113
113
  headers = {}
@@ -117,7 +117,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
117
117
 
118
118
  if self.session_id:
119
119
  headers["X-Session-ID"] = self.session_id
120
- logger.debug(f"Using session ID: {self.session_id}")
120
+ logger.debug("Using session ID: %s", self.session_id)
121
121
 
122
122
  http_params = StreamableHTTPParameters(
123
123
  url=self.url,
@@ -154,7 +154,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
154
154
  self._metrics["initialization_time"] = init_time
155
155
  self._metrics["last_ping_time"] = ping_time
156
156
 
157
- logger.info(f"HTTP Streamable transport initialized successfully in {init_time:.3f}s (ping: {ping_time:.3f}s)")
157
+ logger.debug("HTTP Streamable transport initialized successfully in %.3fs (ping: %.3fs)", init_time, ping_time)
158
158
  return True
159
159
  else:
160
160
  logger.warning("HTTP connection established but ping failed")
@@ -164,12 +164,12 @@ class HTTPStreamableTransport(MCPBaseTransport):
164
164
  return True
165
165
 
166
166
  except asyncio.TimeoutError:
167
- logger.error(f"HTTP Streamable initialization timed out after {self.connection_timeout}s")
167
+ logger.error("HTTP Streamable initialization timed out after %ss", self.connection_timeout)
168
168
  logger.error("This may indicate the server is not responding to MCP initialization")
169
169
  await self._cleanup()
170
170
  return False
171
171
  except Exception as e:
172
- logger.error(f"Error initializing HTTP Streamable transport: {e}", exc_info=True)
172
+ logger.error("Error initializing HTTP Streamable transport: %s", e, exc_info=True)
173
173
  await self._cleanup()
174
174
  return False
175
175
 
@@ -180,10 +180,11 @@ class HTTPStreamableTransport(MCPBaseTransport):
180
180
 
181
181
  # Log final metrics (enhanced from SSE)
182
182
  if self.enable_metrics and self._metrics["total_calls"] > 0:
183
- logger.info(
184
- f"HTTP Streamable transport closing - Total calls: {self._metrics['total_calls']}, "
185
- f"Success rate: {(self._metrics['successful_calls']/self._metrics['total_calls']*100):.1f}%, "
186
- f"Avg response time: {self._metrics['avg_response_time']:.3f}s"
183
+ logger.debug(
184
+ "HTTP Streamable transport closing - Total calls: %d, Success rate: %.1f%%, Avg response time: %.3fs",
185
+ self._metrics["total_calls"],
186
+ (self._metrics["successful_calls"] / self._metrics["total_calls"] * 100),
187
+ self._metrics["avg_response_time"]
187
188
  )
188
189
 
189
190
  try:
@@ -192,7 +193,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
192
193
  logger.debug("HTTP Streamable context closed")
193
194
 
194
195
  except Exception as e:
195
- logger.debug(f"Error during transport close: {e}")
196
+ logger.debug("Error during transport close: %s", e)
196
197
  finally:
197
198
  await self._cleanup()
198
199
 
@@ -219,14 +220,14 @@ class HTTPStreamableTransport(MCPBaseTransport):
219
220
  if self.enable_metrics:
220
221
  ping_time = time.time() - start_time
221
222
  self._metrics["last_ping_time"] = ping_time
222
- logger.debug(f"Ping completed in {ping_time:.3f}s: {result}")
223
+ logger.debug("Ping completed in %.3fs: %s", ping_time, result)
223
224
 
224
225
  return bool(result)
225
226
  except asyncio.TimeoutError:
226
227
  logger.error("Ping timed out")
227
228
  return False
228
229
  except Exception as e:
229
- logger.error(f"Ping failed: {e}")
230
+ logger.error("Ping failed: %s", e)
230
231
  return False
231
232
 
232
233
  async def get_tools(self) -> List[Dict[str, Any]]:
@@ -248,12 +249,12 @@ class HTTPStreamableTransport(MCPBaseTransport):
248
249
  elif isinstance(tools_response, list):
249
250
  tools = tools_response
250
251
  else:
251
- logger.warning(f"Unexpected tools response type: {type(tools_response)}")
252
+ logger.warning("Unexpected tools response type: %s", type(tools_response))
252
253
  tools = []
253
254
 
254
255
  if self.enable_metrics:
255
256
  response_time = time.time() - start_time
256
- logger.debug(f"Retrieved {len(tools)} tools in {response_time:.3f}s")
257
+ logger.debug("Retrieved %d tools in %.3fs", len(tools), response_time)
257
258
 
258
259
  return tools
259
260
 
@@ -261,7 +262,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
261
262
  logger.error("Get tools timed out")
262
263
  return []
263
264
  except Exception as e:
264
- logger.error(f"Error getting tools: {e}")
265
+ logger.error("Error getting tools: %s", e)
265
266
  return []
266
267
 
267
268
  async def call_tool(self, tool_name: str, arguments: Dict[str, Any],
@@ -280,7 +281,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
280
281
  self._metrics["total_calls"] += 1
281
282
 
282
283
  try:
283
- logger.debug(f"Calling tool '{tool_name}' with timeout {tool_timeout}s")
284
+ logger.debug("Calling tool '%s' with timeout %ss", tool_name, tool_timeout)
284
285
 
285
286
  raw_response = await asyncio.wait_for(
286
287
  send_tools_call(
@@ -299,9 +300,9 @@ class HTTPStreamableTransport(MCPBaseTransport):
299
300
  self._update_metrics(response_time, not result.get("isError", False))
300
301
 
301
302
  if not result.get("isError", False):
302
- logger.debug(f"Tool '{tool_name}' completed successfully in {response_time:.3f}s")
303
+ logger.debug("Tool '%s' completed successfully in %.3fs", tool_name, response_time)
303
304
  else:
304
- logger.warning(f"Tool '{tool_name}' failed in {response_time:.3f}s: {result.get('error', 'Unknown error')}")
305
+ logger.warning("Tool '%s' failed in %.3fs: %s", tool_name, response_time, result.get('error', 'Unknown error'))
305
306
 
306
307
  return result
307
308
 
@@ -311,7 +312,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
311
312
  self._update_metrics(response_time, False)
312
313
 
313
314
  error_msg = f"Tool execution timed out after {tool_timeout}s"
314
- logger.error(f"Tool '{tool_name}' {error_msg}")
315
+ logger.error("Tool '%s' %s", tool_name, error_msg)
315
316
  return {
316
317
  "isError": True,
317
318
  "error": error_msg
@@ -322,7 +323,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
322
323
  self._update_metrics(response_time, False)
323
324
 
324
325
  error_msg = f"Tool execution failed: {str(e)}"
325
- logger.error(f"Tool '{tool_name}' error: {error_msg}")
326
+ logger.error("Tool '%s' error: %s", tool_name, error_msg)
326
327
  return {
327
328
  "isError": True,
328
329
  "error": error_msg
@@ -359,7 +360,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
359
360
  logger.error("List resources timed out")
360
361
  return {}
361
362
  except Exception as e:
362
- logger.debug(f"Error listing resources: {e}")
363
+ logger.debug("Error listing resources: %s", e)
363
364
  return {}
364
365
 
365
366
  async def list_prompts(self) -> Dict[str, Any]:
@@ -381,7 +382,7 @@ class HTTPStreamableTransport(MCPBaseTransport):
381
382
  logger.error("List prompts timed out")
382
383
  return {}
383
384
  except Exception as e:
384
- logger.debug(f"Error listing prompts: {e}")
385
+ logger.debug("Error listing prompts: %s", e)
385
386
  return {}
386
387
 
387
388
  def _normalize_tool_response(self, raw_response: Dict[str, Any]) -> Dict[str, Any]: